Signed-off-by: John Howard <jhoward@microsoft.com>
John Howard authored on 2016/05/03 10:33:59... | ... |
@@ -9,8 +9,6 @@ package dockerfile |
9 | 9 |
|
10 | 10 |
import ( |
11 | 11 |
"fmt" |
12 |
- "os" |
|
13 |
- "path/filepath" |
|
14 | 12 |
"regexp" |
15 | 13 |
"runtime" |
16 | 14 |
"sort" |
... | ... |
@@ -20,7 +18,6 @@ import ( |
20 | 20 |
"github.com/docker/docker/api" |
21 | 21 |
"github.com/docker/docker/builder" |
22 | 22 |
"github.com/docker/docker/pkg/signal" |
23 |
- "github.com/docker/docker/pkg/system" |
|
24 | 23 |
runconfigopts "github.com/docker/docker/runconfig/opts" |
25 | 24 |
"github.com/docker/engine-api/types/container" |
26 | 25 |
"github.com/docker/engine-api/types/strslice" |
... | ... |
@@ -257,45 +254,17 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str |
257 | 257 |
return errExactlyOneArgument("WORKDIR") |
258 | 258 |
} |
259 | 259 |
|
260 |
- if err := b.flags.Parse(); err != nil { |
|
260 |
+ err := b.flags.Parse() |
|
261 |
+ if err != nil { |
|
261 | 262 |
return err |
262 | 263 |
} |
263 | 264 |
|
264 | 265 |
// This is from the Dockerfile and will not necessarily be in platform |
265 | 266 |
// specific semantics, hence ensure it is converted. |
266 |
- workdir := filepath.FromSlash(args[0]) |
|
267 |
- current := filepath.FromSlash(b.runConfig.WorkingDir) |
|
268 |
- if runtime.GOOS == "windows" { |
|
269 |
- // Windows is a little more complicated than Linux. This code ensures |
|
270 |
- // we end up with a workdir which is consistent in terms of platform |
|
271 |
- // semantics. This means C:\somefolder, specifically in the format: |
|
272 |
- // UPPERCASEDriveLetter-Colon-Backslash-FolderName. We are already |
|
273 |
- // guaranteed that `current`, if set, is consistent. This allows us to |
|
274 |
- // cope correctly with any of the following in a Dockerfile: |
|
275 |
- // WORKDIR a --> C:\a |
|
276 |
- // WORKDIR c:\\foo --> C:\foo |
|
277 |
- // WORKDIR \\foo --> C:\foo |
|
278 |
- // WORKDIR /foo --> C:\foo |
|
279 |
- // WORKDIR c:\\foo \ WORKDIR bar --> C:\foo --> C:\foo\bar |
|
280 |
- // WORKDIR C:/foo \ WORKDIR bar --> C:\foo --> C:\foo\bar |
|
281 |
- // WORKDIR C:/foo \ WORKDIR \\bar --> C:\foo --> C:\bar |
|
282 |
- // WORKDIR /foo \ WORKDIR c:/bar --> C:\foo --> C:\bar |
|
283 |
- if len(current) == 0 || system.IsAbs(workdir) { |
|
284 |
- if (workdir[0] == os.PathSeparator) || |
|
285 |
- (len(workdir) > 1 && string(workdir[1]) != ":") || |
|
286 |
- (len(workdir) == 1) { |
|
287 |
- workdir = filepath.Join(`C:\`, workdir) |
|
288 |
- } |
|
289 |
- } else { |
|
290 |
- workdir = filepath.Join(current, workdir) |
|
291 |
- } |
|
292 |
- workdir = strings.ToUpper(string(workdir[0])) + workdir[1:] // Upper-case drive letter |
|
293 |
- } else { |
|
294 |
- if !filepath.IsAbs(workdir) { |
|
295 |
- workdir = filepath.Join(string(os.PathSeparator), current, workdir) |
|
296 |
- } |
|
267 |
+ b.runConfig.WorkingDir, err = normaliseWorkdir(b.runConfig.WorkingDir, args[0]) |
|
268 |
+ if err != nil { |
|
269 |
+ return err |
|
297 | 270 |
} |
298 |
- b.runConfig.WorkingDir = workdir |
|
299 | 271 |
|
300 | 272 |
return b.commit("", b.runConfig.Cmd, fmt.Sprintf("WORKDIR %v", workdir)) |
301 | 273 |
} |
302 | 274 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,23 @@ |
0 |
+// +build !windows |
|
1 |
+ |
|
2 |
+package dockerfile |
|
3 |
+ |
|
4 |
+import ( |
|
5 |
+ "fmt" |
|
6 |
+ "os" |
|
7 |
+ "path/filepath" |
|
8 |
+) |
|
9 |
+ |
|
10 |
+// normaliseWorkdir normalises a user requested working directory in a |
|
11 |
+// platform sematically consistent way. |
|
12 |
+func normaliseWorkdir(current string, requested string) (string, error) { |
|
13 |
+ if requested == "" { |
|
14 |
+ return "", fmt.Errorf("cannot normalise nothing") |
|
15 |
+ } |
|
16 |
+ current = filepath.FromSlash(current) |
|
17 |
+ requested = filepath.FromSlash(requested) |
|
18 |
+ if !filepath.IsAbs(requested) { |
|
19 |
+ return filepath.Join(string(os.PathSeparator), current, requested), nil |
|
20 |
+ } |
|
21 |
+ return requested, nil |
|
22 |
+} |
0 | 23 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,45 @@ |
0 |
+package dockerfile |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "fmt" |
|
4 |
+ "os" |
|
5 |
+ "path/filepath" |
|
6 |
+ "strings" |
|
7 |
+ |
|
8 |
+ "github.com/docker/docker/pkg/system" |
|
9 |
+) |
|
10 |
+ |
|
11 |
+// normaliseWorkdir normalises a user requested working directory in a |
|
12 |
+// platform sematically consistent way. |
|
13 |
+func normaliseWorkdir(current string, requested string) (string, error) { |
|
14 |
+ if requested == "" { |
|
15 |
+ return "", fmt.Errorf("cannot normalise nothing") |
|
16 |
+ } |
|
17 |
+ |
|
18 |
+ current = filepath.FromSlash(current) |
|
19 |
+ requested = filepath.FromSlash(requested) |
|
20 |
+ |
|
21 |
+ // Target semantics is C:\somefolder, specifically in the format: |
|
22 |
+ // UPPERCASEDriveLetter-Colon-Backslash-FolderName. We are already |
|
23 |
+ // guaranteed that `current`, if set, is consistent. This allows us to |
|
24 |
+ // cope correctly with any of the following in a Dockerfile: |
|
25 |
+ // WORKDIR a --> C:\a |
|
26 |
+ // WORKDIR c:\\foo --> C:\foo |
|
27 |
+ // WORKDIR \\foo --> C:\foo |
|
28 |
+ // WORKDIR /foo --> C:\foo |
|
29 |
+ // WORKDIR c:\\foo \ WORKDIR bar --> C:\foo --> C:\foo\bar |
|
30 |
+ // WORKDIR C:/foo \ WORKDIR bar --> C:\foo --> C:\foo\bar |
|
31 |
+ // WORKDIR C:/foo \ WORKDIR \\bar --> C:\foo --> C:\bar |
|
32 |
+ // WORKDIR /foo \ WORKDIR c:/bar --> C:\foo --> C:\bar |
|
33 |
+ if len(current) == 0 || system.IsAbs(requested) { |
|
34 |
+ if (requested[0] == os.PathSeparator) || |
|
35 |
+ (len(requested) > 1 && string(requested[1]) != ":") || |
|
36 |
+ (len(requested) == 1) { |
|
37 |
+ requested = filepath.Join(`C:\`, requested) |
|
38 |
+ } |
|
39 |
+ } else { |
|
40 |
+ requested = filepath.Join(current, requested) |
|
41 |
+ } |
|
42 |
+ // Upper-case drive letter |
|
43 |
+ return (strings.ToUpper(string(requested[0])) + requested[1:]), nil |
|
44 |
+} |
0 | 45 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,34 @@ |
0 |
+// +build windows |
|
1 |
+ |
|
2 |
+package dockerfile |
|
3 |
+ |
|
4 |
+import "testing" |
|
5 |
+ |
|
6 |
+func TestNormaliseWorkdir(t *testing.T) { |
|
7 |
+ tests := []struct{ current, requested, expected, etext string }{ |
|
8 |
+ {``, ``, ``, `cannot normalise nothing`}, |
|
9 |
+ {``, `a`, `C:\a`, ``}, |
|
10 |
+ {``, `c:\foo`, `C:\foo`, ``}, |
|
11 |
+ {``, `\foo`, `C:\foo`, ``}, |
|
12 |
+ {``, `/foo`, `C:\foo`, ``}, |
|
13 |
+ {``, `C:/foo`, `C:\foo`, ``}, |
|
14 |
+ {`C:\foo`, `bar`, `C:\foo\bar`, ``}, |
|
15 |
+ {`C:\foo`, `/bar`, `C:\bar`, ``}, |
|
16 |
+ {`C:\foo`, `\bar`, `C:\bar`, ``}, |
|
17 |
+ } |
|
18 |
+ for _, i := range tests { |
|
19 |
+ r, e := normaliseWorkdir(i.current, i.requested) |
|
20 |
+ |
|
21 |
+ if i.etext != "" && e == nil { |
|
22 |
+ t.Fatalf("TestNormaliseWorkingDir Expected error %s", i.etext) |
|
23 |
+ } |
|
24 |
+ |
|
25 |
+ if i.etext != "" && e.Error() != i.etext { |
|
26 |
+ t.Fatalf("TestNormaliseWorkingDir Expected error %s, got %s", i.etext, e.Error()) |
|
27 |
+ } |
|
28 |
+ |
|
29 |
+ if r != i.expected { |
|
30 |
+ t.Fatalf("TestNormaliseWorkingDir Expected %s for %s %s", i.expected, i.current, i.requested) |
|
31 |
+ } |
|
32 |
+ } |
|
33 |
+} |
... | ... |
@@ -200,60 +200,8 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD |
200 | 200 |
|
201 | 201 |
// Twiddle the destination when its a relative path - meaning, make it |
202 | 202 |
// relative to the WORKINGDIR |
203 |
- |
|
204 |
- endsInSlash := strings.HasSuffix(dest, string(os.PathSeparator)) |
|
205 |
- |
|
206 |
- if runtime.GOOS == "windows" { |
|
207 |
- // On Windows, this is more complicated. We are guaranteed that the |
|
208 |
- // WorkingDir is already platform consistent meaning in the format |
|
209 |
- // UPPERCASEDriveLetter-Colon-Backslash-Foldername. However, Windows |
|
210 |
- // for now also has the limitation that ADD/COPY can only be done to |
|
211 |
- // the C: (system) drive, not any drives that might be present as a |
|
212 |
- // result of bind mounts. |
|
213 |
- // |
|
214 |
- // So... if the path specified is Linux-style absolute (/foo or \\foo), |
|
215 |
- // we assume it is the system drive. If it is a Windows-style absolute |
|
216 |
- // (DRIVE:\\foo), error if DRIVE is not C. And finally, ensure we |
|
217 |
- // strip any configured working directories drive letter so that it |
|
218 |
- // can be subsequently legitimately converted to a Windows volume-style |
|
219 |
- // pathname. |
|
220 |
- |
|
221 |
- // Not a typo - filepath.IsAbs, not system.IsAbs on this next check as |
|
222 |
- // we only want to validate where the DriveColon part has been supplied. |
|
223 |
- if filepath.IsAbs(dest) { |
|
224 |
- if strings.ToUpper(string(dest[0])) != "C" { |
|
225 |
- return fmt.Errorf("Windows does not support %s with a destinations not on the system drive (C:)", cmdName) |
|
226 |
- } |
|
227 |
- dest = dest[2:] // Strip the drive letter |
|
228 |
- } |
|
229 |
- |
|
230 |
- // Cannot handle relative where WorkingDir is not the system drive. |
|
231 |
- if len(b.runConfig.WorkingDir) > 0 { |
|
232 |
- if !system.IsAbs(b.runConfig.WorkingDir[2:]) { |
|
233 |
- return fmt.Errorf("Current WorkingDir %s is not platform consistent", b.runConfig.WorkingDir) |
|
234 |
- } |
|
235 |
- if !system.IsAbs(dest) { |
|
236 |
- if string(b.runConfig.WorkingDir[0]) != "C" { |
|
237 |
- return fmt.Errorf("Windows does not support %s with relative paths when WORKDIR is not the system drive", cmdName) |
|
238 |
- } |
|
239 |
- |
|
240 |
- dest = filepath.Join(string(os.PathSeparator), b.runConfig.WorkingDir[2:], dest) |
|
241 |
- |
|
242 |
- // Make sure we preserve any trailing slash |
|
243 |
- if endsInSlash { |
|
244 |
- dest += string(os.PathSeparator) |
|
245 |
- } |
|
246 |
- } |
|
247 |
- } |
|
248 |
- } else { |
|
249 |
- if !system.IsAbs(dest) { |
|
250 |
- dest = filepath.Join(string(os.PathSeparator), filepath.FromSlash(b.runConfig.WorkingDir), dest) |
|
251 |
- |
|
252 |
- // Make sure we preserve any trailing slash |
|
253 |
- if endsInSlash { |
|
254 |
- dest += string(os.PathSeparator) |
|
255 |
- } |
|
256 |
- } |
|
203 |
+ if dest, err = normaliseDest(cmdName, b.runConfig.WorkingDir, dest); err != nil { |
|
204 |
+ return err |
|
257 | 205 |
} |
258 | 206 |
|
259 | 207 |
for _, info := range infos { |
260 | 208 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,26 @@ |
0 |
+// +build !windows |
|
1 |
+ |
|
2 |
+package dockerfile |
|
3 |
+ |
|
4 |
+import ( |
|
5 |
+ "os" |
|
6 |
+ "path/filepath" |
|
7 |
+ "strings" |
|
8 |
+ |
|
9 |
+ "github.com/docker/docker/pkg/system" |
|
10 |
+) |
|
11 |
+ |
|
12 |
+// normaliseDest normalises the destination of a COPY/ADD command in a |
|
13 |
+// platform semantically consistent way. |
|
14 |
+func normaliseDest(cmdName, workingDir, requested string) (string, error) { |
|
15 |
+ dest := filepath.FromSlash(requested) |
|
16 |
+ endsInSlash := strings.HasSuffix(requested, string(os.PathSeparator)) |
|
17 |
+ if !system.IsAbs(requested) { |
|
18 |
+ dest = filepath.Join(string(os.PathSeparator), filepath.FromSlash(workingDir), dest) |
|
19 |
+ // Make sure we preserve any trailing slash |
|
20 |
+ if endsInSlash { |
|
21 |
+ dest += string(os.PathSeparator) |
|
22 |
+ } |
|
23 |
+ } |
|
24 |
+ return dest, nil |
|
25 |
+} |
0 | 26 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,56 @@ |
0 |
+package dockerfile |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "fmt" |
|
4 |
+ "os" |
|
5 |
+ "path/filepath" |
|
6 |
+ "strings" |
|
7 |
+ |
|
8 |
+ "github.com/docker/docker/pkg/system" |
|
9 |
+) |
|
10 |
+ |
|
11 |
+// normaliseDest normalises the destination of a COPY/ADD command in a |
|
12 |
+// platform semantically consistent way. |
|
13 |
+func normaliseDest(cmdName, workingDir, requested string) (string, error) { |
|
14 |
+ dest := filepath.FromSlash(requested) |
|
15 |
+ endsInSlash := strings.HasSuffix(dest, string(os.PathSeparator)) |
|
16 |
+ |
|
17 |
+ // We are guaranteed that the working directory is already consistent, |
|
18 |
+ // However, Windows also has, for now, the limitation that ADD/COPY can |
|
19 |
+ // only be done to the system drive, not any drives that might be present |
|
20 |
+ // as a result of a bind mount. |
|
21 |
+ // |
|
22 |
+ // So... if the path requested is Linux-style absolute (/foo or \\foo), |
|
23 |
+ // we assume it is the system drive. If it is a Windows-style absolute |
|
24 |
+ // (DRIVE:\\foo), error if DRIVE is not C. And finally, ensure we |
|
25 |
+ // strip any configured working directories drive letter so that it |
|
26 |
+ // can be subsequently legitimately converted to a Windows volume-style |
|
27 |
+ // pathname. |
|
28 |
+ |
|
29 |
+ // Not a typo - filepath.IsAbs, not system.IsAbs on this next check as |
|
30 |
+ // we only want to validate where the DriveColon part has been supplied. |
|
31 |
+ if filepath.IsAbs(dest) { |
|
32 |
+ if strings.ToUpper(string(dest[0])) != "C" { |
|
33 |
+ return "", fmt.Errorf("Windows does not support %s with a destinations not on the system drive (C:)", cmdName) |
|
34 |
+ } |
|
35 |
+ dest = dest[2:] // Strip the drive letter |
|
36 |
+ } |
|
37 |
+ |
|
38 |
+ // Cannot handle relative where WorkingDir is not the system drive. |
|
39 |
+ if len(workingDir) > 0 { |
|
40 |
+ if ((len(workingDir) > 1) && !system.IsAbs(workingDir[2:])) || (len(workingDir) == 1) { |
|
41 |
+ return "", fmt.Errorf("Current WorkingDir %s is not platform consistent", workingDir) |
|
42 |
+ } |
|
43 |
+ if !system.IsAbs(dest) { |
|
44 |
+ if string(workingDir[0]) != "C" { |
|
45 |
+ return "", fmt.Errorf("Windows does not support %s with relative paths when WORKDIR is not the system drive", cmdName) |
|
46 |
+ } |
|
47 |
+ dest = filepath.Join(string(os.PathSeparator), workingDir[2:], dest) |
|
48 |
+ // Make sure we preserve any trailing slash |
|
49 |
+ if endsInSlash { |
|
50 |
+ dest += string(os.PathSeparator) |
|
51 |
+ } |
|
52 |
+ } |
|
53 |
+ } |
|
54 |
+ return dest, nil |
|
55 |
+} |
0 | 56 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,51 @@ |
0 |
+// +build windows |
|
1 |
+ |
|
2 |
+package dockerfile |
|
3 |
+ |
|
4 |
+import "testing" |
|
5 |
+ |
|
6 |
+func TestNormaliseDest(t *testing.T) { |
|
7 |
+ tests := []struct{ current, requested, expected, etext string }{ |
|
8 |
+ {``, `D:\`, ``, `Windows does not support TEST with a destinations not on the system drive (C:)`}, |
|
9 |
+ {``, `e:/`, ``, `Windows does not support TEST with a destinations not on the system drive (C:)`}, |
|
10 |
+ {`invalid`, `./c1`, ``, `Current WorkingDir invalid is not platform consistent`}, |
|
11 |
+ {`C:`, ``, ``, `Current WorkingDir C: is not platform consistent`}, |
|
12 |
+ {`C`, ``, ``, `Current WorkingDir C is not platform consistent`}, |
|
13 |
+ {`D:\`, `.`, ``, "Windows does not support TEST with relative paths when WORKDIR is not the system drive"}, |
|
14 |
+ {``, `D`, `D`, ``}, |
|
15 |
+ {``, `./a1`, `.\a1`, ``}, |
|
16 |
+ {``, `.\b1`, `.\b1`, ``}, |
|
17 |
+ {``, `/`, `\`, ``}, |
|
18 |
+ {``, `\`, `\`, ``}, |
|
19 |
+ {``, `c:/`, `\`, ``}, |
|
20 |
+ {``, `c:\`, `\`, ``}, |
|
21 |
+ {``, `.`, `.`, ``}, |
|
22 |
+ {`C:\wdd`, `./a1`, `\wdd\a1`, ``}, |
|
23 |
+ {`C:\wde`, `.\b1`, `\wde\b1`, ``}, |
|
24 |
+ {`C:\wdf`, `/`, `\`, ``}, |
|
25 |
+ {`C:\wdg`, `\`, `\`, ``}, |
|
26 |
+ {`C:\wdh`, `c:/`, `\`, ``}, |
|
27 |
+ {`C:\wdi`, `c:\`, `\`, ``}, |
|
28 |
+ {`C:\wdj`, `.`, `\wdj`, ``}, |
|
29 |
+ {`C:\wdk`, `foo/bar`, `\wdk\foo\bar`, ``}, |
|
30 |
+ {`C:\wdl`, `foo\bar`, `\wdl\foo\bar`, ``}, |
|
31 |
+ {`C:\wdm`, `foo/bar/`, `\wdm\foo\bar\`, ``}, |
|
32 |
+ {`C:\wdn`, `foo\bar/`, `\wdn\foo\bar\`, ``}, |
|
33 |
+ } |
|
34 |
+ for _, i := range tests { |
|
35 |
+ got, err := normaliseDest("TEST", i.current, i.requested) |
|
36 |
+ if err != nil && i.etext == "" { |
|
37 |
+ t.Fatalf("TestNormaliseDest Got unexpected error %q for %s %s. ", err.Error(), i.current, i.requested) |
|
38 |
+ } |
|
39 |
+ if i.etext != "" && ((err == nil) || (err != nil && err.Error() != i.etext)) { |
|
40 |
+ if err == nil { |
|
41 |
+ t.Fatalf("TestNormaliseDest Expected an error for %s %s but didn't get one", i.current, i.requested) |
|
42 |
+ } else { |
|
43 |
+ t.Fatalf("TestNormaliseDest Wrong error text for %s %s - %s", i.current, i.requested, err.Error()) |
|
44 |
+ } |
|
45 |
+ } |
|
46 |
+ if i.etext == "" && got != i.expected { |
|
47 |
+ t.Fatalf("TestNormaliseDest Expected %q for %q and %q. Got %q", i.expected, i.current, i.requested, got) |
|
48 |
+ } |
|
49 |
+ } |
|
50 |
+} |
... | ... |
@@ -2108,33 +2108,16 @@ func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) { |
2108 | 2108 |
} |
2109 | 2109 |
} |
2110 | 2110 |
|
2111 |
-// #22181 Regression test. Validates combinations of supported |
|
2112 |
-// WORKDIR dockerfile directives in Windows and non-Windows semantics. |
|
2111 |
+// #22181 Regression test. Single end-to-end test of using |
|
2112 |
+// Windows semantics. Most path handling verifications are in unit tests |
|
2113 | 2113 |
func (s *DockerSuite) TestBuildWindowsWorkdirProcessing(c *check.C) { |
2114 | 2114 |
testRequires(c, DaemonIsWindows) |
2115 | 2115 |
name := "testbuildwindowsworkdirprocessing" |
2116 | 2116 |
_, err := buildImage(name, |
2117 | 2117 |
`FROM busybox |
2118 |
- WORKDIR a |
|
2119 |
- RUN sh -c "[ "$PWD" = "C:/a" ]" |
|
2120 |
- WORKDIR c:\\foo |
|
2121 |
- RUN sh -c "[ "$PWD" = "C:/foo" ]" |
|
2122 |
- WORKDIR \\foo |
|
2123 |
- RUN sh -c "[ "$PWD" = "C:/foo" ]" |
|
2124 |
- WORKDIR /foo |
|
2125 |
- RUN sh -c "[ "$PWD" = "C:/foo" ]" |
|
2126 |
- WORKDIR C:/foo |
|
2118 |
+ WORKDIR C:\\foo |
|
2127 | 2119 |
WORKDIR bar |
2128 | 2120 |
RUN sh -c "[ "$PWD" = "C:/foo/bar" ]" |
2129 |
- WORKDIR c:/foo |
|
2130 |
- WORKDIR bar |
|
2131 |
- RUN sh -c "[ "$PWD" = "C:/foo/bar" ]" |
|
2132 |
- WORKDIR c:/foo |
|
2133 |
- WORKDIR \\bar |
|
2134 |
- RUN sh -c "[ "$PWD" = "C:/bar" ]" |
|
2135 |
- WORKDIR /foo |
|
2136 |
- WORKDIR c:\\bar |
|
2137 |
- RUN sh -c "[ "$PWD" = "C:/bar" ]" |
|
2138 | 2121 |
`, |
2139 | 2122 |
true) |
2140 | 2123 |
if err != nil { |
... | ... |
@@ -2142,8 +2125,8 @@ func (s *DockerSuite) TestBuildWindowsWorkdirProcessing(c *check.C) { |
2142 | 2142 |
} |
2143 | 2143 |
} |
2144 | 2144 |
|
2145 |
-// #22181 Regression test. Validates combinations of supported |
|
2146 |
-// COPY dockerfile directives in Windows and non-Windows semantics. |
|
2145 |
+// #22181 Regression test. Most paths handling verifications are in unit test. |
|
2146 |
+// One functional test for end-to-end |
|
2147 | 2147 |
func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) { |
2148 | 2148 |
testRequires(c, DaemonIsWindows) |
2149 | 2149 |
name := "testbuildwindowsaddcopypathprocessing" |
... | ... |
@@ -2153,50 +2136,7 @@ func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) { |
2153 | 2153 |
// by docker on the Windows platform. |
2154 | 2154 |
dockerfile := ` |
2155 | 2155 |
FROM busybox |
2156 |
- # First cases with no workdir, all end up in the root directory of the system drive |
|
2157 |
- COPY a1 ./ |
|
2158 |
- ADD a2 ./ |
|
2159 |
- RUN sh -c "[ $(cat c:/a1) = 'helloa1' ]" |
|
2160 |
- RUN sh -c "[ $(cat c:/a2) = 'worlda2' ]" |
|
2161 |
- |
|
2162 |
- COPY b1 / |
|
2163 |
- ADD b2 / |
|
2164 |
- RUN sh -c "[ $(cat c:/b1) = 'hellob1' ]" |
|
2165 |
- RUN sh -c "[ $(cat c:/b2) = 'worldb2' ]" |
|
2166 |
- |
|
2167 |
- COPY c1 c:/ |
|
2168 |
- ADD c2 c:/ |
|
2169 |
- RUN sh -c "[ $(cat c:/c1) = 'helloc1' ]" |
|
2170 |
- RUN sh -c "[ $(cat c:/c2) = 'worldc2' ]" |
|
2171 |
- |
|
2172 |
- COPY d1 c:/ |
|
2173 |
- ADD d2 c:/ |
|
2174 |
- RUN sh -c "[ $(cat c:/d1) = 'hellod1' ]" |
|
2175 |
- RUN sh -c "[ $(cat c:/d2) = 'worldd2' ]" |
|
2176 |
- |
|
2177 |
- COPY e1 . |
|
2178 |
- ADD e2 . |
|
2179 |
- RUN sh -c "[ $(cat c:/e1) = 'helloe1' ]" |
|
2180 |
- RUN sh -c "[ $(cat c:/e2) = 'worlde2' ]" |
|
2181 |
- |
|
2182 |
- # Now with a workdir |
|
2183 |
- WORKDIR c:\\wa12 |
|
2184 |
- COPY wa1 ./ |
|
2185 |
- ADD wa2 ./ |
|
2186 |
- RUN sh -c "[ $(cat c:/wa12/wa1) = 'hellowa1' ]" |
|
2187 |
- RUN sh -c "[ $(cat c:/wa12/wa2) = 'worldwa2' ]" |
|
2188 |
- |
|
2189 |
- # No trailing slash on COPY/ADD, Linux-style path. |
|
2190 |
- # Results in dir being changed to a file |
|
2191 |
- WORKDIR /wb1 |
|
2192 |
- COPY wb1 . |
|
2193 |
- WORKDIR /wb2 |
|
2194 |
- ADD wb2 . |
|
2195 |
- WORKDIR c:/ |
|
2196 |
- RUN sh -c "[ $(cat c:/wb1) = 'hellowb1' ]" |
|
2197 |
- RUN sh -c "[ $(cat c:/wb2) = 'worldwb2' ]" |
|
2198 |
- |
|
2199 |
- # No trailing slash on COPY/ADD, Windows-style path. |
|
2156 |
+ # No trailing slash on COPY/ADD |
|
2200 | 2157 |
# Results in dir being changed to a file |
2201 | 2158 |
WORKDIR /wc1 |
2202 | 2159 |
COPY wc1 c:/wc1 |
... | ... |
@@ -2215,20 +2155,6 @@ func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) { |
2215 | 2215 |
RUN sh -c "[ $(cat c:/wd2/wd2) = 'worldwd2' ]" |
2216 | 2216 |
` |
2217 | 2217 |
ctx, err := fakeContext(dockerfile, map[string]string{ |
2218 |
- "a1": "helloa1", |
|
2219 |
- "a2": "worlda2", |
|
2220 |
- "b1": "hellob1", |
|
2221 |
- "b2": "worldb2", |
|
2222 |
- "c1": "helloc1", |
|
2223 |
- "c2": "worldc2", |
|
2224 |
- "d1": "hellod1", |
|
2225 |
- "d2": "worldd2", |
|
2226 |
- "e1": "helloe1", |
|
2227 |
- "e2": "worlde2", |
|
2228 |
- "wa1": "hellowa1", |
|
2229 |
- "wa2": "worldwa2", |
|
2230 |
- "wb1": "hellowb1", |
|
2231 |
- "wb2": "worldwb2", |
|
2232 | 2218 |
"wc1": "hellowc1", |
2233 | 2219 |
"wc2": "worldwc2", |
2234 | 2220 |
"wd1": "hellowd1", |
... | ... |
@@ -2244,96 +2170,6 @@ func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) { |
2244 | 2244 |
} |
2245 | 2245 |
} |
2246 | 2246 |
|
2247 |
-// #22181 Regression test. |
|
2248 |
-func (s *DockerSuite) TestBuildWindowsCopyFailsNonSystemDrive(c *check.C) { |
|
2249 |
- testRequires(c, DaemonIsWindows) |
|
2250 |
- name := "testbuildwindowscopyfailsnonsystemdrive" |
|
2251 |
- dockerfile := ` |
|
2252 |
- FROM busybox |
|
2253 |
- cOpY foo d:/ |
|
2254 |
- ` |
|
2255 |
- ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"}) |
|
2256 |
- if err != nil { |
|
2257 |
- c.Fatal(err) |
|
2258 |
- } |
|
2259 |
- defer ctx.Close() |
|
2260 |
- _, err = buildImageFromContext(name, ctx, false) |
|
2261 |
- if err == nil { |
|
2262 |
- c.Fatal(err) |
|
2263 |
- } |
|
2264 |
- if !strings.Contains(err.Error(), "Windows does not support COPY with a destinations not on the system drive (C:)") { |
|
2265 |
- c.Fatal(err) |
|
2266 |
- } |
|
2267 |
-} |
|
2268 |
- |
|
2269 |
-// #22181 Regression test. |
|
2270 |
-func (s *DockerSuite) TestBuildWindowsCopyFailsWorkdirNonSystemDrive(c *check.C) { |
|
2271 |
- testRequires(c, DaemonIsWindows) |
|
2272 |
- name := "testbuildwindowscopyfailsworkdirsystemdrive" |
|
2273 |
- dockerfile := ` |
|
2274 |
- FROM busybox |
|
2275 |
- WORKDIR d:/ |
|
2276 |
- cOpY foo . |
|
2277 |
- ` |
|
2278 |
- ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"}) |
|
2279 |
- if err != nil { |
|
2280 |
- c.Fatal(err) |
|
2281 |
- } |
|
2282 |
- defer ctx.Close() |
|
2283 |
- _, err = buildImageFromContext(name, ctx, false) |
|
2284 |
- if err == nil { |
|
2285 |
- c.Fatal(err) |
|
2286 |
- } |
|
2287 |
- if !strings.Contains(err.Error(), "Windows does not support COPY with relative paths when WORKDIR is not the system drive") { |
|
2288 |
- c.Fatal(err) |
|
2289 |
- } |
|
2290 |
-} |
|
2291 |
- |
|
2292 |
-// #22181 Regression test. |
|
2293 |
-func (s *DockerSuite) TestBuildWindowsAddFailsNonSystemDrive(c *check.C) { |
|
2294 |
- testRequires(c, DaemonIsWindows) |
|
2295 |
- name := "testbuildwindowsaddfailsnonsystemdrive" |
|
2296 |
- dockerfile := ` |
|
2297 |
- FROM busybox |
|
2298 |
- AdD foo d:/ |
|
2299 |
- ` |
|
2300 |
- ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"}) |
|
2301 |
- if err != nil { |
|
2302 |
- c.Fatal(err) |
|
2303 |
- } |
|
2304 |
- defer ctx.Close() |
|
2305 |
- _, err = buildImageFromContext(name, ctx, false) |
|
2306 |
- if err == nil { |
|
2307 |
- c.Fatal(err) |
|
2308 |
- } |
|
2309 |
- if !strings.Contains(err.Error(), "Windows does not support ADD with a destinations not on the system drive (C:)") { |
|
2310 |
- c.Fatal(err) |
|
2311 |
- } |
|
2312 |
-} |
|
2313 |
- |
|
2314 |
-// #22181 Regression test. |
|
2315 |
-func (s *DockerSuite) TestBuildWindowsAddFailsWorkdirNonSystemDrive(c *check.C) { |
|
2316 |
- testRequires(c, DaemonIsWindows) |
|
2317 |
- name := "testbuildwindowsaddfailsworkdirsystemdrive" |
|
2318 |
- dockerfile := ` |
|
2319 |
- FROM busybox |
|
2320 |
- WORKDIR d:/ |
|
2321 |
- AdD foo . |
|
2322 |
- ` |
|
2323 |
- ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"}) |
|
2324 |
- if err != nil { |
|
2325 |
- c.Fatal(err) |
|
2326 |
- } |
|
2327 |
- defer ctx.Close() |
|
2328 |
- _, err = buildImageFromContext(name, ctx, false) |
|
2329 |
- if err == nil { |
|
2330 |
- c.Fatal(err) |
|
2331 |
- } |
|
2332 |
- if !strings.Contains(err.Error(), "Windows does not support ADD with relative paths when WORKDIR is not the system drive") { |
|
2333 |
- c.Fatal(err) |
|
2334 |
- } |
|
2335 |
-} |
|
2336 |
- |
|
2337 | 2247 |
func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) { |
2338 | 2248 |
name := "testbuildworkdirwithenvvariables" |
2339 | 2249 |
|