Browse code

Apply build labels to images with only a FROM tag.

Signed-off-by: David Calavera <david.calavera@gmail.com>

David Calavera authored on 2016/03/31 06:26:02
Showing 4 changed files
... ...
@@ -222,6 +222,17 @@ func (b *Builder) build(config *types.ImageBuildOptions, context builder.Context
222 222
 			}
223 223
 			return "", err
224 224
 		}
225
+
226
+		// Commit the layer when there are only one children in
227
+		// the dockerfile, this is only the `FROM` tag, and
228
+		// build labels. Otherwise, the new image won't be
229
+		// labeled properly.
230
+		// Commit here, so the ID of the final image is reported
231
+		// properly.
232
+		if len(b.dockerfile.Children) == 1 && len(b.options.Labels) > 0 {
233
+			b.commit("", b.runConfig.Cmd, "")
234
+		}
235
+
225 236
 		shortImgID = stringid.TruncateID(b.image)
226 237
 		fmt.Fprintf(b.Stdout, " ---> %s\n", shortImgID)
227 238
 		if b.options.Remove {
... ...
@@ -418,7 +418,20 @@ func (b *Builder) processImageFrom(img builder.Image) error {
418 418
 		b.image = img.ImageID()
419 419
 
420 420
 		if img.RunConfig() != nil {
421
-			b.runConfig = img.RunConfig()
421
+			imgConfig := *img.RunConfig()
422
+			// inherit runConfig labels from the current
423
+			// state if they've been set already.
424
+			// Ensures that images with only a FROM
425
+			// get the labels populated properly.
426
+			if b.runConfig.Labels != nil {
427
+				if imgConfig.Labels == nil {
428
+					imgConfig.Labels = make(map[string]string)
429
+				}
430
+				for k, v := range b.runConfig.Labels {
431
+					imgConfig.Labels[k] = v
432
+				}
433
+			}
434
+			b.runConfig = &imgConfig
422 435
 		}
423 436
 	}
424 437
 
... ...
@@ -6680,11 +6680,9 @@ func (s *DockerSuite) TestBuildLabel(c *check.C) {
6680 6680
 	_, err := buildImage(name, `
6681 6681
   FROM `+minimalBaseImage()+`
6682 6682
   LABEL default foo
6683
-`, false, []string{"--label", testLabel}...)
6683
+`, false, "--label", testLabel)
6684 6684
 
6685
-	if err != nil {
6686
-		c.Fatal("error building image with labels", err)
6687
-	}
6685
+	c.Assert(err, checker.IsNil)
6688 6686
 
6689 6687
 	res := inspectFieldJSON(c, name, "Config.Labels")
6690 6688
 
... ...
@@ -6699,6 +6697,28 @@ func (s *DockerSuite) TestBuildLabel(c *check.C) {
6699 6699
 	}
6700 6700
 }
6701 6701
 
6702
+func (s *DockerSuite) TestBuildLabelOneNode(c *check.C) {
6703
+	name := "testbuildlabel"
6704
+
6705
+	_, err := buildImage(name, "FROM busybox", false, "--label", "foo=bar")
6706
+
6707
+	c.Assert(err, checker.IsNil)
6708
+
6709
+	res, err := inspectImage(name, "json .Config.Labels")
6710
+	c.Assert(err, checker.IsNil)
6711
+	var labels map[string]string
6712
+
6713
+	if err := json.Unmarshal([]byte(res), &labels); err != nil {
6714
+		c.Fatal(err)
6715
+	}
6716
+
6717
+	v, ok := labels["foo"]
6718
+	if !ok {
6719
+		c.Fatal("label `foo` not found in image")
6720
+	}
6721
+	c.Assert(v, checker.Equals, "bar")
6722
+}
6723
+
6702 6724
 func (s *DockerSuite) TestBuildLabelCacheCommit(c *check.C) {
6703 6725
 	name := "testbuildlabelcachecommit"
6704 6726
 	testLabel := "foo"
... ...
@@ -6713,11 +6733,9 @@ func (s *DockerSuite) TestBuildLabelCacheCommit(c *check.C) {
6713 6713
 	_, err := buildImage(name, `
6714 6714
   FROM `+minimalBaseImage()+`
6715 6715
   LABEL default foo
6716
-`, true, []string{"--label", testLabel}...)
6716
+`, true, "--label", testLabel)
6717 6717
 
6718
-	if err != nil {
6719
-		c.Fatal("error building image with labels", err)
6720
-	}
6718
+	c.Assert(err, checker.IsNil)
6721 6719
 
6722 6720
 	res := inspectFieldJSON(c, name, "Config.Labels")
6723 6721
 
... ...
@@ -890,6 +890,21 @@ func inspectMountPointJSON(j, destination string) (types.MountPoint, error) {
890 890
 	return *m, nil
891 891
 }
892 892
 
893
+func inspectImage(name, filter string) (string, error) {
894
+	args := []string{"inspect", "--type", "image"}
895
+	if filter != "" {
896
+		format := fmt.Sprintf("{{%s}}", filter)
897
+		args = append(args, "-f", format)
898
+	}
899
+	args = append(args, name)
900
+	inspectCmd := exec.Command(dockerBinary, args...)
901
+	out, exitCode, err := runCommandWithOutput(inspectCmd)
902
+	if err != nil || exitCode != 0 {
903
+		return "", fmt.Errorf("failed to inspect %s: %s", name, out)
904
+	}
905
+	return strings.TrimSpace(out), nil
906
+}
907
+
893 908
 func getIDByName(name string) (string, error) {
894 909
 	return inspectFieldWithError(name, "Id")
895 910
 }