Skip to content

Commit

Permalink
layer tree: handle more errors
Browse files Browse the repository at this point in the history
Commit 97961a6 took a first stab at making operating on the layer
tree more resilient by detecting unknown-image errors.  Testing in
containers/podman/pull/18980 revealed that we also need to detect
unknown-layer and -size errors as well.

Move the errors checks into a convenience function and update the
relevant call sites to facilitate future changes.  Export the
function since Podman needs the very same checks when operating
on images, for instance, when looking up image labels.

Signed-off-by: Valentin Rothberg <[email protected]>
  • Loading branch information
vrothberg committed Jun 26, 2023
1 parent 3273ac8 commit 4c693c4
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 7 deletions.
2 changes: 1 addition & 1 deletion libimage/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
// have a closer look at the errors. On top, image removal should be
// tolerant toward corrupted images.
handleError := func(err error) error {
if errors.Is(err, storage.ErrImageUnknown) || errors.Is(err, storage.ErrNotAnImage) || errors.Is(err, storage.ErrLayerUnknown) {
if ErrorIsImageUnknown(err) {
// The image or layers of the image may already have been removed
// in which case we consider the image to be removed.
return nil
Expand Down
22 changes: 16 additions & 6 deletions libimage/layer_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"

"github.com/containers/storage"
storageTypes "github.com/containers/storage/types"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus"
)
Expand All @@ -31,10 +32,19 @@ func (t *layerTree) node(layerID string) *layerNode {
return node
}

// ErrorIsImageUnknown returns true if the specified error indicates that an
// image is unknown or has been partially removed (e.g., a missing layer).
func ErrorIsImageUnknown(err error) bool {
return errors.Is(err, storage.ErrImageUnknown) ||
errors.Is(err, storageTypes.ErrLayerUnknown) ||
errors.Is(err, storageTypes.ErrSizeUnknown) ||
errors.Is(err, storage.ErrNotAnImage)
}

// toOCI returns an OCI image for the specified image.
//
// WARNING: callers are responsible for handling cases where the target image
// has been removed and need to check for `storage.ErrImageUnknown`.
// has been (partially) removed and can use `ErrorIsImageUnknown` to detect it.
func (t *layerTree) toOCI(ctx context.Context, i *Image) (*ociv1.Image, error) {
var err error
oci, exists := t.ociCache[i.ID()]
Expand Down Expand Up @@ -159,7 +169,7 @@ func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*I
parentID := parent.ID()
parentOCI, err := t.toOCI(ctx, parent)
if err != nil {
if errors.Is(err, storage.ErrImageUnknown) {
if ErrorIsImageUnknown(err) {
return nil, nil
}
return nil, err
Expand All @@ -172,7 +182,7 @@ func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*I
}
childOCI, err := t.toOCI(ctx, child)
if err != nil {
if errors.Is(err, storage.ErrImageUnknown) {
if ErrorIsImageUnknown(err) {
return false, nil
}
return false, err
Expand Down Expand Up @@ -265,7 +275,7 @@ func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) {
childID := child.ID()
childOCI, err := t.toOCI(ctx, child)
if err != nil {
if errors.Is(err, storage.ErrImageUnknown) {
if ErrorIsImageUnknown(err) {
return nil, nil
}
return nil, err
Expand All @@ -281,7 +291,7 @@ func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) {
}
emptyOCI, err := t.toOCI(ctx, empty)
if err != nil {
if errors.Is(err, storage.ErrImageUnknown) {
if ErrorIsImageUnknown(err) {
return nil, nil
}
return nil, err
Expand Down Expand Up @@ -316,7 +326,7 @@ func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) {
}
parentOCI, err := t.toOCI(ctx, parent)
if err != nil {
if errors.Is(err, storage.ErrImageUnknown) {
if ErrorIsImageUnknown(err) {
return nil, nil
}
return nil, err
Expand Down

0 comments on commit 4c693c4

Please sign in to comment.