summaryrefslogtreecommitdiff
path: root/libpod/image/image.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/image/image.go')
-rw-r--r--libpod/image/image.go140
1 files changed, 15 insertions, 125 deletions
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 8b2aa318f..6106084d5 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -14,6 +14,7 @@ import (
"syscall"
"time"
+ "github.com/containers/common/pkg/retry"
cp "github.com/containers/image/v5/copy"
"github.com/containers/image/v5/directory"
dockerarchive "github.com/containers/image/v5/docker/archive"
@@ -75,6 +76,8 @@ type InfoImage struct {
Layers []LayerInfo
}
+const maxRetry = 3
+
// ImageFilter is a function to determine whether a image is included
// in command output. Images to be outputted are tested using the function.
// A true return will include the image, a false return will exclude it.
@@ -158,7 +161,7 @@ func (ir *Runtime) New(ctx context.Context, name, signaturePolicyPath, authfile
if signaturePolicyPath == "" {
signaturePolicyPath = ir.SignaturePolicyPath
}
- imageName, err := ir.pullImageFromHeuristicSource(ctx, name, writer, authfile, signaturePolicyPath, signingoptions, dockeroptions, label)
+ imageName, err := ir.pullImageFromHeuristicSource(ctx, name, writer, authfile, signaturePolicyPath, signingoptions, dockeroptions, &retry.RetryOptions{MaxRetry: maxRetry}, label)
if err != nil {
return nil, errors.Wrapf(err, "unable to pull %s", name)
}
@@ -176,7 +179,7 @@ func (ir *Runtime) LoadFromArchiveReference(ctx context.Context, srcRef types.Im
if signaturePolicyPath == "" {
signaturePolicyPath = ir.SignaturePolicyPath
}
- imageNames, err := ir.pullImageFromReference(ctx, srcRef, writer, "", signaturePolicyPath, SigningOptions{}, &DockerRegistryOptions{})
+ imageNames, err := ir.pullImageFromReference(ctx, srcRef, writer, "", signaturePolicyPath, SigningOptions{}, &DockerRegistryOptions{}, &retry.RetryOptions{MaxRetry: maxRetry})
if err != nil {
return nil, errors.Wrapf(err, "unable to pull %s", transports.ImageName(srcRef))
}
@@ -856,26 +859,6 @@ func (i *Image) Dangling() bool {
return len(i.Names()) == 0
}
-// Intermediate returns true if the image is cache or intermediate image.
-// Cache image has parent and child.
-func (i *Image) Intermediate(ctx context.Context) (bool, error) {
- parent, err := i.IsParent(ctx)
- if err != nil {
- return false, err
- }
- if !parent {
- return false, nil
- }
- img, err := i.GetParent(ctx)
- if err != nil {
- return false, err
- }
- if img != nil {
- return true, nil
- }
- return false, nil
-}
-
// User returns the image's user
func (i *Image) User(ctx context.Context) (string, error) {
imgInspect, err := i.inspect(ctx, false)
@@ -1214,7 +1197,7 @@ func splitString(input string) string {
// the parent of any other layer in store. Double check that image with that
// layer exists as well.
func (i *Image) IsParent(ctx context.Context) (bool, error) {
- children, err := i.getChildren(ctx, 1)
+ children, err := i.getChildren(ctx, false)
if err != nil {
if errors.Cause(err) == ErrImageIsBareList {
return false, nil
@@ -1289,63 +1272,16 @@ func areParentAndChild(parent, child *imgspecv1.Image) bool {
// GetParent returns the image ID of the parent. Return nil if a parent is not found.
func (i *Image) GetParent(ctx context.Context) (*Image, error) {
- var childLayer *storage.Layer
- images, err := i.imageruntime.GetImages()
- if err != nil {
- return nil, err
- }
- if i.TopLayer() != "" {
- if childLayer, err = i.imageruntime.store.Layer(i.TopLayer()); err != nil {
- return nil, err
- }
- }
- // fetch the configuration for the child image
- child, err := i.ociv1Image(ctx)
+ tree, err := i.imageruntime.layerTree()
if err != nil {
- if errors.Cause(err) == ErrImageIsBareList {
- return nil, nil
- }
return nil, err
}
- for _, img := range images {
- if img.ID() == i.ID() {
- continue
- }
- candidateLayer := img.TopLayer()
- // as a child, our top layer, if we have one, is either the
- // candidate parent's layer, or one that's derived from it, so
- // skip over any candidate image where we know that isn't the
- // case
- if childLayer != nil {
- // The child has at least one layer, so a parent would
- // have a top layer that's either the same as the child's
- // top layer or the top layer's recorded parent layer,
- // which could be an empty value.
- if candidateLayer != childLayer.Parent && candidateLayer != childLayer.ID {
- continue
- }
- } else {
- // The child has no layers, but the candidate does.
- if candidateLayer != "" {
- continue
- }
- }
- // fetch the configuration for the candidate image
- candidate, err := img.ociv1Image(ctx)
- if err != nil {
- return nil, err
- }
- // compare them
- if areParentAndChild(candidate, child) {
- return img, nil
- }
- }
- return nil, nil
+ return tree.parent(ctx, i)
}
// GetChildren returns a list of the imageIDs that depend on the image
func (i *Image) GetChildren(ctx context.Context) ([]string, error) {
- children, err := i.getChildren(ctx, 0)
+ children, err := i.getChildren(ctx, true)
if err != nil {
if errors.Cause(err) == ErrImageIsBareList {
return nil, nil
@@ -1355,62 +1291,15 @@ func (i *Image) GetChildren(ctx context.Context) ([]string, error) {
return children, nil
}
-// getChildren returns a list of at most "max" imageIDs that depend on the image
-func (i *Image) getChildren(ctx context.Context, max int) ([]string, error) {
- var children []string
-
- if _, err := i.toImageRef(ctx); err != nil {
- return nil, nil
- }
-
- images, err := i.imageruntime.GetImages()
- if err != nil {
- return nil, err
- }
-
- // fetch the configuration for the parent image
- parent, err := i.ociv1Image(ctx)
+// getChildren returns a list of imageIDs that depend on the image. If all is
+// false, only the first child image is returned.
+func (i *Image) getChildren(ctx context.Context, all bool) ([]string, error) {
+ tree, err := i.imageruntime.layerTree()
if err != nil {
return nil, err
}
- parentLayer := i.TopLayer()
- for _, img := range images {
- if img.ID() == i.ID() {
- continue
- }
- if img.TopLayer() == "" {
- if parentLayer != "" {
- // this image has no layers, but we do, so
- // it can't be derived from this one
- continue
- }
- } else {
- candidateLayer, err := img.Layer()
- if err != nil {
- return nil, err
- }
- // if this image's top layer is not our top layer, and is not
- // based on our top layer, we can skip it
- if candidateLayer.Parent != parentLayer && candidateLayer.ID != parentLayer {
- continue
- }
- }
- // fetch the configuration for the candidate image
- candidate, err := img.ociv1Image(ctx)
- if err != nil {
- return nil, err
- }
- // compare them
- if areParentAndChild(parent, candidate) {
- children = append(children, img.ID())
- }
- // if we're not building an exhaustive list, maybe we're done?
- if max > 0 && len(children) >= max {
- break
- }
- }
- return children, nil
+ return tree.children(ctx, i, all)
}
// InputIsID returns a bool if the user input for an image
@@ -1667,6 +1556,7 @@ type LayerInfo struct {
// GetLayersMapWithImageInfo returns map of image-layers, with associated information like RepoTags, parent and list of child layers.
func GetLayersMapWithImageInfo(imageruntime *Runtime) (map[string]*LayerInfo, error) {
+ // TODO: evaluate if we can reuse `layerTree` here.
// Memory allocated to store map of layers with key LayerID.
// Map will build dependency chain with ParentID and ChildID(s)