Windows: Consistent build workdir handling
| ... | ... |
@@ -264,12 +264,37 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str |
| 264 | 264 |
// This is from the Dockerfile and will not necessarily be in platform |
| 265 | 265 |
// specific semantics, hence ensure it is converted. |
| 266 | 266 |
workdir := filepath.FromSlash(args[0]) |
| 267 |
- |
|
| 268 |
- if !system.IsAbs(workdir) {
|
|
| 269 |
- current := filepath.FromSlash(b.runConfig.WorkingDir) |
|
| 270 |
- workdir = filepath.Join(string(os.PathSeparator), current, workdir) |
|
| 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 |
+ } |
|
| 271 | 297 |
} |
| 272 |
- |
|
| 273 | 298 |
b.runConfig.WorkingDir = workdir |
| 274 | 299 |
|
| 275 | 300 |
return b.commit("", b.runConfig.Cmd, fmt.Sprintf("WORKDIR %v", workdir))
|
| ... | ... |
@@ -200,13 +200,59 @@ 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 |
- if !system.IsAbs(dest) {
|
|
| 204 |
- hasSlash := strings.HasSuffix(dest, string(os.PathSeparator)) |
|
| 205 |
- dest = filepath.Join(string(os.PathSeparator), filepath.FromSlash(b.runConfig.WorkingDir), dest) |
|
| 206 | 203 |
|
| 207 |
- // Make sure we preserve any trailing slash |
|
| 208 |
- if hasSlash {
|
|
| 209 |
- dest += string(os.PathSeparator) |
|
| 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 |
+ } |
|
| 210 | 256 |
} |
| 211 | 257 |
} |
| 212 | 258 |
|
| ... | ... |
@@ -251,6 +251,13 @@ func (container *Container) GetResourcePath(path string) (string, error) {
|
| 251 | 251 |
|
| 252 | 252 |
cleanPath := cleanResourcePath(path) |
| 253 | 253 |
r, e := symlink.FollowSymlinkInScope(filepath.Join(container.BaseFS, cleanPath), container.BaseFS) |
| 254 |
+ |
|
| 255 |
+ // Log this here on the daemon side as there's otherwise no indication apart |
|
| 256 |
+ // from the error being propagated all the way back to the client. This makes |
|
| 257 |
+ // debugging significantly easier and clearly indicates the error comes from the daemon. |
|
| 258 |
+ if e != nil {
|
|
| 259 |
+ logrus.Errorf("Failed to FollowSymlinkInScope BaseFS %s cleanPath %s path %s %s\n", container.BaseFS, cleanPath, path, e)
|
|
| 260 |
+ } |
|
| 254 | 261 |
return r, e |
| 255 | 262 |
} |
| 256 | 263 |
|
| ... | ... |
@@ -2074,22 +2074,13 @@ func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) {
|
| 2074 | 2074 |
expected4 string |
| 2075 | 2075 |
expectedFinal string |
| 2076 | 2076 |
) |
| 2077 |
- // TODO Windows: The expectedFinal needs fixing to match Windows |
|
| 2078 |
- // filepath semantics. However, this is a non-trivial change. @jhowardmsft |
|
| 2079 |
- // Short story - need to make the configuration file platform semantically |
|
| 2080 |
- // consistent, so even if `WORKDIR /test2/test3` is specified in a Dockerfile, |
|
| 2081 |
- // the configuration should be stored as C:\test2\test3. Something similar to |
|
| 2082 |
- // if runtime.GOOS == "windows" && len(workdir) > 2 && string(workdir[0]) == `\` {
|
|
| 2083 |
- // workdir = "C:" + workdir |
|
| 2084 |
- // } |
|
| 2085 |
- // in builder\dockerfile\dispatchers.go, function workdir(), but also |
|
| 2086 |
- // ironing out all other cases where this causes other failures. |
|
| 2077 |
+ |
|
| 2087 | 2078 |
if daemonPlatform == "windows" {
|
| 2088 | 2079 |
expected1 = `C:/` |
| 2089 | 2080 |
expected2 = `C:/test1` |
| 2090 | 2081 |
expected3 = `C:/test2` |
| 2091 | 2082 |
expected4 = `C:/test2/test3` |
| 2092 |
- expectedFinal = `\test2\test3` |
|
| 2083 |
+ expectedFinal = `C:\test2\test3` // Note inspect is going to return Windows paths, as it's not in busybox |
|
| 2093 | 2084 |
} else {
|
| 2094 | 2085 |
expected1 = `/` |
| 2095 | 2086 |
expected2 = `/test1` |
| ... | ... |
@@ -2117,12 +2108,238 @@ func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) {
|
| 2117 | 2117 |
} |
| 2118 | 2118 |
} |
| 2119 | 2119 |
|
| 2120 |
+// #22181 Regression test. Validates combinations of supported |
|
| 2121 |
+// WORKDIR dockerfile directives in Windows and non-Windows semantics. |
|
| 2122 |
+func (s *DockerSuite) TestBuildWindowsWorkdirProcessing(c *check.C) {
|
|
| 2123 |
+ testRequires(c, DaemonIsWindows) |
|
| 2124 |
+ name := "testbuildwindowsworkdirprocessing" |
|
| 2125 |
+ _, err := buildImage(name, |
|
| 2126 |
+ `FROM busybox |
|
| 2127 |
+ WORKDIR a |
|
| 2128 |
+ RUN sh -c "[ "$PWD" = "C:/a" ]" |
|
| 2129 |
+ WORKDIR c:\\foo |
|
| 2130 |
+ RUN sh -c "[ "$PWD" = "C:/foo" ]" |
|
| 2131 |
+ WORKDIR \\foo |
|
| 2132 |
+ RUN sh -c "[ "$PWD" = "C:/foo" ]" |
|
| 2133 |
+ WORKDIR /foo |
|
| 2134 |
+ RUN sh -c "[ "$PWD" = "C:/foo" ]" |
|
| 2135 |
+ WORKDIR C:/foo |
|
| 2136 |
+ WORKDIR bar |
|
| 2137 |
+ RUN sh -c "[ "$PWD" = "C:/foo/bar" ]" |
|
| 2138 |
+ WORKDIR c:/foo |
|
| 2139 |
+ WORKDIR bar |
|
| 2140 |
+ RUN sh -c "[ "$PWD" = "C:/foo/bar" ]" |
|
| 2141 |
+ WORKDIR c:/foo |
|
| 2142 |
+ WORKDIR \\bar |
|
| 2143 |
+ RUN sh -c "[ "$PWD" = "C:/bar" ]" |
|
| 2144 |
+ WORKDIR /foo |
|
| 2145 |
+ WORKDIR c:\\bar |
|
| 2146 |
+ RUN sh -c "[ "$PWD" = "C:/bar" ]" |
|
| 2147 |
+ `, |
|
| 2148 |
+ true) |
|
| 2149 |
+ if err != nil {
|
|
| 2150 |
+ c.Fatal(err) |
|
| 2151 |
+ } |
|
| 2152 |
+} |
|
| 2153 |
+ |
|
| 2154 |
+// #22181 Regression test. Validates combinations of supported |
|
| 2155 |
+// COPY dockerfile directives in Windows and non-Windows semantics. |
|
| 2156 |
+func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) {
|
|
| 2157 |
+ testRequires(c, DaemonIsWindows) |
|
| 2158 |
+ name := "testbuildwindowsaddcopypathprocessing" |
|
| 2159 |
+ // TODO Windows (@jhowardmsft). Needs a follow-up PR to 22181 to |
|
| 2160 |
+ // support backslash such as .\\ being equivalent to ./ and c:\\ being |
|
| 2161 |
+ // equivalent to c:/. This is not currently (nor ever has been) supported |
|
| 2162 |
+ // by docker on the Windows platform. |
|
| 2163 |
+ dockerfile := ` |
|
| 2164 |
+ FROM busybox |
|
| 2165 |
+ # First cases with no workdir, all end up in the root directory of the system drive |
|
| 2166 |
+ COPY a1 ./ |
|
| 2167 |
+ ADD a2 ./ |
|
| 2168 |
+ RUN sh -c "[ $(cat c:/a1) = 'helloa1' ]" |
|
| 2169 |
+ RUN sh -c "[ $(cat c:/a2) = 'worlda2' ]" |
|
| 2170 |
+ |
|
| 2171 |
+ COPY b1 / |
|
| 2172 |
+ ADD b2 / |
|
| 2173 |
+ RUN sh -c "[ $(cat c:/b1) = 'hellob1' ]" |
|
| 2174 |
+ RUN sh -c "[ $(cat c:/b2) = 'worldb2' ]" |
|
| 2175 |
+ |
|
| 2176 |
+ COPY c1 c:/ |
|
| 2177 |
+ ADD c2 c:/ |
|
| 2178 |
+ RUN sh -c "[ $(cat c:/c1) = 'helloc1' ]" |
|
| 2179 |
+ RUN sh -c "[ $(cat c:/c2) = 'worldc2' ]" |
|
| 2180 |
+ |
|
| 2181 |
+ COPY d1 c:/ |
|
| 2182 |
+ ADD d2 c:/ |
|
| 2183 |
+ RUN sh -c "[ $(cat c:/d1) = 'hellod1' ]" |
|
| 2184 |
+ RUN sh -c "[ $(cat c:/d2) = 'worldd2' ]" |
|
| 2185 |
+ |
|
| 2186 |
+ COPY e1 . |
|
| 2187 |
+ ADD e2 . |
|
| 2188 |
+ RUN sh -c "[ $(cat c:/e1) = 'helloe1' ]" |
|
| 2189 |
+ RUN sh -c "[ $(cat c:/e2) = 'worlde2' ]" |
|
| 2190 |
+ |
|
| 2191 |
+ # Now with a workdir |
|
| 2192 |
+ WORKDIR c:\\wa12 |
|
| 2193 |
+ COPY wa1 ./ |
|
| 2194 |
+ ADD wa2 ./ |
|
| 2195 |
+ RUN sh -c "[ $(cat c:/wa12/wa1) = 'hellowa1' ]" |
|
| 2196 |
+ RUN sh -c "[ $(cat c:/wa12/wa2) = 'worldwa2' ]" |
|
| 2197 |
+ |
|
| 2198 |
+ # No trailing slash on COPY/ADD, Linux-style path. |
|
| 2199 |
+ # Results in dir being changed to a file |
|
| 2200 |
+ WORKDIR /wb1 |
|
| 2201 |
+ COPY wb1 . |
|
| 2202 |
+ WORKDIR /wb2 |
|
| 2203 |
+ ADD wb2 . |
|
| 2204 |
+ WORKDIR c:/ |
|
| 2205 |
+ RUN sh -c "[ $(cat c:/wb1) = 'hellowb1' ]" |
|
| 2206 |
+ RUN sh -c "[ $(cat c:/wb2) = 'worldwb2' ]" |
|
| 2207 |
+ |
|
| 2208 |
+ # No trailing slash on COPY/ADD, Windows-style path. |
|
| 2209 |
+ # Results in dir being changed to a file |
|
| 2210 |
+ WORKDIR /wc1 |
|
| 2211 |
+ COPY wc1 c:/wc1 |
|
| 2212 |
+ WORKDIR /wc2 |
|
| 2213 |
+ ADD wc2 c:/wc2 |
|
| 2214 |
+ WORKDIR c:/ |
|
| 2215 |
+ RUN sh -c "[ $(cat c:/wc1) = 'hellowc1' ]" |
|
| 2216 |
+ RUN sh -c "[ $(cat c:/wc2) = 'worldwc2' ]" |
|
| 2217 |
+ |
|
| 2218 |
+ # Trailing slash on COPY/ADD, Windows-style path. |
|
| 2219 |
+ WORKDIR /wd1 |
|
| 2220 |
+ COPY wd1 c:/wd1/ |
|
| 2221 |
+ WORKDIR /wd2 |
|
| 2222 |
+ ADD wd2 c:/wd2/ |
|
| 2223 |
+ RUN sh -c "[ $(cat c:/wd1/wd1) = 'hellowd1' ]" |
|
| 2224 |
+ RUN sh -c "[ $(cat c:/wd2/wd2) = 'worldwd2' ]" |
|
| 2225 |
+ ` |
|
| 2226 |
+ ctx, err := fakeContext(dockerfile, map[string]string{
|
|
| 2227 |
+ "a1": "helloa1", |
|
| 2228 |
+ "a2": "worlda2", |
|
| 2229 |
+ "b1": "hellob1", |
|
| 2230 |
+ "b2": "worldb2", |
|
| 2231 |
+ "c1": "helloc1", |
|
| 2232 |
+ "c2": "worldc2", |
|
| 2233 |
+ "d1": "hellod1", |
|
| 2234 |
+ "d2": "worldd2", |
|
| 2235 |
+ "e1": "helloe1", |
|
| 2236 |
+ "e2": "worlde2", |
|
| 2237 |
+ "wa1": "hellowa1", |
|
| 2238 |
+ "wa2": "worldwa2", |
|
| 2239 |
+ "wb1": "hellowb1", |
|
| 2240 |
+ "wb2": "worldwb2", |
|
| 2241 |
+ "wc1": "hellowc1", |
|
| 2242 |
+ "wc2": "worldwc2", |
|
| 2243 |
+ "wd1": "hellowd1", |
|
| 2244 |
+ "wd2": "worldwd2", |
|
| 2245 |
+ }) |
|
| 2246 |
+ if err != nil {
|
|
| 2247 |
+ c.Fatal(err) |
|
| 2248 |
+ } |
|
| 2249 |
+ defer ctx.Close() |
|
| 2250 |
+ _, err = buildImageFromContext(name, ctx, false) |
|
| 2251 |
+ if err != nil {
|
|
| 2252 |
+ c.Fatal(err) |
|
| 2253 |
+ } |
|
| 2254 |
+} |
|
| 2255 |
+ |
|
| 2256 |
+// #22181 Regression test. |
|
| 2257 |
+func (s *DockerSuite) TestBuildWindowsCopyFailsNonSystemDrive(c *check.C) {
|
|
| 2258 |
+ testRequires(c, DaemonIsWindows) |
|
| 2259 |
+ name := "testbuildwindowscopyfailsnonsystemdrive" |
|
| 2260 |
+ dockerfile := ` |
|
| 2261 |
+ FROM busybox |
|
| 2262 |
+ cOpY foo d:/ |
|
| 2263 |
+ ` |
|
| 2264 |
+ ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"})
|
|
| 2265 |
+ if err != nil {
|
|
| 2266 |
+ c.Fatal(err) |
|
| 2267 |
+ } |
|
| 2268 |
+ defer ctx.Close() |
|
| 2269 |
+ _, err = buildImageFromContext(name, ctx, false) |
|
| 2270 |
+ if err == nil {
|
|
| 2271 |
+ c.Fatal(err) |
|
| 2272 |
+ } |
|
| 2273 |
+ if !strings.Contains(err.Error(), "Windows does not support COPY with a destinations not on the system drive (C:)") {
|
|
| 2274 |
+ c.Fatal(err) |
|
| 2275 |
+ } |
|
| 2276 |
+} |
|
| 2277 |
+ |
|
| 2278 |
+// #22181 Regression test. |
|
| 2279 |
+func (s *DockerSuite) TestBuildWindowsCopyFailsWorkdirNonSystemDrive(c *check.C) {
|
|
| 2280 |
+ testRequires(c, DaemonIsWindows) |
|
| 2281 |
+ name := "testbuildwindowscopyfailsworkdirsystemdrive" |
|
| 2282 |
+ dockerfile := ` |
|
| 2283 |
+ FROM busybox |
|
| 2284 |
+ WORKDIR d:/ |
|
| 2285 |
+ cOpY foo . |
|
| 2286 |
+ ` |
|
| 2287 |
+ ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"})
|
|
| 2288 |
+ if err != nil {
|
|
| 2289 |
+ c.Fatal(err) |
|
| 2290 |
+ } |
|
| 2291 |
+ defer ctx.Close() |
|
| 2292 |
+ _, err = buildImageFromContext(name, ctx, false) |
|
| 2293 |
+ if err == nil {
|
|
| 2294 |
+ c.Fatal(err) |
|
| 2295 |
+ } |
|
| 2296 |
+ if !strings.Contains(err.Error(), "Windows does not support COPY with relative paths when WORKDIR is not the system drive") {
|
|
| 2297 |
+ c.Fatal(err) |
|
| 2298 |
+ } |
|
| 2299 |
+} |
|
| 2300 |
+ |
|
| 2301 |
+// #22181 Regression test. |
|
| 2302 |
+func (s *DockerSuite) TestBuildWindowsAddFailsNonSystemDrive(c *check.C) {
|
|
| 2303 |
+ testRequires(c, DaemonIsWindows) |
|
| 2304 |
+ name := "testbuildwindowsaddfailsnonsystemdrive" |
|
| 2305 |
+ dockerfile := ` |
|
| 2306 |
+ FROM busybox |
|
| 2307 |
+ AdD foo d:/ |
|
| 2308 |
+ ` |
|
| 2309 |
+ ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"})
|
|
| 2310 |
+ if err != nil {
|
|
| 2311 |
+ c.Fatal(err) |
|
| 2312 |
+ } |
|
| 2313 |
+ defer ctx.Close() |
|
| 2314 |
+ _, err = buildImageFromContext(name, ctx, false) |
|
| 2315 |
+ if err == nil {
|
|
| 2316 |
+ c.Fatal(err) |
|
| 2317 |
+ } |
|
| 2318 |
+ if !strings.Contains(err.Error(), "Windows does not support ADD with a destinations not on the system drive (C:)") {
|
|
| 2319 |
+ c.Fatal(err) |
|
| 2320 |
+ } |
|
| 2321 |
+} |
|
| 2322 |
+ |
|
| 2323 |
+// #22181 Regression test. |
|
| 2324 |
+func (s *DockerSuite) TestBuildWindowsAddFailsWorkdirNonSystemDrive(c *check.C) {
|
|
| 2325 |
+ testRequires(c, DaemonIsWindows) |
|
| 2326 |
+ name := "testbuildwindowsaddfailsworkdirsystemdrive" |
|
| 2327 |
+ dockerfile := ` |
|
| 2328 |
+ FROM busybox |
|
| 2329 |
+ WORKDIR d:/ |
|
| 2330 |
+ AdD foo . |
|
| 2331 |
+ ` |
|
| 2332 |
+ ctx, err := fakeContext(dockerfile, map[string]string{"foo": "hello"})
|
|
| 2333 |
+ if err != nil {
|
|
| 2334 |
+ c.Fatal(err) |
|
| 2335 |
+ } |
|
| 2336 |
+ defer ctx.Close() |
|
| 2337 |
+ _, err = buildImageFromContext(name, ctx, false) |
|
| 2338 |
+ if err == nil {
|
|
| 2339 |
+ c.Fatal(err) |
|
| 2340 |
+ } |
|
| 2341 |
+ if !strings.Contains(err.Error(), "Windows does not support ADD with relative paths when WORKDIR is not the system drive") {
|
|
| 2342 |
+ c.Fatal(err) |
|
| 2343 |
+ } |
|
| 2344 |
+} |
|
| 2345 |
+ |
|
| 2120 | 2346 |
func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) {
|
| 2121 | 2347 |
name := "testbuildworkdirwithenvvariables" |
| 2122 | 2348 |
|
| 2123 | 2349 |
var expected string |
| 2124 | 2350 |
if daemonPlatform == "windows" {
|
| 2125 |
- expected = `\test1\test2` |
|
| 2351 |
+ expected = `C:\test1\test2` |
|
| 2126 | 2352 |
} else {
|
| 2127 | 2353 |
expected = `/test1/test2` |
| 2128 | 2354 |
} |