Browse code

Fix filter by label for docker images

Using Config.Labels to filter images on Labels.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Vincent Demeester authored on 2015/08/22 21:06:48
Showing 3 changed files
... ...
@@ -108,17 +108,19 @@ func (s *TagStore) Images(filterArgs, filter string, all bool) ([]*types.Image,
108 108
 			} else {
109 109
 				// get the boolean list for if only the untagged images are requested
110 110
 				delete(allImages, id)
111
-				if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) {
112
-					continue
111
+
112
+				if len(imageFilters["label"]) > 0 {
113
+					if image.Config == nil {
114
+						// Very old image that do not have image.Config (or even labels)
115
+						continue
116
+					}
117
+					// We are now sure image.Config is not nil
118
+					if !imageFilters.MatchKVList("label", image.Config.Labels) {
119
+						continue
120
+					}
113 121
 				}
114 122
 				if filtTagged {
115
-					newImage := new(types.Image)
116
-					newImage.ParentID = image.Parent
117
-					newImage.ID = image.ID
118
-					newImage.Created = image.Created.Unix()
119
-					newImage.Size = image.Size
120
-					newImage.VirtualSize = s.graph.GetParentsSize(image) + image.Size
121
-					newImage.Labels = image.ContainerConfig.Labels
123
+					newImage := newImage(image, s.graph.GetParentsSize(image))
122 124
 
123 125
 					if utils.DigestReference(ref) {
124 126
 						newImage.RepoTags = []string{}
... ...
@@ -144,18 +146,19 @@ func (s *TagStore) Images(filterArgs, filter string, all bool) ([]*types.Image,
144 144
 	// Display images which aren't part of a repository/tag
145 145
 	if filter == "" || filtLabel {
146 146
 		for _, image := range allImages {
147
-			if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) {
148
-				continue
147
+			if len(imageFilters["label"]) > 0 {
148
+				if image.Config == nil {
149
+					// Very old image that do not have image.Config (or even labels)
150
+					continue
151
+				}
152
+				// We are now sure image.Config is not nil
153
+				if !imageFilters.MatchKVList("label", image.Config.Labels) {
154
+					continue
155
+				}
149 156
 			}
150
-			newImage := new(types.Image)
151
-			newImage.ParentID = image.Parent
157
+			newImage := newImage(image, s.graph.GetParentsSize(image))
152 158
 			newImage.RepoTags = []string{"<none>:<none>"}
153 159
 			newImage.RepoDigests = []string{"<none>@<none>"}
154
-			newImage.ID = image.ID
155
-			newImage.Created = image.Created.Unix()
156
-			newImage.Size = image.Size
157
-			newImage.VirtualSize = s.graph.GetParentsSize(image) + image.Size
158
-			newImage.Labels = image.ContainerConfig.Labels
159 160
 
160 161
 			images = append(images, newImage)
161 162
 		}
... ...
@@ -165,3 +168,16 @@ func (s *TagStore) Images(filterArgs, filter string, all bool) ([]*types.Image,
165 165
 
166 166
 	return images, nil
167 167
 }
168
+
169
+func newImage(image *image.Image, parentSize int64) *types.Image {
170
+	newImage := new(types.Image)
171
+	newImage.ParentID = image.Parent
172
+	newImage.ID = image.ID
173
+	newImage.Created = image.Created.Unix()
174
+	newImage.Size = image.Size
175
+	newImage.VirtualSize = parentSize + image.Size
176
+	if image.Config != nil {
177
+		newImage.Labels = image.Config.Labels
178
+	}
179
+	return newImage
180
+}
... ...
@@ -100,35 +100,40 @@ func (s *DockerSuite) TestImagesFilterLabel(c *check.C) {
100 100
 	image1ID, err := buildImage(imageName1,
101 101
 		`FROM scratch
102 102
 		 LABEL match me`, true)
103
-	if err != nil {
104
-		c.Fatal(err)
105
-	}
103
+	c.Assert(err, check.IsNil)
106 104
 
107 105
 	image2ID, err := buildImage(imageName2,
108 106
 		`FROM scratch
109 107
 		 LABEL match="me too"`, true)
110
-	if err != nil {
111
-		c.Fatal(err)
112
-	}
108
+	c.Assert(err, check.IsNil)
113 109
 
114 110
 	image3ID, err := buildImage(imageName3,
115 111
 		`FROM scratch
116 112
 		 LABEL nomatch me`, true)
117
-	if err != nil {
118
-		c.Fatal(err)
119
-	}
113
+	c.Assert(err, check.IsNil)
120 114
 
121 115
 	out, _ := dockerCmd(c, "images", "--no-trunc", "-q", "-f", "label=match")
122 116
 	out = strings.TrimSpace(out)
123
-	if (!strings.Contains(out, image1ID) && !strings.Contains(out, image2ID)) || strings.Contains(out, image3ID) {
124
-		c.Fatalf("Expected ids %s,%s got %s", image1ID, image2ID, out)
125
-	}
117
+	c.Assert(out, check.Matches, fmt.Sprintf("[\\s\\w]*%s[\\s\\w]*", image1ID))
118
+	c.Assert(out, check.Matches, fmt.Sprintf("[\\s\\w]*%s[\\s\\w]*", image2ID))
119
+	c.Assert(out, check.Not(check.Matches), fmt.Sprintf("[\\s\\w]*%s[\\s\\w]*", image3ID))
126 120
 
127 121
 	out, _ = dockerCmd(c, "images", "--no-trunc", "-q", "-f", "label=match=me too")
128 122
 	out = strings.TrimSpace(out)
129
-	if out != image2ID {
130
-		c.Fatalf("Expected %s got %s", image2ID, out)
131
-	}
123
+	c.Assert(out, check.Equals, image2ID)
124
+}
125
+
126
+// Regression : #15659
127
+func (s *DockerSuite) TestImagesFilterLabelWithCommit(c *check.C) {
128
+	// Create a container
129
+	dockerCmd(c, "run", "--name", "bar", "busybox", "/bin/sh")
130
+	// Commit with labels "using changes"
131
+	out, _ := dockerCmd(c, "commit", "-c", "LABEL foo.version=1.0.0-1", "-c", "LABEL foo.name=bar", "-c", "LABEL foo.author=starlord", "bar", "bar:1.0.0-1")
132
+	imageID := strings.TrimSpace(out)
133
+
134
+	out, _ = dockerCmd(c, "images", "--no-trunc", "-q", "-f", "label=foo.version=1.0.0-1")
135
+	out = strings.TrimSpace(out)
136
+	c.Assert(out, check.Equals, imageID)
132 137
 }
133 138
 
134 139
 func (s *DockerSuite) TestImagesFilterSpaceTrimCase(c *check.C) {
... ...
@@ -104,6 +104,10 @@ func (s *DockerSuite) TestSaveImageId(c *check.C) {
104 104
 	out, _ = dockerCmd(c, "images", "-q", repoName)
105 105
 	cleanedShortImageID := strings.TrimSpace(out)
106 106
 
107
+	// Make sure IDs are not empty
108
+	c.Assert(cleanedLongImageID, check.Not(check.Equals), "", check.Commentf("Id should not be empty."))
109
+	c.Assert(cleanedShortImageID, check.Not(check.Equals), "", check.Commentf("Id should not be empty."))
110
+
107 111
 	saveCmd := exec.Command(dockerBinary, "save", cleanedShortImageID)
108 112
 	tarCmd := exec.Command("tar", "t")
109 113