summaryrefslogtreecommitdiff
path: root/libpod/image
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/image')
-rw-r--r--libpod/image/df.go2
-rw-r--r--libpod/image/image.go2
-rw-r--r--libpod/image/parts.go2
-rw-r--r--libpod/image/prune.go23
-rw-r--r--libpod/image/search.go2
-rw-r--r--libpod/image/utils.go58
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.