Browse code

Cleanup in dispatcher.env

Remove commented code blocks
Remove some duplication in comparing and restructuring env

Signed-off-by: Daniel Nephin <dnephin@docker.com>

Daniel Nephin authored on 2017/04/05 01:28:59
Showing 9 changed files
... ...
@@ -2,7 +2,6 @@ package dockerfile
2 2
 
3 3
 import (
4 4
 	"bytes"
5
-	"errors"
6 5
 	"fmt"
7 6
 	"io"
8 7
 	"io/ioutil"
... ...
@@ -20,7 +19,7 @@ import (
20 20
 	"github.com/docker/docker/builder/dockerfile/parser"
21 21
 	"github.com/docker/docker/image"
22 22
 	"github.com/docker/docker/pkg/stringid"
23
-	perrors "github.com/pkg/errors"
23
+	"github.com/pkg/errors"
24 24
 	"golang.org/x/net/context"
25 25
 )
26 26
 
... ...
@@ -220,7 +219,7 @@ func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (stri
220 220
 	total := len(dockerfile.Children)
221 221
 	for _, n := range dockerfile.Children {
222 222
 		if err := b.checkDispatch(n, false); err != nil {
223
-			return "", perrors.Wrapf(err, "Dockerfile parse error line %d", n.StartLine)
223
+			return "", errors.Wrapf(err, "Dockerfile parse error line %d", n.StartLine)
224 224
 		}
225 225
 	}
226 226
 
... ...
@@ -253,7 +252,7 @@ func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (stri
253 253
 	}
254 254
 
255 255
 	if b.options.Target != "" && !b.imageContexts.isCurrentTarget(b.options.Target) {
256
-		return "", perrors.Errorf("failed to reach build target %s in Dockerfile", b.options.Target)
256
+		return "", errors.Errorf("failed to reach build target %s in Dockerfile", b.options.Target)
257 257
 	}
258 258
 
259 259
 	b.warnOnUnusedBuildArgs()
... ...
@@ -269,7 +268,7 @@ func (b *Builder) build(stdout io.Writer, stderr io.Writer, out io.Writer) (stri
269 269
 		}
270 270
 		b.image, err = b.docker.SquashImage(b.image, fromID)
271 271
 		if err != nil {
272
-			return "", perrors.Wrap(err, "error squashing image")
272
+			return "", errors.Wrap(err, "error squashing image")
273 273
 		}
274 274
 	}
275 275
 
... ...
@@ -16,6 +16,7 @@ import (
16 16
 	"strings"
17 17
 	"time"
18 18
 
19
+	"bytes"
19 20
 	"github.com/Sirupsen/logrus"
20 21
 	"github.com/docker/docker/api"
21 22
 	"github.com/docker/docker/api/types"
... ...
@@ -46,45 +47,22 @@ func env(b *Builder, args []string, attributes map[string]bool, original string)
46 46
 		return err
47 47
 	}
48 48
 
49
-	// TODO/FIXME/NOT USED
50
-	// Just here to show how to use the builder flags stuff within the
51
-	// context of a builder command. Will remove once we actually add
52
-	// a builder command to something!
53
-	/*
54
-		flBool1 := b.flags.AddBool("bool1", false)
55
-		flStr1 := b.flags.AddString("str1", "HI")
56
-
57
-		if err := b.flags.Parse(); err != nil {
58
-			return err
59
-		}
60
-
61
-		fmt.Printf("Bool1:%v\n", flBool1)
62
-		fmt.Printf("Str1:%v\n", flStr1)
63
-	*/
64
-
65
-	commitStr := "ENV"
66
-
67
-	for j := 0; j < len(args); j++ {
68
-		// name  ==> args[j]
69
-		// value ==> args[j+1]
49
+	commitMessage := bytes.NewBufferString("ENV")
70 50
 
51
+	for j := 0; j < len(args); j += 2 {
71 52
 		if len(args[j]) == 0 {
72 53
 			return errBlankCommandNames("ENV")
73 54
 		}
74
-		newVar := args[j] + "=" + args[j+1] + ""
75
-		commitStr += " " + newVar
55
+		name := args[j]
56
+		value := args[j+1]
57
+		newVar := name + "=" + value
58
+		commitMessage.WriteString(" " + newVar)
76 59
 
77 60
 		gotOne := false
78 61
 		for i, envVar := range b.runConfig.Env {
79 62
 			envParts := strings.SplitN(envVar, "=", 2)
80 63
 			compareFrom := envParts[0]
81
-			compareTo := args[j]
82
-			if runtime.GOOS == "windows" {
83
-				// Case insensitive environment variables on Windows
84
-				compareFrom = strings.ToUpper(compareFrom)
85
-				compareTo = strings.ToUpper(compareTo)
86
-			}
87
-			if compareFrom == compareTo {
64
+			if equalEnvKeys(compareFrom, name) {
88 65
 				b.runConfig.Env[i] = newVar
89 66
 				gotOne = true
90 67
 				break
... ...
@@ -93,10 +71,9 @@ func env(b *Builder, args []string, attributes map[string]bool, original string)
93 93
 		if !gotOne {
94 94
 			b.runConfig.Env = append(b.runConfig.Env, newVar)
95 95
 		}
96
-		j++
97 96
 	}
98 97
 
99
-	return b.commit("", b.runConfig.Cmd, commitStr)
98
+	return b.commit("", b.runConfig.Cmd, commitMessage.String())
100 99
 }
101 100
 
102 101
 // MAINTAINER some text <maybe@an.email.address>
... ...
@@ -440,6 +417,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
440 440
 		return err
441 441
 	}
442 442
 
443
+	// FIXME: this is duplicated with the defer above in this function (i think?)
443 444
 	// revert to original config environment and set the command string to
444 445
 	// have the build-time env vars in it (if any) so that future cache look-ups
445 446
 	// properly match it.
... ...
@@ -133,27 +133,34 @@ func TestCommandseBlankNames(t *testing.T) {
133 133
 }
134 134
 
135 135
 func TestEnv2Variables(t *testing.T) {
136
-	variables := []string{"var1", "val1", "var2", "val2"}
137
-
138
-	bflags := &BFlags{}
139
-	config := &container.Config{}
136
+	b := newBuilderWithMockBackend()
137
+	b.disableCommit = true
140 138
 
141
-	b := &Builder{flags: bflags, runConfig: config, disableCommit: true}
139
+	args := []string{"var1", "val1", "var2", "val2"}
140
+	err := env(b, args, nil, "")
141
+	assert.NilError(t, err)
142 142
 
143
-	if err := env(b, variables, nil, ""); err != nil {
144
-		t.Fatalf("Error when executing env: %s", err.Error())
143
+	expected := []string{
144
+		fmt.Sprintf("%s=%s", args[0], args[1]),
145
+		fmt.Sprintf("%s=%s", args[2], args[3]),
145 146
 	}
147
+	assert.DeepEqual(t, b.runConfig.Env, expected)
148
+}
146 149
 
147
-	expectedVar1 := fmt.Sprintf("%s=%s", variables[0], variables[1])
148
-	expectedVar2 := fmt.Sprintf("%s=%s", variables[2], variables[3])
150
+func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
151
+	b := newBuilderWithMockBackend()
152
+	b.disableCommit = true
153
+	b.runConfig.Env = []string{"var1=old", "var2=fromenv"}
149 154
 
150
-	if b.runConfig.Env[0] != expectedVar1 {
151
-		t.Fatalf("Wrong env output for first variable. Got: %s. Should be: %s", b.runConfig.Env[0], expectedVar1)
152
-	}
155
+	args := []string{"var1", "val1"}
156
+	err := env(b, args, nil, "")
157
+	assert.NilError(t, err)
153 158
 
154
-	if b.runConfig.Env[1] != expectedVar2 {
155
-		t.Fatalf("Wrong env output for second variable. Got: %s, Should be: %s", b.runConfig.Env[1], expectedVar2)
159
+	expected := []string{
160
+		fmt.Sprintf("%s=%s", args[0], args[1]),
161
+		"var2=fromenv",
156 162
 	}
163
+	assert.DeepEqual(t, b.runConfig.Env, expected)
157 164
 }
158 165
 
159 166
 func TestMaintainer(t *testing.T) {
... ...
@@ -26,3 +26,9 @@ func normaliseWorkdir(current string, requested string) (string, error) {
26 26
 func errNotJSON(command, _ string) error {
27 27
 	return fmt.Errorf("%s requires the arguments to be in JSON form", command)
28 28
 }
29
+
30
+// equalEnvKeys compare two strings and returns true if they are equal. On
31
+// Windows this comparison is case insensitive.
32
+func equalEnvKeys(from, to string) bool {
33
+	return from == to
34
+}
... ...
@@ -85,3 +85,9 @@ func errNotJSON(command, original string) error {
85 85
 	}
86 86
 	return fmt.Errorf("%s requires the arguments to be in JSON form%s", command, extra)
87 87
 }
88
+
89
+// equalEnvKeys compare two strings and returns true if they are equal. On
90
+// Windows this comparison is case insensitive.
91
+func equalEnvKeys(from, to string) bool {
92
+	return strings.ToUpper(from) == strings.ToUpper(to)
93
+}
... ...
@@ -20,13 +20,13 @@
20 20
 package dockerfile
21 21
 
22 22
 import (
23
-	"errors"
24 23
 	"fmt"
25 24
 	"strings"
26 25
 
27 26
 	"github.com/docker/docker/builder/dockerfile/command"
28 27
 	"github.com/docker/docker/builder/dockerfile/parser"
29
-	runconfigopts "github.com/docker/docker/runconfig/opts"
28
+	"github.com/docker/docker/runconfig/opts"
29
+	"github.com/pkg/errors"
30 30
 )
31 31
 
32 32
 // Environment variable interpolation will happen on these statements only.
... ...
@@ -187,7 +187,7 @@ func (b *Builder) evaluateEnv(cmd string, str string, envs []string) ([]string,
187 187
 // args that are not overriden by runConfig environment variables.
188 188
 func (b *Builder) buildArgsWithoutConfigEnv() []string {
189 189
 	envs := []string{}
190
-	configEnv := runconfigopts.ConvertKVStringsToMap(b.runConfig.Env)
190
+	configEnv := b.runConfigEnvMapping()
191 191
 
192 192
 	for key, val := range b.buildArgs.GetAllAllowed() {
193 193
 		if _, ok := configEnv[key]; !ok {
... ...
@@ -197,6 +197,10 @@ func (b *Builder) buildArgsWithoutConfigEnv() []string {
197 197
 	return envs
198 198
 }
199 199
 
200
+func (b *Builder) runConfigEnvMapping() map[string]string {
201
+	return opts.ConvertKVStringsToMap(b.runConfig.Env)
202
+}
203
+
200 204
 // checkDispatch does a simple check for syntax errors of the Dockerfile.
201 205
 // Because some of the instructions can only be validated through runtime,
202 206
 // arg, env, etc., this syntax check will not be complete and could not replace
... ...
@@ -235,5 +239,5 @@ func (b *Builder) checkDispatch(ast *parser.Node, onbuild bool) error {
235 235
 		return nil
236 236
 	}
237 237
 
238
-	return fmt.Errorf("Unknown instruction: %s", upperCasedCmd)
238
+	return errors.Errorf("unknown instruction: %s", upperCasedCmd)
239 239
 }
... ...
@@ -35,7 +35,6 @@ import (
35 35
 	"github.com/docker/docker/pkg/system"
36 36
 	"github.com/docker/docker/pkg/tarsum"
37 37
 	"github.com/docker/docker/pkg/urlutil"
38
-	"github.com/docker/docker/runconfig/opts"
39 38
 	"github.com/pkg/errors"
40 39
 )
41 40
 
... ...
@@ -433,11 +432,7 @@ func (b *Builder) processImageFrom(img builder.Image) error {
433 433
 	// Check to see if we have a default PATH, note that windows won't
434 434
 	// have one as it's set by HCS
435 435
 	if system.DefaultPathEnv != "" {
436
-		// Convert the slice of strings that represent the current list
437
-		// of env vars into a map so we can see if PATH is already set.
438
-		// If it's not set then go ahead and give it our default value
439
-		configEnv := opts.ConvertKVStringsToMap(b.runConfig.Env)
440
-		if _, ok := configEnv["PATH"]; !ok {
436
+		if _, ok := b.runConfigEnvMapping()["PATH"]; !ok {
441 437
 			b.runConfig.Env = append(b.runConfig.Env,
442 438
 				"PATH="+system.DefaultPathEnv)
443 439
 		}
... ...
@@ -8,7 +8,6 @@ package dockerfile
8 8
 
9 9
 import (
10 10
 	"fmt"
11
-	"runtime"
12 11
 	"strings"
13 12
 	"text/scanner"
14 13
 	"unicode"
... ...
@@ -296,17 +295,10 @@ func (sw *shellWord) processName() string {
296 296
 }
297 297
 
298 298
 func (sw *shellWord) getEnv(name string) string {
299
-	if runtime.GOOS == "windows" {
300
-		// Case-insensitive environment variables on Windows
301
-		name = strings.ToUpper(name)
302
-	}
303 299
 	for _, env := range sw.envs {
304 300
 		i := strings.Index(env, "=")
305 301
 		if i < 0 {
306
-			if runtime.GOOS == "windows" {
307
-				env = strings.ToUpper(env)
308
-			}
309
-			if name == env {
302
+			if equalEnvKeys(name, env) {
310 303
 				// Should probably never get here, but just in case treat
311 304
 				// it like "var" and "var=" are the same
312 305
 				return ""
... ...
@@ -314,10 +306,7 @@ func (sw *shellWord) getEnv(name string) string {
314 314
 			continue
315 315
 		}
316 316
 		compareName := env[:i]
317
-		if runtime.GOOS == "windows" {
318
-			compareName = strings.ToUpper(compareName)
319
-		}
320
-		if name != compareName {
317
+		if !equalEnvKeys(name, compareName) {
321 318
 			continue
322 319
 		}
323 320
 		return env[i+1:]
... ...
@@ -6156,7 +6156,7 @@ func (s *DockerSuite) TestBuildCopyFromPreviousFromWindows(c *check.C) {
6156 6156
 func (s *DockerSuite) TestBuildCopyFromForbidWindowsSystemPaths(c *check.C) {
6157 6157
 	testRequires(c, DaemonIsWindows)
6158 6158
 	dockerfile := `
6159
-		FROM ` + testEnv.MinimalBaseImage() + `		
6159
+		FROM ` + testEnv.MinimalBaseImage() + `
6160 6160
 		FROM ` + testEnv.MinimalBaseImage() + `
6161 6161
 		COPY --from=0 %s c:\\oscopy
6162 6162
 		`
... ...
@@ -6173,7 +6173,7 @@ func (s *DockerSuite) TestBuildCopyFromForbidWindowsSystemPaths(c *check.C) {
6173 6173
 func (s *DockerSuite) TestBuildCopyFromForbidWindowsRelativePaths(c *check.C) {
6174 6174
 	testRequires(c, DaemonIsWindows)
6175 6175
 	dockerfile := `
6176
-		FROM ` + testEnv.MinimalBaseImage() + `		
6176
+		FROM ` + testEnv.MinimalBaseImage() + `
6177 6177
 		FROM ` + testEnv.MinimalBaseImage() + `
6178 6178
 		COPY --from=0 %s c:\\oscopy
6179 6179
 		`
... ...
@@ -6192,7 +6192,7 @@ func (s *DockerSuite) TestBuildCopyFromWindowsIsCaseInsensitive(c *check.C) {
6192 6192
 	testRequires(c, DaemonIsWindows)
6193 6193
 	dockerfile := `
6194 6194
 		FROM ` + testEnv.MinimalBaseImage() + `
6195
-		COPY foo /	
6195
+		COPY foo /
6196 6196
 		FROM ` + testEnv.MinimalBaseImage() + `
6197 6197
 		COPY --from=0 c:\\fOo c:\\copied
6198 6198
 		RUN type c:\\copied
... ...
@@ -6351,23 +6351,23 @@ func (s *DockerSuite) TestBuildLineErrorOnBuild(c *check.C) {
6351 6351
 }
6352 6352
 
6353 6353
 // FIXME(vdemeester) should be a unit test
6354
-func (s *DockerSuite) TestBuildLineErrorUknownInstruction(c *check.C) {
6354
+func (s *DockerSuite) TestBuildLineErrorUnknownInstruction(c *check.C) {
6355 6355
 	name := "test_build_line_error_unknown_instruction"
6356
-	buildImage(name, build.WithDockerfile(`FROM busybox
6356
+	cli.Docker(cli.Build(name), build.WithDockerfile(`FROM busybox
6357 6357
   RUN echo hello world
6358 6358
   NOINSTRUCTION echo ba
6359 6359
   RUN echo hello
6360 6360
   ERROR
6361 6361
   `)).Assert(c, icmd.Expected{
6362 6362
 		ExitCode: 1,
6363
-		Err:      "Dockerfile parse error line 3: Unknown instruction: NOINSTRUCTION",
6363
+		Err:      "Dockerfile parse error line 3: unknown instruction: NOINSTRUCTION",
6364 6364
 	})
6365 6365
 }
6366 6366
 
6367 6367
 // FIXME(vdemeester) should be a unit test
6368 6368
 func (s *DockerSuite) TestBuildLineErrorWithEmptyLines(c *check.C) {
6369 6369
 	name := "test_build_line_error_with_empty_lines"
6370
-	buildImage(name, build.WithDockerfile(`
6370
+	cli.Docker(cli.Build(name), build.WithDockerfile(`
6371 6371
   FROM busybox
6372 6372
 
6373 6373
   RUN echo hello world
... ...
@@ -6377,21 +6377,21 @@ func (s *DockerSuite) TestBuildLineErrorWithEmptyLines(c *check.C) {
6377 6377
   CMD ["/bin/init"]
6378 6378
   `)).Assert(c, icmd.Expected{
6379 6379
 		ExitCode: 1,
6380
-		Err:      "Dockerfile parse error line 6: Unknown instruction: NOINSTRUCTION",
6380
+		Err:      "Dockerfile parse error line 6: unknown instruction: NOINSTRUCTION",
6381 6381
 	})
6382 6382
 }
6383 6383
 
6384 6384
 // FIXME(vdemeester) should be a unit test
6385 6385
 func (s *DockerSuite) TestBuildLineErrorWithComments(c *check.C) {
6386 6386
 	name := "test_build_line_error_with_comments"
6387
-	buildImage(name, build.WithDockerfile(`FROM busybox
6387
+	cli.Docker(cli.Build(name), build.WithDockerfile(`FROM busybox
6388 6388
   # This will print hello world
6389 6389
   # and then ba
6390 6390
   RUN echo hello world
6391 6391
   NOINSTRUCTION echo ba
6392 6392
   `)).Assert(c, icmd.Expected{
6393 6393
 		ExitCode: 1,
6394
-		Err:      "Dockerfile parse error line 5: Unknown instruction: NOINSTRUCTION",
6394
+		Err:      "Dockerfile parse error line 5: unknown instruction: NOINSTRUCTION",
6395 6395
 	})
6396 6396
 }
6397 6397