diff options
Diffstat (limited to 'libpod/image')
-rw-r--r-- | libpod/image/df.go | 2 | ||||
-rw-r--r-- | libpod/image/image.go | 2 | ||||
-rw-r--r-- | libpod/image/parts.go | 2 | ||||
-rw-r--r-- | libpod/image/prune.go | 23 | ||||
-rw-r--r-- | libpod/image/search.go | 2 | ||||
-rw-r--r-- | libpod/image/utils.go | 58 |
6 files changed, 68 insertions, 21 deletions
diff --git a/libpod/image/df.go b/libpod/image/df.go index 84cf7af9e..231d28df4 100644 --- a/libpod/image/df.go +++ b/libpod/image/df.go @@ -51,7 +51,7 @@ func (ir *Runtime) DiskUsage(ctx context.Context, images []*Image) ([]DiskUsageS return stats, nil } -// diskUsageForImage returns the disk-usage statistics for the spcified image. +// diskUsageForImage returns the disk-usage statistics for the specified image. func diskUsageForImage(ctx context.Context, image *Image, tree *layerTree) (*DiskUsageStat, error) { stat := DiskUsageStat{ ID: image.ID(), diff --git a/libpod/image/image.go b/libpod/image/image.go index 5c3f3b9e4..a9082b2c6 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -497,7 +497,7 @@ func (ir *Runtime) getLocalImage(inputName string) (string, *storage.Image, erro return inputName, repoImage, nil } - return "", nil, errors.Wrapf(ErrNoSuchImage, err.Error()) + return "", nil, err } // ID returns the image ID as a string diff --git a/libpod/image/parts.go b/libpod/image/parts.go index d6c98783b..08421320c 100644 --- a/libpod/image/parts.go +++ b/libpod/image/parts.go @@ -50,7 +50,7 @@ func decompose(input string) (imageParts, error) { // suspiciousRefNameTagValuesForSearch returns a "tag" value used in a previous implementation. // This exists only to preserve existing behavior in heuristic code; it’s dubious that that behavior is correct, -// gespecially for the tag value. +// especially for the tag value. func (ip *imageParts) suspiciousRefNameTagValuesForSearch() (string, string, string) { registry := reference.Domain(ip.unnormalizedRef) imageName := reference.Path(ip.unnormalizedRef) diff --git a/libpod/image/prune.go b/libpod/image/prune.go index b38265a7e..3c06a89c2 100644 --- a/libpod/image/prune.go +++ b/libpod/image/prune.go @@ -6,6 +6,7 @@ import ( "time" "github.com/containers/podman/v2/libpod/events" + "github.com/containers/podman/v2/pkg/domain/entities/reports" "github.com/containers/podman/v2/pkg/timetype" "github.com/containers/storage" "github.com/pkg/errors" @@ -110,7 +111,8 @@ func (ir *Runtime) GetPruneImages(ctx context.Context, all bool, filterFuncs []I // PruneImages prunes dangling and optionally all unused images from the local // image store -func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) ([]string, error) { +func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) ([]*reports.PruneReport, error) { + preports := make([]*reports.PruneReport, 0) filterFuncs := make([]ImageFilter, 0, len(filter)) for _, f := range filter { filterSplit := strings.SplitN(f, "=", 2) @@ -125,7 +127,6 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) ( filterFuncs = append(filterFuncs, generatedFunc) } - pruned := []string{} prev := 0 for { toPrune, err := ir.GetPruneImages(ctx, all, filterFuncs) @@ -143,6 +144,13 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) ( if err != nil { return nil, err } + nameOrID := img.ID() + s, err := img.Size(ctx) + imgSize := *s + if err != nil { + logrus.Warnf("Failed to collect image size for: %s, %s", nameOrID, err) + imgSize = 0 + } if err := img.Remove(ctx, false); err != nil { if errors.Cause(err) == storage.ErrImageUsedByContainer { logrus.Warnf("Failed to prune image %s as it is in use: %v.\nA container associated with containers/storage (e.g., Buildah, CRI-O, etc.) maybe associated with this image.\nUsing the rmi command with the --force option will remove the container and image, but may cause failures for other dependent systems.", img.ID(), err) @@ -151,13 +159,18 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) ( return nil, errors.Wrap(err, "failed to prune image") } defer img.newImageEvent(events.Prune) - nameOrID := img.ID() + if len(repotags) > 0 { nameOrID = repotags[0] } - pruned = append(pruned, nameOrID) + + preports = append(preports, &reports.PruneReport{ + Id: nameOrID, + Err: nil, + Size: uint64(imgSize), + }) } } - return pruned, nil + return preports, nil } diff --git a/libpod/image/search.go b/libpod/image/search.go index b9acf4a20..6020fbca9 100644 --- a/libpod/image/search.go +++ b/libpod/image/search.go @@ -26,7 +26,7 @@ const ( type SearchResult struct { // Index is the image index (e.g., "docker.io" or "quay.io") Index string - // Name is the canoncical name of the image (e.g., "docker.io/library/alpine"). + // Name is the canonical name of the image (e.g., "docker.io/library/alpine"). Name string // Description of the image. Description string diff --git a/libpod/image/utils.go b/libpod/image/utils.go index 7429a7f10..5e7fed5c6 100644 --- a/libpod/image/utils.go +++ b/libpod/image/utils.go @@ -20,7 +20,11 @@ import ( // a match on name:tag func findImageInRepotags(search imageParts, images []*Image) (*storage.Image, error) { _, searchName, searchSuspiciousTagValueForSearch := search.suspiciousRefNameTagValuesForSearch() - var results []*storage.Image + type Candidate struct { + name string + image *Image + } + var candidates []Candidate for _, image := range images { for _, name := range image.Names() { d, err := decompose(name) @@ -29,23 +33,53 @@ func findImageInRepotags(search imageParts, images []*Image) (*storage.Image, er continue } _, dName, dSuspiciousTagValueForSearch := d.suspiciousRefNameTagValuesForSearch() - if dName == searchName && dSuspiciousTagValueForSearch == searchSuspiciousTagValueForSearch { - results = append(results, image.image) + if dSuspiciousTagValueForSearch != searchSuspiciousTagValueForSearch { continue } - // account for registry:/somedir/image - if strings.HasSuffix(dName, "/"+searchName) && dSuspiciousTagValueForSearch == searchSuspiciousTagValueForSearch { - results = append(results, image.image) - continue + if dName == searchName || strings.HasSuffix(dName, "/"+searchName) { + candidates = append(candidates, Candidate{ + name: name, + image: image, + }) } } } - if len(results) == 0 { - return &storage.Image{}, errors.Errorf("unable to find a name and tag match for %s in repotags", searchName) - } else if len(results) > 1 { - return &storage.Image{}, errors.Wrapf(define.ErrMultipleImages, searchName) + if len(candidates) == 0 { + + return nil, errors.Wrapf(define.ErrNoSuchImage, "unable to find a name and tag match for %s in repotags", searchName) + } + + // If more then one candidate and the candidates all have same name + // and only one is read/write return it. + // Othewise return error with the list of candidates + if len(candidates) > 1 { + var ( + rwImage *Image + rwImageCnt int + ) + names := make(map[string]bool) + for _, c := range candidates { + names[c.name] = true + if !c.image.IsReadOnly() { + rwImageCnt++ + rwImage = c.image + } + } + // If only one name used and have read/write image return it + if len(names) == 1 && rwImageCnt == 1 { + return rwImage.image, nil + } + keys := []string{} + for k := range names { + keys = append(keys, k) + } + if rwImageCnt > 1 { + return nil, errors.Wrapf(define.ErrMultipleImages, "found multiple read/write images %s", strings.Join(keys, ",")) + } else { + return nil, errors.Wrapf(define.ErrMultipleImages, "found multiple read/only images %s", strings.Join(keys, ",")) + } } - return results[0], nil + return candidates[0].image.image, nil } // getCopyOptions constructs a new containers/image/copy.Options{} struct from the given parameters, inheriting some from sc. |