aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@redhat.com>2019-10-16 12:01:30 -0400
committerNalin Dahyabhai <nalin@redhat.com>2019-10-29 13:35:19 -0400
commit248bb61b14a3f0d4e1d244eff85b30f48554a6a8 (patch)
treebbaa162a20177f96a0fc03a48faaa49dcfc89215 /libpod
parent07195ff09fdcb0d2d3a044c92665b082d6e742b1 (diff)
downloadpodman-248bb61b14a3f0d4e1d244eff85b30f48554a6a8.tar.gz
podman-248bb61b14a3f0d4e1d244eff85b30f48554a6a8.tar.bz2
podman-248bb61b14a3f0d4e1d244eff85b30f48554a6a8.zip
images: distinguish between tags and digests
Generate an image's RepoDigests list using all applicable digests, and refrain from outputting a digest in the tag column of the "images" output. Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r--libpod/image/image.go55
-rw-r--r--libpod/image/image_test.go13
-rw-r--r--libpod/image/utils.go14
3 files changed, 63 insertions, 19 deletions
diff --git a/libpod/image/image.go b/libpod/image/image.go
index faa3b648a..c912ac2ca 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -9,6 +9,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "sort"
"strings"
"syscall"
"time"
@@ -324,29 +325,54 @@ func (i *Image) Manifest(ctx context.Context) ([]byte, string, error) {
return imgRef.Manifest(ctx)
}
-// Names returns a string array of names associated with the image
+// Names returns a string array of names associated with the image, which may be a mixture of tags and digests
func (i *Image) Names() []string {
return i.image.Names
}
-// RepoDigests returns a string array of repodigests associated with the image
-func (i *Image) RepoDigests() ([]string, error) {
- var repoDigests []string
- imageDigest := i.Digest()
-
+// RepoTags returns a string array of repotags associated with the image
+func (i *Image) RepoTags() ([]string, error) {
+ var repoTags []string
for _, name := range i.Names() {
named, err := reference.ParseNormalizedNamed(name)
if err != nil {
return nil, err
}
-
- canonical, err := reference.WithDigest(reference.TrimNamed(named), imageDigest)
- if err != nil {
- return nil, err
+ if tagged, isTagged := named.(reference.NamedTagged); isTagged {
+ repoTags = append(repoTags, tagged.String())
}
+ }
+ return repoTags, nil
+}
+
+// RepoDigests returns a string array of repodigests associated with the image
+func (i *Image) RepoDigests() ([]string, error) {
+ var repoDigests []string
+ added := make(map[string]struct{})
- repoDigests = append(repoDigests, canonical.String())
+ for _, name := range i.Names() {
+ for _, imageDigest := range append(i.Digests(), i.Digest()) {
+ if imageDigest == "" {
+ continue
+ }
+
+ named, err := reference.ParseNormalizedNamed(name)
+ if err != nil {
+ return nil, err
+ }
+
+ canonical, err := reference.WithDigest(reference.TrimNamed(named), imageDigest)
+ if err != nil {
+ return nil, err
+ }
+
+ if _, alreadyInList := added[canonical.String()]; !alreadyInList {
+ repoDigests = append(repoDigests, canonical.String())
+ added[canonical.String()] = struct{}{}
+ }
+ }
}
+ sort.Strings(repoDigests)
return repoDigests, nil
}
@@ -944,6 +970,11 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) {
size = int64(*usize)
}
+ repoTags, err := i.RepoTags()
+ if err != nil {
+ return nil, err
+ }
+
repoDigests, err := i.RepoDigests()
if err != nil {
return nil, err
@@ -965,7 +996,7 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) {
data := &inspect.ImageData{
ID: i.ID(),
- RepoTags: i.Names(),
+ RepoTags: repoTags,
RepoDigests: repoDigests,
Comment: comment,
Created: ociv1Img.Created,
diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go
index ef39d09c3..5aff7d860 100644
--- a/libpod/image/image_test.go
+++ b/libpod/image/image_test.go
@@ -247,6 +247,19 @@ func TestImage_RepoDigests(t *testing.T) {
}
assert.Equal(t, test.expected, actual)
+
+ image = &Image{
+ image: &storage.Image{
+ Names: test.names,
+ Digests: []digest.Digest{dgst},
+ },
+ }
+ actual, err = image.RepoDigests()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ assert.Equal(t, test.expected, actual)
})
}
}
diff --git a/libpod/image/utils.go b/libpod/image/utils.go
index 5c971cb2b..b7ea63c66 100644
--- a/libpod/image/utils.go
+++ b/libpod/image/utils.go
@@ -87,18 +87,18 @@ func hasTransport(image string) bool {
}
// ReposToMap parses the specified repotags and returns a map with repositories
-// as keys and the corresponding arrays of tags as values.
-func ReposToMap(repotags []string) (map[string][]string, error) {
- // map format is repo -> tag
+// as keys and the corresponding arrays of tags or digests-as-strings as values.
+func ReposToMap(names []string) (map[string][]string, error) {
+ // map format is repo -> []tag-or-digest
repos := make(map[string][]string)
- for _, repo := range repotags {
+ for _, name := range names {
var repository, tag string
- if len(repo) > 0 {
- named, err := reference.ParseNormalizedNamed(repo)
- repository = named.Name()
+ if len(name) > 0 {
+ named, err := reference.ParseNormalizedNamed(name)
if err != nil {
return nil, err
}
+ repository = named.Name()
if ref, ok := named.(reference.NamedTagged); ok {
tag = ref.Tag()
} else if ref, ok := named.(reference.Canonical); ok {