From ce6859fd250dc3c1db670562f28e644ffec1aaf6 Mon Sep 17 00:00:00 2001 From: Stephen J Day Date: Wed, 27 Sep 2017 16:03:29 -0700 Subject: [PATCH] images: provide separated children function for images Signed-off-by: Stephen J Day --- images/handlers.go | 61 ++-------------------------------------------- images/image.go | 60 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 59 deletions(-) diff --git a/images/handlers.go b/images/handlers.go index 4ac5143ec..a993593de 100644 --- a/images/handlers.go +++ b/images/handlers.go @@ -2,12 +2,9 @@ package images import ( "context" - "encoding/json" "fmt" "github.com/containerd/containerd/content" - "github.com/containerd/containerd/log" - "github.com/containerd/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "golang.org/x/sync/errgroup" @@ -121,7 +118,7 @@ func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) return eg.Wait() } -// ChildrenHandler decodes well-known manifests types and returns their children. +// ChildrenHandler decodes well-known manifest types and returns their children. // // This is useful for supporting recursive fetch and other use cases where you // want to do a full walk of resources. @@ -130,60 +127,6 @@ func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) // arbitrary types. func ChildrenHandler(provider content.Provider, platform string) HandlerFunc { return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { - var descs []ocispec.Descriptor - switch desc.MediaType { - case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: - p, err := content.ReadBlob(ctx, provider, desc.Digest) - if err != nil { - return nil, err - } - - // TODO(stevvooe): We just assume oci manifest, for now. There may be - // subtle differences from the docker version. - var manifest ocispec.Manifest - if err := json.Unmarshal(p, &manifest); err != nil { - return nil, err - } - - descs = append(descs, manifest.Config) - descs = append(descs, manifest.Layers...) - case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex: - p, err := content.ReadBlob(ctx, provider, desc.Digest) - if err != nil { - return nil, err - } - - var index ocispec.Index - if err := json.Unmarshal(p, &index); err != nil { - return nil, err - } - - if platform != "" { - matcher, err := platforms.Parse(platform) - if err != nil { - return nil, err - } - - for _, d := range index.Manifests { - if d.Platform == nil || matcher.Match(*d.Platform) { - descs = append(descs, d) - } - } - } else { - descs = append(descs, index.Manifests...) - } - - case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip, - MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip, - MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig, - ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerGzip, - ocispec.MediaTypeImageLayerNonDistributable, ocispec.MediaTypeImageLayerNonDistributableGzip: - // childless data types. - return nil, nil - default: - log.G(ctx).Warnf("encountered unknown type %v; children may not be fetched", desc.MediaType) - } - - return descs, nil + return Children(ctx, provider, desc, platform) } } diff --git a/images/image.go b/images/image.go index 763db1517..969374bb5 100644 --- a/images/image.go +++ b/images/image.go @@ -7,6 +7,7 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/platforms" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -199,6 +200,65 @@ func Platforms(ctx context.Context, provider content.Provider, image ocispec.Des }), ChildrenHandler(provider, "")), image) } +// Children returns the immediate children of content described by the descriptor. +func Children(ctx context.Context, provider content.Provider, desc ocispec.Descriptor, platform string) ([]ocispec.Descriptor, error) { + var descs []ocispec.Descriptor + switch desc.MediaType { + case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: + p, err := content.ReadBlob(ctx, provider, desc.Digest) + if err != nil { + return nil, err + } + + // TODO(stevvooe): We just assume oci manifest, for now. There may be + // subtle differences from the docker version. + var manifest ocispec.Manifest + if err := json.Unmarshal(p, &manifest); err != nil { + return nil, err + } + + descs = append(descs, manifest.Config) + descs = append(descs, manifest.Layers...) + case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex: + p, err := content.ReadBlob(ctx, provider, desc.Digest) + if err != nil { + return nil, err + } + + var index ocispec.Index + if err := json.Unmarshal(p, &index); err != nil { + return nil, err + } + + if platform != "" { + matcher, err := platforms.Parse(platform) + if err != nil { + return nil, err + } + + for _, d := range index.Manifests { + if d.Platform == nil || matcher.Match(*d.Platform) { + descs = append(descs, d) + } + } + } else { + descs = append(descs, index.Manifests...) + } + + case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip, + MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip, + MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig, + ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerGzip, + ocispec.MediaTypeImageLayerNonDistributable, ocispec.MediaTypeImageLayerNonDistributableGzip: + // childless data types. + return nil, nil + default: + log.G(ctx).Warnf("encountered unknown type %v; children may not be fetched", desc.MediaType) + } + + return descs, nil +} + // RootFS returns the unpacked diffids that make up and images rootfs. // // These are used to verify that a set of layers unpacked to the expected