@@ -31,6 +31,7 @@ import (
3131 "github.com/containerd/containerd"
3232 "github.com/containerd/containerd/errdefs"
3333 containerdimages "github.com/containerd/containerd/images"
34+ "github.com/containerd/containerd/labels"
3435 "github.com/containerd/containerd/log"
3536 distribution "github.com/containerd/containerd/reference/docker"
3637 "github.com/containerd/containerd/remotes/docker"
@@ -460,7 +461,7 @@ const (
460461 targetDigestLabel = "containerd.io/snapshot/cri.layer-digest"
461462 // targetImageLayersLabel is a label which contains layer digests contained in
462463 // the target image and will be passed to snapshotters for preparing layers in
463- // parallel.
464+ // parallel. Skipping some layers is allowed and only affects performance.
464465 targetImageLayersLabel = "containerd.io/snapshot/cri.image-layers"
465466)
466467
@@ -478,15 +479,6 @@ func appendInfoHandlerWrapper(ref string) func(f containerdimages.Handler) conta
478479 }
479480 switch desc .MediaType {
480481 case imagespec .MediaTypeImageManifest , containerdimages .MediaTypeDockerSchema2Manifest :
481- var layers string
482- for _ , c := range children {
483- if containerdimages .IsLayerType (c .MediaType ) {
484- layers += fmt .Sprintf ("%s," , c .Digest .String ())
485- }
486- }
487- if len (layers ) >= 1 {
488- layers = layers [:len (layers )- 1 ]
489- }
490482 for i := range children {
491483 c := & children [i ]
492484 if containerdimages .IsLayerType (c .MediaType ) {
@@ -495,11 +487,33 @@ func appendInfoHandlerWrapper(ref string) func(f containerdimages.Handler) conta
495487 }
496488 c .Annotations [targetRefLabel ] = ref
497489 c .Annotations [targetDigestLabel ] = c .Digest .String ()
498- c .Annotations [targetImageLayersLabel ] = layers
490+ c .Annotations [targetImageLayersLabel ] = getLayers ( ctx , targetImageLayersLabel , children [ i :], labels . Validate )
499491 }
500492 }
501493 }
502494 return children , nil
503495 })
504496 }
505497}
498+
499+ // getLayers returns comma-separated digests based on the passed list of
500+ // descriptors. The returned list contains as many digests as possible as well
501+ // as meets the label validation.
502+ func getLayers (ctx context.Context , key string , descs []imagespec.Descriptor , validate func (k , v string ) error ) (layers string ) {
503+ var item string
504+ for _ , l := range descs {
505+ if containerdimages .IsLayerType (l .MediaType ) {
506+ item = l .Digest .String ()
507+ if layers != "" {
508+ item = "," + item
509+ }
510+ // This avoids the label hits the size limitation.
511+ if err := validate (key , layers + item ); err != nil {
512+ log .G (ctx ).WithError (err ).WithField ("label" , key ).Debugf ("%q is omitted in the layers list" , l .Digest .String ())
513+ break
514+ }
515+ layers += item
516+ }
517+ }
518+ return
519+ }
0 commit comments