Ver código fonte

Merge pull request #44840 from vvoland/c8d-list-dangling-upstream

c8d/list: Fix Repo(Digests|Tags) for untagged images
Bjorn Neergaard 2 anos atrás
pai
commit
a9f17a28db

+ 7 - 0
api/server/router/image/image_routes.go

@@ -337,6 +337,13 @@ func (ir *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter,
 		return err
 	}
 
+	for _, img := range images {
+		if len(img.RepoTags) == 0 && len(img.RepoDigests) == 0 {
+			img.RepoTags = append(img.RepoTags, "<none>:<none>")
+			img.RepoDigests = append(img.RepoDigests, "<none>@<none>")
+		}
+	}
+
 	return httputils.WriteJSON(w, http.StatusOK, images)
 }
 

+ 37 - 4
daemon/containerd/image_list.go

@@ -9,6 +9,7 @@ import (
 	"github.com/docker/docker/api/types/filters"
 	"github.com/opencontainers/go-digest"
 	"github.com/opencontainers/image-spec/identity"
+	"github.com/sirupsen/logrus"
 )
 
 var acceptedImageFilterTags = map[string]bool{
@@ -64,6 +65,7 @@ func (i *ImageService) Images(ctx context.Context, opts types.ImageListOptions)
 		root = make([]*[]digest.Digest, len(imgs))
 		layers = make(map[digest.Digest]int)
 	}
+
 	for n, img := range imgs {
 		if !filter(img) {
 			continue
@@ -91,12 +93,43 @@ func (i *ImageService) Images(ctx context.Context, opts types.ImageListOptions)
 			return nil, err
 		}
 
+		var repoTags, repoDigests []string
+		rawImg := img.Metadata()
+		target := rawImg.Target.Digest
+
+		logger := logrus.WithFields(logrus.Fields{
+			"name":   img.Name(),
+			"digest": target,
+		})
+
+		ref, err := reference.ParseNamed(rawImg.Name)
+		if err != nil {
+			// If the image has unexpected name format (not a Named reference or a dangling image)
+			// add the offending name to RepoTags but also log an error to make it clear to the
+			// administrator that this is unexpected.
+			// TODO: Reconsider when containerd is more strict on image names, see:
+			//       https://github.com/containerd/containerd/issues/7986
+			if !isDanglingImage(rawImg) {
+				logger.WithError(err).Error("failed to parse image name as reference")
+				repoTags = append(repoTags, img.Name())
+			}
+		} else {
+			repoTags = append(repoTags, reference.TagNameOnly(ref).String())
+
+			digested, err := reference.WithDigest(reference.TrimNamed(ref), target)
+			if err != nil {
+				logger.WithError(err).Error("failed to create digested reference")
+			} else {
+				repoDigests = append(repoDigests, digested.String())
+			}
+		}
+
 		summaries = append(summaries, &types.ImageSummary{
 			ParentID:    "",
-			ID:          img.Target().Digest.String(),
-			Created:     img.Metadata().CreatedAt.Unix(),
-			RepoDigests: []string{img.Name() + "@" + img.Target().Digest.String()}, // "hello-world@sha256:bfea6278a0a267fad2634554f4f0c6f31981eea41c553fdf5a83e95a41d40c38"},
-			RepoTags:    []string{img.Name()},
+			ID:          target.String(),
+			Created:     rawImg.CreatedAt.Unix(),
+			RepoDigests: repoDigests,
+			RepoTags:    repoTags,
 			Size:        size,
 			VirtualSize: virtualSize,
 			// -1 indicates that the value has not been set (avoids ambiguity

+ 4 - 0
daemon/containerd/soft_delete.go

@@ -59,3 +59,7 @@ func (i *ImageService) softImageDelete(ctx context.Context, img containerdimages
 func danglingImageName(digest digest.Digest) string {
 	return "moby-dangling@" + digest.String()
 }
+
+func isDanglingImage(image containerdimages.Image) bool {
+	return image.Name == danglingImageName(image.Target.Digest)
+}

+ 0 - 2
daemon/images/image_list.go

@@ -173,8 +173,6 @@ func (i *ImageService) Images(ctx context.Context, opts types.ImageListOptions)
 				if opts.Filters.Contains("reference") { // skip images with no references if filtering by reference
 					continue
 				}
-				summary.RepoDigests = []string{"<none>@<none>"}
-				summary.RepoTags = []string{"<none>:<none>"}
 			} else {
 				continue
 			}