images/Children: Return error
Change return value in function signature and return fatal errors so they can actually be reported to the caller instead of just being logged to daemon log. Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
parent
45483a1d0d
commit
9cb5da400c
4 changed files with 43 additions and 31 deletions
|
@ -7,46 +7,49 @@ import (
|
|||
cerrdefs "github.com/containerd/containerd/errdefs"
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/image"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Children returns a slice of image ID which rootfs is a superset of the
|
||||
// rootfs of the given image ID, excluding images with exactly the same rootfs.
|
||||
// Called from list.go to filter containers.
|
||||
func (i *ImageService) Children(ctx context.Context, id image.ID) []image.ID {
|
||||
func (i *ImageService) Children(ctx context.Context, id image.ID) ([]image.ID, error) {
|
||||
target, err := i.resolveDescriptor(ctx, id.String())
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("failed to get parent image")
|
||||
return []image.ID{}
|
||||
return []image.ID{}, errors.Wrap(err, "failed to get parent image")
|
||||
}
|
||||
|
||||
is := i.client.ImageService()
|
||||
cs := i.client.ContentStore()
|
||||
|
||||
log := logrus.WithField("id", id)
|
||||
|
||||
allPlatforms, err := containerdimages.Platforms(ctx, cs, target)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to list supported platorms of image")
|
||||
return []image.ID{}
|
||||
return []image.ID{}, errdefs.System(errors.Wrap(err, "failed to list platforms supported by image"))
|
||||
}
|
||||
|
||||
parentRootFS := []ocispec.RootFS{}
|
||||
for _, platform := range allPlatforms {
|
||||
rootfs, err := platformRootfs(ctx, cs, target, platform)
|
||||
if err != nil {
|
||||
if !cerrdefs.IsNotFound(err) {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
logrus.ErrorKey: err,
|
||||
"image": target.Digest,
|
||||
"platform": platform,
|
||||
}).Warning("failed to get platform-specific rootfs")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
parentRootFS = append(parentRootFS, rootfs)
|
||||
}
|
||||
|
||||
imgs, err := is.List(ctx)
|
||||
imgs, err := i.client.ImageService().List(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to list all images")
|
||||
return []image.ID{}
|
||||
return []image.ID{}, errdefs.System(errors.Wrap(err, "failed to list all images"))
|
||||
}
|
||||
|
||||
children := []image.ID{}
|
||||
|
@ -55,6 +58,13 @@ func (i *ImageService) Children(ctx context.Context, id image.ID) []image.ID {
|
|||
for _, platform := range allPlatforms {
|
||||
rootfs, err := platformRootfs(ctx, cs, img.Target, platform)
|
||||
if err != nil {
|
||||
if !cerrdefs.IsNotFound(err) {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
logrus.ErrorKey: err,
|
||||
"image": img.Target.Digest,
|
||||
"platform": platform,
|
||||
}).Warning("failed to get platform-specific rootfs")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -68,29 +78,21 @@ func (i *ImageService) Children(ctx context.Context, id image.ID) []image.ID {
|
|||
|
||||
}
|
||||
|
||||
return children
|
||||
return children, nil
|
||||
}
|
||||
|
||||
// platformRootfs returns a rootfs for a specified platform.
|
||||
func platformRootfs(ctx context.Context, store content.Store, desc ocispec.Descriptor, platform ocispec.Platform) (ocispec.RootFS, error) {
|
||||
empty := ocispec.RootFS{}
|
||||
|
||||
log := logrus.WithField("desc", desc.Digest).WithField("platform", platforms.Format(platform))
|
||||
configDesc, err := containerdimages.Config(ctx, store, desc, platforms.OnlyStrict(platform))
|
||||
if err != nil {
|
||||
if !cerrdefs.IsNotFound(err) {
|
||||
log.WithError(err).Warning("failed to get parent image config")
|
||||
}
|
||||
return empty, err
|
||||
return empty, errors.Wrapf(err, "failed to get config for platform %s", platforms.Format(platform))
|
||||
}
|
||||
|
||||
log = log.WithField("configDesc", configDesc)
|
||||
diffs, err := containerdimages.RootFS(ctx, store, configDesc)
|
||||
if err != nil {
|
||||
if !cerrdefs.IsNotFound(err) {
|
||||
log.WithError(err).Warning("failed to get parent image rootfs")
|
||||
}
|
||||
return empty, err
|
||||
return empty, errors.Wrapf(err, "failed to obtain rootfs")
|
||||
}
|
||||
|
||||
return ocispec.RootFS{
|
||||
|
|
|
@ -73,7 +73,7 @@ type ImageService interface {
|
|||
// Other
|
||||
|
||||
DistributionServices() images.DistributionServices
|
||||
Children(ctx context.Context, id image.ID) []image.ID
|
||||
Children(ctx context.Context, id image.ID) ([]image.ID, error)
|
||||
Cleanup() error
|
||||
StorageDriver() string
|
||||
UpdateConfig(maxDownloads, maxUploads int)
|
||||
|
|
|
@ -109,8 +109,8 @@ func (i *ImageService) CountImages() int {
|
|||
// Children returns the children image.IDs for a parent image.
|
||||
// called from list.go to filter containers
|
||||
// TODO: refactor to expose an ancestry for image.ID?
|
||||
func (i *ImageService) Children(_ context.Context, id image.ID) []image.ID {
|
||||
return i.imageStore.Children(id)
|
||||
func (i *ImageService) Children(_ context.Context, id image.ID) ([]image.ID, error) {
|
||||
return i.imageStore.Children(id), nil
|
||||
}
|
||||
|
||||
// CreateLayer creates a filesystem layer for a container.
|
||||
|
|
|
@ -317,7 +317,7 @@ func (daemon *Daemon) foldFilter(ctx context.Context, view *container.View, conf
|
|||
var ancestorFilter bool
|
||||
if psFilters.Contains("ancestor") {
|
||||
ancestorFilter = true
|
||||
psFilters.WalkValues("ancestor", func(ancestor string) error {
|
||||
err := psFilters.WalkValues("ancestor", func(ancestor string) error {
|
||||
img, err := daemon.imageService.GetImage(ctx, ancestor, imagetypes.GetImageOpts{})
|
||||
if err != nil {
|
||||
logrus.Warnf("Error while looking up for image %v", ancestor)
|
||||
|
@ -328,9 +328,12 @@ func (daemon *Daemon) foldFilter(ctx context.Context, view *container.View, conf
|
|||
return nil
|
||||
}
|
||||
// Then walk down the graph and put the imageIds in imagesFilter
|
||||
populateImageFilterByParents(ctx, imagesFilter, img.ID(), daemon.imageService.Children)
|
||||
return nil
|
||||
return populateImageFilterByParents(ctx, imagesFilter, img.ID(), daemon.imageService.Children)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
publishFilter := map[nat.Port]bool{}
|
||||
|
@ -594,11 +597,18 @@ func (daemon *Daemon) refreshImage(ctx context.Context, s *container.Snapshot, f
|
|||
return &c, nil
|
||||
}
|
||||
|
||||
func populateImageFilterByParents(ctx context.Context, ancestorMap map[image.ID]bool, imageID image.ID, getChildren func(context.Context, image.ID) []image.ID) {
|
||||
func populateImageFilterByParents(ctx context.Context, ancestorMap map[image.ID]bool, imageID image.ID, getChildren func(context.Context, image.ID) ([]image.ID, error)) error {
|
||||
if !ancestorMap[imageID] {
|
||||
for _, id := range getChildren(ctx, imageID) {
|
||||
populateImageFilterByParents(ctx, ancestorMap, id, getChildren)
|
||||
children, err := getChildren(ctx, imageID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, id := range children {
|
||||
if err := populateImageFilterByParents(ctx, ancestorMap, id, getChildren); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ancestorMap[imageID] = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue