Skip to content

Commit

Permalink
fix: ocitar image scope
Browse files Browse the repository at this point in the history
  • Loading branch information
morlay committed May 20, 2024
1 parent 1a94605 commit 8cf6d3f
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 25 deletions.
4 changes: 4 additions & 0 deletions pkg/artifact/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ type artifactImage struct {
m atomic.Pointer[specv1.Manifest]
}

func (img *artifactImage) ArtifactType() (string, error) {
return img.config.ArtifactType()
}

func (img *artifactImage) MediaType() (types.MediaType, error) {
return types.OCIManifestSchema1, nil
}
Expand Down
28 changes: 28 additions & 0 deletions pkg/kubepkg/packer.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,16 @@ func (p *Packer) PackAsKubePkgImage(ctx context.Context, kpkg *kubepkgv1alpha1.K
}
})

if len(p.Platforms) == 0 {
for image := range workloadImages {
if len(p.Platforms) == 0 {
p.Platforms = image.Platforms
} else if len(image.Platforms) > 0 {
p.Platforms = intersection(p.Platforms, image.Platforms)
}
}
}

var kubepkgImage v1.Image = empty.Image

for image := range workloadImages {
Expand Down Expand Up @@ -306,3 +316,21 @@ func (p *Packer) ImageName(repoName name.Repository) (name string) {
}
return repoName.String()
}

func intersection[E comparable](a []E, b []E) (c []E) {
includes := map[E]bool{}
for i := range a {
includes[a[i]] = true
}

c = make([]E, 0, len(a)+len(b))
for i := range b {
x := b[i]

if _, ok := includes[x]; ok {
c = append(c, x)
}
}

return
}
2 changes: 1 addition & 1 deletion pkg/kubepkg/packer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
var kubepkgExample []byte

func TestPacker(t *testing.T) {
t.Skip()
//t.Skip()

registry, _ := name.NewRegistry(os.Getenv("CONTAINER_REGISTRY"))

Expand Down
14 changes: 11 additions & 3 deletions pkg/ocitar/progess.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ type Update struct {
Complete int64
}

func (u *Update) String() string {
if repoName := u.Repository.String(); repoName != "" {
return repoName + "@" + u.Digest.String()
}
return u.Digest.String()
}

type progress struct {
updates chan<- Update
}
Expand All @@ -38,9 +45,10 @@ func (r *progressReader) Read(b []byte) (int, error) {
return n, err
}
r.progress.complete(Update{
Digest: r.digest,
Total: r.total,
Complete: atomic.AddInt64(r.count, int64(n)),
Repository: r.repository,
Digest: r.digest,
Total: r.total,
Complete: atomic.AddInt64(r.count, int64(n)),
})
return n, nil
}
67 changes: 46 additions & 21 deletions pkg/ocitar/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import (
"archive/tar"
"bytes"
"fmt"
"github.com/google/go-containerregistry/pkg/name"
"io"
"path/filepath"
"strings"
"sync"

"github.com/octohelm/x/ptr"

"github.com/pkg/errors"

"github.com/containerd/containerd/images"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/partial"
)
Expand Down Expand Up @@ -53,7 +56,7 @@ func WithProgress(updates chan<- Update) Option {
}

func (w *ociTarWriter) writeRootIndex(idx v1.ImageIndex) error {
if err := w.writeDeps(idx); err != nil {
if err := w.writeDeps(idx, nil); err != nil {
return errors.Wrap(err, "write deps failed")
}

Expand Down Expand Up @@ -85,7 +88,7 @@ type manifest interface {
RawManifest() ([]byte, error)
}

func (w *ociTarWriter) writeToTarWithDigest(dgst v1.Hash, size int64, r io.Reader) error {
func (w *ociTarWriter) writeToTarWithDigest(dgst v1.Hash, size int64, r io.Reader, scope *v1.Descriptor) error {
// avoid dup blob write
if _, ok := w.blobs.Load(dgst); ok {
return nil
Expand All @@ -96,13 +99,21 @@ func (w *ociTarWriter) writeToTarWithDigest(dgst v1.Hash, size int64, r io.Reade
}()

if w.progress != nil {
r = &progressReader{
pr := &progressReader{
r: r,
digest: dgst,
total: size,
count: ptr.Ptr(int64(0)),
progress: w.progress,
}

if scope != nil && scope.Annotations != nil {
if imageName, ok := scope.Annotations[images.AnnotationImageName]; ok {
pr.repository, _ = name.NewRepository(strings.Split(imageName, ":")[0])
}
}

r = pr
}

return w.writeToTar(tar.Header{
Expand All @@ -123,63 +134,77 @@ func (w *ociTarWriter) writeToTar(header tar.Header, r io.Reader) error {
return nil
}

func (w *ociTarWriter) writeDeps(m manifest) error {
func (w *ociTarWriter) writeDeps(m manifest, scope *v1.Descriptor) error {
switch x := m.(type) {
case v1.ImageIndex:
return w.writeChildren(x)
return w.writeChildren(x, scope)
case v1.Image:
return w.writeLayers(x)
return w.writeLayers(x, scope)
}
return nil
}

func (w *ociTarWriter) writeChildren(idx v1.ImageIndex) error {
func (w *ociTarWriter) writeChildren(idx v1.ImageIndex, scope *v1.Descriptor) error {
children, err := partial.Manifests(idx)
if err != nil {
return errors.Wrapf(err, "resolve manifests failed, %T", idx)
}
for _, child := range children {
if err := w.writeChild(child); err != nil {

index, err := idx.IndexManifest()
if err != nil {
return errors.Wrapf(err, "resolve index manifests failed, %T", idx)
}

for i, child := range children {
if i <= len(index.Manifests) {
s := index.Manifests[i]
if s.Annotations != nil {
if _, ok := s.Annotations[images.AnnotationImageName]; ok {
scope = &s
}
}
}
if err := w.writeChild(child, scope); err != nil {
return err
}
}
return nil
}

func (w *ociTarWriter) writeChild(child partial.Describable) error {
func (w *ociTarWriter) writeChild(child partial.Describable, scope *v1.Descriptor) error {
switch child := child.(type) {
case v1.ImageIndex:
return w.writeManifest(child)
return w.writeManifest(child, scope)
case v1.Image:
return w.writeManifest(child)
return w.writeManifest(child, scope)
case v1.Layer:
return w.writeLayer(child)
return w.writeLayer(child, scope)
default:
// This can't happen.
return fmt.Errorf("encountered unknown child: %T", child)
}
}

func (w *ociTarWriter) writeLayers(img v1.Image) error {
func (w *ociTarWriter) writeLayers(img v1.Image, scope *v1.Descriptor) error {
ls, err := img.Layers()
if err != nil {
return errors.Wrap(err, "resolve layers failed")
}

for _, l := range ls {
if err := w.writeLayer(l); err != nil {
if err := w.writeLayer(l, scope); err != nil {
return err
}
}
cl, err := partial.ConfigLayer(img)
if err != nil {
return errors.Wrap(err, "resolve config failed")
}
return w.writeLayer(cl)
return w.writeLayer(cl, scope)
}

func (w *ociTarWriter) writeManifest(m manifest) error {
if err := w.writeDeps(m); err != nil {
func (w *ociTarWriter) writeManifest(m manifest, scope *v1.Descriptor) error {
if err := w.writeDeps(m, scope); err != nil {
return err
}

Expand All @@ -199,7 +224,7 @@ func (w *ociTarWriter) writeManifest(m manifest) error {
}, bytes.NewReader(raw))
}

func (w *ociTarWriter) writeLayer(layer v1.Layer) error {
func (w *ociTarWriter) writeLayer(layer v1.Layer, scope *v1.Descriptor) error {
dgst, err := layer.Digest()
if err != nil {
return errors.Wrap(err, "read layer digest failed")
Expand All @@ -219,8 +244,8 @@ func (w *ociTarWriter) writeLayer(layer v1.Layer) error {
_ = r.Close()
}()

if err := w.writeToTarWithDigest(dgst, size, r); err != nil {
return errors.Wrap(err, "copy layer failed")
if err := w.writeToTarWithDigest(dgst, size, r, scope); err != nil {
return errors.Wrapf(err, "copy %s failed", dgst)
}

return nil
Expand Down

0 comments on commit 8cf6d3f

Please sign in to comment.