diff --git a/exporter/containerimage/export.go b/exporter/containerimage/export.go index 26c64748ee82..5dd83785dbec 100644 --- a/exporter/containerimage/export.go +++ b/exporter/containerimage/export.go @@ -239,6 +239,7 @@ func (e *imageExporterInstance) Export(ctx context.Context, src exporter.Source, } } if e.push { + annotations := map[digest.Digest]map[string]string{} mprovider := contentutil.NewMultiProvider(e.opt.ImageWriter.ContentStore()) if src.Ref != nil { remote, err := src.Ref.GetRemote(ctx, false, e.layerCompression) @@ -247,6 +248,7 @@ func (e *imageExporterInstance) Export(ctx context.Context, src exporter.Source, } for _, desc := range remote.Descriptors { mprovider.Add(desc.Digest, remote.Provider) + addAnnotations(annotations, desc) } } if len(src.Refs) > 0 { @@ -257,11 +259,12 @@ func (e *imageExporterInstance) Export(ctx context.Context, src exporter.Source, } for _, desc := range remote.Descriptors { mprovider.Add(desc.Digest, remote.Provider) + addAnnotations(annotations, desc) } } } - if err := push.Push(ctx, e.opt.SessionManager, sessionID, mprovider, e.opt.ImageWriter.ContentStore(), desc.Digest, targetName, e.insecure, e.opt.RegistryHosts, e.pushByDigest); err != nil { + if err := push.Push(ctx, e.opt.SessionManager, sessionID, mprovider, e.opt.ImageWriter.ContentStore(), desc.Digest, targetName, e.insecure, e.opt.RegistryHosts, e.pushByDigest, annotations); err != nil { return nil, err } } @@ -357,3 +360,17 @@ func getLayers(ctx context.Context, descs []ocispec.Descriptor, manifest ocispec } return layers, nil } + +func addAnnotations(m map[digest.Digest]map[string]string, desc ocispec.Descriptor) { + if desc.Annotations == nil { + return + } + a, ok := m[desc.Digest] + if !ok { + m[desc.Digest] = desc.Annotations + return + } + for k, v := range desc.Annotations { + a[k] = v + } +} diff --git a/exporter/containerimage/writer.go b/exporter/containerimage/writer.go index 589ee1201f50..05a8b90faec5 100644 --- a/exporter/containerimage/writer.go +++ b/exporter/containerimage/writer.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "time" "github.com/containerd/containerd/content" @@ -235,6 +236,18 @@ func (ic *ImageWriter) commitDistributionManifest(ctx context.Context, ref cache } for i, desc := range remote.Descriptors { + // oci supports annotations but don't export internal annotations + if oci { + delete(desc.Annotations, "containerd.io/uncompressed") + delete(desc.Annotations, "buildkit/createdat") + for k := range desc.Annotations { + if strings.HasPrefix(k, "containerd.io/distribution.source.") { + delete(desc.Annotations, k) + } + } + } else { + desc.Annotations = nil + } mfst.Layers = append(mfst.Layers, desc) labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i+1)] = desc.Digest.String() } diff --git a/util/push/push.go b/util/push/push.go index d553974d4e09..e73caf8b23e2 100644 --- a/util/push/push.go +++ b/util/push/push.go @@ -26,7 +26,7 @@ import ( "github.com/sirupsen/logrus" ) -func Push(ctx context.Context, sm *session.Manager, sid string, provider content.Provider, manager content.Manager, dgst digest.Digest, ref string, insecure bool, hosts docker.RegistryHosts, byDigest bool) error { +func Push(ctx context.Context, sm *session.Manager, sid string, provider content.Provider, manager content.Manager, dgst digest.Digest, ref string, insecure bool, hosts docker.RegistryHosts, byDigest bool, annotations map[digest.Digest]map[string]string) error { desc := ocispec.Descriptor{ Digest: dgst, } @@ -87,7 +87,7 @@ func Push(ctx context.Context, sm *session.Manager, sid string, provider content } handlers := append([]images.Handler{}, - images.HandlerFunc(annotateDistributionSourceHandler(manager, childrenHandler(provider))), + images.HandlerFunc(annotateDistributionSourceHandler(manager, annotations, childrenHandler(provider))), filterHandler, dedupeHandler(pushUpdateSourceHandler), ) @@ -121,7 +121,7 @@ func Push(ctx context.Context, sm *session.Manager, sid string, provider content return mfstDone(nil) } -func annotateDistributionSourceHandler(manager content.Manager, f images.HandlerFunc) func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { +func annotateDistributionSourceHandler(manager content.Manager, annotations map[digest.Digest]map[string]string, f images.HandlerFunc) func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { children, err := f(ctx, desc) if err != nil { @@ -138,6 +138,20 @@ func annotateDistributionSourceHandler(manager content.Manager, f images.Handler for i := range children { child := children[i] + + if m, ok := annotations[child.Digest]; ok { + for k, v := range m { + if !strings.HasPrefix(k, "containerd.io/distribution.source.") { + continue + } + if child.Annotations == nil { + child.Annotations = map[string]string{} + } + child.Annotations[k] = v + } + } + children[i] = child + info, err := manager.Info(ctx, child.Digest) if errors.Is(err, errdefs.ErrNotFound) { continue