github.com/containers/podman/v4@v4.9.4/test/e2e/build_test.go (about) 1 package integration 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "runtime" 10 "strings" 11 12 "github.com/containers/buildah/define" 13 . "github.com/containers/podman/v4/test/utils" 14 . "github.com/onsi/ginkgo/v2" 15 . "github.com/onsi/gomega" 16 . "github.com/onsi/gomega/gexec" 17 ) 18 19 var _ = Describe("Podman build", func() { 20 // Let's first do the most simple build possible to make sure stuff is 21 // happy and then clean up after ourselves to make sure that works too. 22 It("podman build and remove basic alpine", func() { 23 podmanTest.AddImageToRWStore(ALPINE) 24 session := podmanTest.Podman([]string{"build", "--pull-never", "build/basicalpine"}) 25 session.WaitWithDefaultTimeout() 26 Expect(session).Should(ExitCleanly()) 27 28 iid := session.OutputToStringArray()[len(session.OutputToStringArray())-1] 29 30 // Verify that OS and Arch are being set 31 inspect := podmanTest.Podman([]string{"inspect", iid}) 32 inspect.WaitWithDefaultTimeout() 33 data := inspect.InspectImageJSON() 34 Expect(data[0]).To(HaveField("Os", runtime.GOOS)) 35 Expect(data[0]).To(HaveField("Architecture", runtime.GOARCH)) 36 37 session = podmanTest.Podman([]string{"rmi", ALPINE}) 38 session.WaitWithDefaultTimeout() 39 Expect(session).Should(ExitCleanly()) 40 }) 41 42 It("podman build and remove basic alpine with TMPDIR as relative", func() { 43 // preserve TMPDIR if it was originally set 44 if cacheDir, found := os.LookupEnv("TMPDIR"); found { 45 defer os.Setenv("TMPDIR", cacheDir) 46 os.Unsetenv("TMPDIR") 47 } else { 48 defer os.Unsetenv("TMPDIR") 49 } 50 // Test case described here: https://github.com/containers/buildah/pull/5084 51 os.Setenv("TMPDIR", ".") 52 podmanTest.AddImageToRWStore(ALPINE) 53 session := podmanTest.Podman([]string{"build", "--pull-never", "build/basicrun"}) 54 session.WaitWithDefaultTimeout() 55 Expect(session).Should(ExitCleanly()) 56 }) 57 58 It("podman build with a secret from file", func() { 59 session := podmanTest.Podman([]string{"build", "-f", "build/Containerfile.with-secret", "-t", "secret-test", "--secret", "id=mysecret,src=build/secret.txt", "build/"}) 60 session.WaitWithDefaultTimeout() 61 Expect(session).Should(ExitCleanly()) 62 Expect(session.OutputToString()).To(ContainSubstring("somesecret")) 63 64 session = podmanTest.Podman([]string{"rmi", "secret-test"}) 65 session.WaitWithDefaultTimeout() 66 Expect(session).Should(ExitCleanly()) 67 }) 68 69 It("podman build with multiple secrets from files", func() { 70 session := podmanTest.Podman([]string{"build", "-f", "build/Containerfile.with-multiple-secret", "-t", "multiple-secret-test", "--secret", "id=mysecret,src=build/secret.txt", "--secret", "id=mysecret2,src=build/anothersecret.txt", "build/"}) 71 session.WaitWithDefaultTimeout() 72 Expect(session).Should(ExitCleanly()) 73 Expect(session.OutputToString()).To(ContainSubstring("somesecret")) 74 Expect(session.OutputToString()).To(ContainSubstring("anothersecret")) 75 76 session = podmanTest.Podman([]string{"rmi", "multiple-secret-test"}) 77 session.WaitWithDefaultTimeout() 78 Expect(session).Should(ExitCleanly()) 79 }) 80 81 It("podman build with a secret from file and verify if secret file is not leaked into image", func() { 82 session := podmanTest.Podman([]string{"build", "-f", "build/secret-verify-leak/Containerfile.with-secret-verify-leak", "-t", "secret-test-leak", "--secret", "id=mysecret,src=build/secret.txt", "build/secret-verify-leak"}) 83 session.WaitWithDefaultTimeout() 84 Expect(session).Should(ExitCleanly()) 85 Expect(session.OutputToString()).To(ContainSubstring("somesecret")) 86 87 session = podmanTest.Podman([]string{"run", "--rm", "secret-test-leak", "ls"}) 88 session.WaitWithDefaultTimeout() 89 Expect(session).Should(ExitCleanly()) 90 Expect(session.OutputToString()).To(Not(ContainSubstring("podman-build-secret"))) 91 92 session = podmanTest.Podman([]string{"rmi", "secret-test-leak"}) 93 session.WaitWithDefaultTimeout() 94 Expect(session).Should(ExitCleanly()) 95 }) 96 97 It("podman build with logfile", func() { 98 logfile := filepath.Join(podmanTest.TempDir, "logfile") 99 session := podmanTest.Podman([]string{"build", "--pull=never", "--tag", "test", "--logfile", logfile, "build/basicalpine"}) 100 session.WaitWithDefaultTimeout() 101 Expect(session).Should(ExitCleanly()) 102 103 // Verify that OS and Arch are being set 104 inspect := podmanTest.Podman([]string{"inspect", "test"}) 105 inspect.WaitWithDefaultTimeout() 106 data := inspect.InspectImageJSON() 107 Expect(data[0]).To(HaveField("Os", runtime.GOOS)) 108 Expect(data[0]).To(HaveField("Architecture", runtime.GOARCH)) 109 110 st, err := os.Stat(logfile) 111 Expect(err).ToNot(HaveOccurred()) 112 Expect(st.Size()).To(Not(Equal(int64(0)))) 113 114 session = podmanTest.Podman([]string{"rmi", "test"}) 115 session.WaitWithDefaultTimeout() 116 Expect(session).Should(ExitCleanly()) 117 }) 118 119 // If the context directory is pointing at a file and not a directory, 120 // that's a no no, fail out. 121 It("podman build context directory a file", func() { 122 session := podmanTest.Podman([]string{"build", "--pull=never", "build/context_dir_a_file"}) 123 session.WaitWithDefaultTimeout() 124 Expect(session).Should(Exit(125)) 125 }) 126 127 // Check that builds with different values for the squash options 128 // create the appropriate number of layers, then clean up after. 129 It("podman build basic alpine with squash", func() { 130 session := podmanTest.Podman([]string{"build", "-q", "--pull-never", "-f", "build/squash/Dockerfile.squash-a", "-t", "test-squash-a:latest", "build/squash"}) 131 session.WaitWithDefaultTimeout() 132 Expect(session).Should(ExitCleanly()) 133 134 session = podmanTest.Podman([]string{"inspect", "--format", "{{.RootFS.Layers}}", "test-squash-a"}) 135 session.WaitWithDefaultTimeout() 136 Expect(session).Should(ExitCleanly()) 137 // Check for two layers 138 Expect(strings.Fields(session.OutputToString())).To(HaveLen(2)) 139 140 session = podmanTest.Podman([]string{"build", "-q", "--pull-never", "-f", "build/squash/Dockerfile.squash-b", "--squash", "-t", "test-squash-b:latest", "build/squash"}) 141 session.WaitWithDefaultTimeout() 142 Expect(session).Should(ExitCleanly()) 143 144 session = podmanTest.Podman([]string{"inspect", "--format", "{{.RootFS.Layers}}", "test-squash-b"}) 145 session.WaitWithDefaultTimeout() 146 Expect(session).Should(ExitCleanly()) 147 // Check for three layers 148 Expect(strings.Fields(session.OutputToString())).To(HaveLen(3)) 149 150 session = podmanTest.Podman([]string{"build", "-q", "--pull-never", "-f", "build/squash/Dockerfile.squash-c", "--squash", "-t", "test-squash-c:latest", "build/squash"}) 151 session.WaitWithDefaultTimeout() 152 Expect(session).Should(ExitCleanly()) 153 154 session = podmanTest.Podman([]string{"inspect", "--format", "{{.RootFS.Layers}}", "test-squash-c"}) 155 session.WaitWithDefaultTimeout() 156 Expect(session).Should(ExitCleanly()) 157 // Check for two layers 158 Expect(strings.Fields(session.OutputToString())).To(HaveLen(2)) 159 160 session = podmanTest.Podman([]string{"build", "-q", "--pull-never", "-f", "build/squash/Dockerfile.squash-c", "--squash-all", "-t", "test-squash-d:latest", "build/squash"}) 161 session.WaitWithDefaultTimeout() 162 Expect(session).Should(ExitCleanly()) 163 164 session = podmanTest.Podman([]string{"inspect", "--format", "{{.RootFS.Layers}}", "test-squash-d"}) 165 session.WaitWithDefaultTimeout() 166 Expect(session).Should(ExitCleanly()) 167 // Check for one layers 168 Expect(strings.Fields(session.OutputToString())).To(HaveLen(1)) 169 170 session = podmanTest.Podman([]string{"rm", "-a"}) 171 session.WaitWithDefaultTimeout() 172 Expect(session).Should(ExitCleanly()) 173 }) 174 175 It("podman build verify explicit cache use with squash-all and --layers", func() { 176 session := podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/squash/Dockerfile.squash-c", "--squash-all", "--layers", "-t", "test-squash-d:latest", "build/squash"}) 177 session.WaitWithDefaultTimeout() 178 Expect(session).Should(ExitCleanly()) 179 180 session = podmanTest.Podman([]string{"inspect", "--format", "{{.RootFS.Layers}}", "test-squash-d"}) 181 session.WaitWithDefaultTimeout() 182 Expect(session).Should(ExitCleanly()) 183 // Check for one layers 184 Expect(strings.Fields(session.OutputToString())).To(HaveLen(1)) 185 186 // Second build must use last squashed build from cache 187 session = podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/squash/Dockerfile.squash-c", "--squash-all", "--layers", "-t", "test", "build/squash"}) 188 session.WaitWithDefaultTimeout() 189 Expect(session).Should(ExitCleanly()) 190 // Test if entire build is used from cache 191 Expect(session.OutputToString()).To(ContainSubstring("Using cache")) 192 193 session = podmanTest.Podman([]string{"inspect", "--format", "{{.RootFS.Layers}}", "test-squash-d"}) 194 session.WaitWithDefaultTimeout() 195 Expect(session).Should(ExitCleanly()) 196 // Check for one layers 197 Expect(strings.Fields(session.OutputToString())).To(HaveLen(1)) 198 199 }) 200 201 It("podman build Containerfile locations", func() { 202 // Given 203 // Switch to temp dir and restore it afterwards 204 cwd, err := os.Getwd() 205 Expect(err).ToNot(HaveOccurred()) 206 Expect(os.Chdir(os.TempDir())).To(Succeed()) 207 defer Expect(os.Chdir(cwd)).To(BeNil()) 208 209 fakeFile := filepath.Join(os.TempDir(), "Containerfile") 210 Expect(os.WriteFile(fakeFile, []byte(fmt.Sprintf("FROM %s", CITEST_IMAGE)), 0755)).To(Succeed()) 211 212 targetFile := filepath.Join(podmanTest.TempDir, "Containerfile") 213 Expect(os.WriteFile(targetFile, []byte("FROM scratch"), 0755)).To(Succeed()) 214 215 defer func() { 216 Expect(os.RemoveAll(fakeFile)).To(Succeed()) 217 Expect(os.RemoveAll(targetFile)).To(Succeed()) 218 }() 219 220 // When 221 session := podmanTest.Podman([]string{ 222 "build", "--pull-never", "-f", targetFile, "-t", "test-locations", 223 }) 224 session.WaitWithDefaultTimeout() 225 226 // Then 227 Expect(session).Should(ExitCleanly()) 228 Expect(strings.Fields(session.OutputToString())). 229 To(ContainElement("scratch")) 230 }) 231 232 It("podman build basic alpine and print id to external file", func() { 233 // Switch to temp dir and restore it afterwards 234 cwd, err := os.Getwd() 235 Expect(err).ToNot(HaveOccurred()) 236 Expect(os.Chdir(os.TempDir())).To(Succeed()) 237 defer Expect(os.Chdir(cwd)).To(BeNil()) 238 239 targetFile := filepath.Join(podmanTest.TempDir, "idFile") 240 241 session := podmanTest.Podman([]string{"build", "--pull-never", "build/basicalpine", "--iidfile", targetFile}) 242 session.WaitWithDefaultTimeout() 243 Expect(session).Should(ExitCleanly()) 244 id, _ := os.ReadFile(targetFile) 245 246 // Verify that id is correct 247 inspect := podmanTest.Podman([]string{"inspect", string(id)}) 248 inspect.WaitWithDefaultTimeout() 249 data := inspect.InspectImageJSON() 250 Expect("sha256:" + data[0].ID).To(Equal(string(id))) 251 }) 252 253 It("podman Test PATH and reserved annotation in built image", func() { 254 path := "/tmp:/bin:/usr/bin:/usr/sbin" 255 session := podmanTest.Podman([]string{ 256 "build", "--annotation", "io.podman.annotations.seccomp=foobar", "--pull-never", "-f", "build/basicalpine/Containerfile.path", "-t", "test-path", 257 }) 258 session.WaitWithDefaultTimeout() 259 Expect(session).Should(ExitCleanly()) 260 261 session = podmanTest.Podman([]string{"run", "--name", "foobar", "test-path", "printenv", "PATH"}) 262 session.WaitWithDefaultTimeout() 263 Expect(session).Should(ExitCleanly()) 264 stdoutLines := session.OutputToStringArray() 265 Expect(stdoutLines[0]).Should(Equal(path)) 266 267 // Reserved annotation should not be applied from the image to the container. 268 session = podmanTest.Podman([]string{"inspect", "foobar"}) 269 session.WaitWithDefaultTimeout() 270 Expect(session).Should(ExitCleanly()) 271 Expect(session.OutputToString()).NotTo(ContainSubstring("io.podman.annotations.seccomp")) 272 }) 273 274 It("podman build where workdir is a symlink and run without creating new workdir", func() { 275 session := podmanTest.Podman([]string{ 276 "build", "-f", "build/workdir-symlink/Dockerfile", "-t", "test-symlink", 277 }) 278 session.WaitWithDefaultTimeout() 279 Expect(session).Should(ExitCleanly()) 280 281 session = podmanTest.Podman([]string{"run", "--workdir", "/tmp/link", "test-symlink"}) 282 session.WaitWithDefaultTimeout() 283 Expect(session).Should(ExitCleanly()) 284 Expect(session.OutputToString()).To(ContainSubstring("hello")) 285 }) 286 287 It("podman build http proxy test", func() { 288 if env, found := os.LookupEnv("http_proxy"); found { 289 defer os.Setenv("http_proxy", env) 290 } else { 291 defer os.Unsetenv("http_proxy") 292 } 293 os.Setenv("http_proxy", "1.2.3.4") 294 if IsRemote() { 295 podmanTest.StopRemoteService() 296 podmanTest.StartRemoteService() 297 // set proxy env again so it will only effect the client 298 // the remote client should still use the proxy that was set for the server 299 os.Setenv("http_proxy", "127.0.0.2") 300 } 301 podmanTest.AddImageToRWStore(CITEST_IMAGE) 302 dockerfile := fmt.Sprintf(`FROM %s 303 RUN printenv http_proxy`, CITEST_IMAGE) 304 305 dockerfilePath := filepath.Join(podmanTest.TempDir, "Dockerfile") 306 err := os.WriteFile(dockerfilePath, []byte(dockerfile), 0755) 307 Expect(err).ToNot(HaveOccurred()) 308 // --http-proxy should be true by default so we do not set it 309 session := podmanTest.Podman([]string{"build", "--pull-never", "--file", dockerfilePath, podmanTest.TempDir}) 310 session.Wait(120) 311 Expect(session).Should(ExitCleanly()) 312 Expect(session.OutputToString()).To(ContainSubstring("1.2.3.4")) 313 314 // this tries to use the cache so we explicitly disable it 315 session = podmanTest.Podman([]string{"build", "--no-cache", "--pull-never", "--http-proxy=false", "--file", dockerfilePath, podmanTest.TempDir}) 316 session.Wait(120) 317 Expect(session).Should(Exit(1)) 318 Expect(session.ErrorToString()).To(ContainSubstring(`Error: building at STEP "RUN printenv http_proxy"`)) 319 }) 320 321 It("podman build relay exit code to process", func() { 322 if IsRemote() { 323 podmanTest.StopRemoteService() 324 podmanTest.StartRemoteService() 325 } 326 podmanTest.AddImageToRWStore(CITEST_IMAGE) 327 dockerfile := fmt.Sprintf(`FROM %s 328 RUN exit 5`, CITEST_IMAGE) 329 330 dockerfilePath := filepath.Join(podmanTest.TempDir, "Dockerfile") 331 err := os.WriteFile(dockerfilePath, []byte(dockerfile), 0755) 332 Expect(err).ToNot(HaveOccurred()) 333 session := podmanTest.Podman([]string{"build", "-t", "error-test", "--file", dockerfilePath, podmanTest.TempDir}) 334 session.Wait(120) 335 Expect(session).Should(Exit(5)) 336 }) 337 338 It("podman build and check identity", func() { 339 session := podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test", "build/basicalpine"}) 340 session.WaitWithDefaultTimeout() 341 Expect(session).Should(ExitCleanly()) 342 343 // Verify that OS and Arch are being set 344 inspect := podmanTest.Podman([]string{"image", "inspect", "--format", "{{ index .Config.Labels }}", "test"}) 345 inspect.WaitWithDefaultTimeout() 346 data := inspect.OutputToString() 347 Expect(data).To(ContainSubstring(define.Version)) 348 }) 349 350 It("podman build and check identity with always", func() { 351 // with --pull=always 352 session := podmanTest.Podman([]string{"build", "-q", "--pull=always", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test1", "build/basicalpine"}) 353 session.WaitWithDefaultTimeout() 354 Expect(session).Should(ExitCleanly()) 355 356 // Verify that OS and Arch are being set 357 inspect := podmanTest.Podman([]string{"image", "inspect", "--format", "{{ index .Config.Labels }}", "test1"}) 358 inspect.WaitWithDefaultTimeout() 359 data := inspect.OutputToString() 360 Expect(data).To(ContainSubstring(define.Version)) 361 362 // with --pull-always 363 session = podmanTest.Podman([]string{"build", "-q", "--pull-always", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test2", "build/basicalpine"}) 364 session.WaitWithDefaultTimeout() 365 Expect(session).Should(ExitCleanly()) 366 367 // Verify that OS and Arch are being set 368 inspect = podmanTest.Podman([]string{"image", "inspect", "--format", "{{ index .Config.Labels }}", "test2"}) 369 inspect.WaitWithDefaultTimeout() 370 data = inspect.OutputToString() 371 Expect(data).To(ContainSubstring(define.Version)) 372 }) 373 374 It("podman-remote send correct path to copier", func() { 375 if IsRemote() { 376 podmanTest.StopRemoteService() 377 podmanTest.StartRemoteService() 378 } 379 // Write target and fake files 380 targetSubPath := filepath.Join(podmanTest.TempDir, "emptydir") 381 if _, err = os.Stat(targetSubPath); err != nil { 382 if os.IsNotExist(err) { 383 err = os.Mkdir(targetSubPath, 0755) 384 Expect(err).ToNot(HaveOccurred()) 385 } 386 } 387 388 containerfile := fmt.Sprintf(`FROM %s 389 COPY /emptydir/* /dir`, CITEST_IMAGE) 390 391 containerfilePath := filepath.Join(podmanTest.TempDir, "ContainerfilePathToCopier") 392 err = os.WriteFile(containerfilePath, []byte(containerfile), 0644) 393 Expect(err).ToNot(HaveOccurred()) 394 defer os.Remove(containerfilePath) 395 396 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "-f", "ContainerfilePathToCopier", podmanTest.TempDir}) 397 session.WaitWithDefaultTimeout() 398 // NOTE: Docker and buildah both should error when `COPY /* /dir` is done on emptydir 399 // as context. However buildkit simply ignores this so when buildah also starts ignoring 400 // for such case edit this test to return 0 and check that no `/dir` should be in the result. 401 Expect(session).Should(Exit(125)) 402 Expect(session.ErrorToString()).To(ContainSubstring("can't make relative to")) 403 }) 404 405 It("podman remote test container/docker file is not inside context dir", func() { 406 // Given 407 // Switch to temp dir and restore it afterwards 408 cwd, err := os.Getwd() 409 Expect(err).ToNot(HaveOccurred()) 410 411 // Write target and fake files 412 targetPath := podmanTest.TempDir 413 targetSubPath := filepath.Join(targetPath, "subdir") 414 err = os.Mkdir(targetSubPath, 0755) 415 Expect(err).ToNot(HaveOccurred()) 416 dummyFile := filepath.Join(targetSubPath, "dummy") 417 err = os.WriteFile(dummyFile, []byte("dummy"), 0644) 418 Expect(err).ToNot(HaveOccurred()) 419 420 containerfile := fmt.Sprintf(`FROM %s 421 ADD . /test 422 RUN find /test`, CITEST_IMAGE) 423 424 containerfilePath := filepath.Join(targetPath, "Containerfile") 425 err = os.WriteFile(containerfilePath, []byte(containerfile), 0644) 426 Expect(err).ToNot(HaveOccurred()) 427 428 defer func() { 429 Expect(os.Chdir(cwd)).To(Succeed()) 430 }() 431 432 // make cwd as context root path 433 Expect(os.Chdir(targetPath)).To(Succeed()) 434 435 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "-f", "Containerfile", targetSubPath}) 436 session.WaitWithDefaultTimeout() 437 Expect(session).Should(ExitCleanly()) 438 Expect(session.OutputToString()).To(ContainSubstring("/test/dummy")) 439 }) 440 441 It("podman remote build must not allow symlink for ignore files", func() { 442 // Create a random file where symlink must be resolved 443 // but build should not be able to access it. 444 privateFile := filepath.Join("/tmp", "private_file") 445 f, err := os.Create(privateFile) 446 Expect(err).ToNot(HaveOccurred()) 447 // Mark hello to be ignored in outerfile, but it should not be ignored. 448 _, err = f.WriteString("hello\n") 449 Expect(err).ToNot(HaveOccurred()) 450 defer f.Close() 451 452 // Create .dockerignore which is a symlink to /tmp/private_file. 453 currentDir, err := os.Getwd() 454 Expect(err).ToNot(HaveOccurred()) 455 ignoreFile := filepath.Join(currentDir, "build/containerignore-symlink/.dockerignore") 456 err = os.Symlink(privateFile, ignoreFile) 457 Expect(err).ToNot(HaveOccurred()) 458 // Remove created .dockerignore for this test when test ends. 459 defer func() { 460 os.Remove(ignoreFile) 461 }() 462 463 if IsRemote() { 464 podmanTest.StopRemoteService() 465 podmanTest.StartRemoteService() 466 } else { 467 Skip("Only valid at remote test") 468 } 469 470 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "build/containerignore-symlink/"}) 471 session.WaitWithDefaultTimeout() 472 Expect(session).Should(ExitCleanly()) 473 474 session = podmanTest.Podman([]string{"run", "--rm", "test", "ls", "/dir"}) 475 session.WaitWithDefaultTimeout() 476 Expect(session).Should(ExitCleanly()) 477 Expect(session.OutputToString()).To(ContainSubstring("hello")) 478 }) 479 480 It("podman remote test container/docker file is not at root of context dir", func() { 481 if IsRemote() { 482 podmanTest.StopRemoteService() 483 podmanTest.StartRemoteService() 484 } else { 485 Skip("Only valid at remote test") 486 } 487 // Given 488 // Switch to temp dir and restore it afterwards 489 cwd, err := os.Getwd() 490 Expect(err).ToNot(HaveOccurred()) 491 492 podmanTest.AddImageToRWStore(CITEST_IMAGE) 493 494 // Write target and fake files 495 targetPath := podmanTest.TempDir 496 targetSubPath := filepath.Join(targetPath, "subdir") 497 err = os.Mkdir(targetSubPath, 0755) 498 Expect(err).ToNot(HaveOccurred()) 499 500 containerfile := fmt.Sprintf("FROM %s", CITEST_IMAGE) 501 502 containerfilePath := filepath.Join(targetSubPath, "Containerfile") 503 err = os.WriteFile(containerfilePath, []byte(containerfile), 0644) 504 Expect(err).ToNot(HaveOccurred()) 505 506 defer func() { 507 Expect(os.Chdir(cwd)).To(Succeed()) 508 }() 509 510 // make cwd as context root path 511 Expect(os.Chdir(targetPath)).To(Succeed()) 512 513 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "-f", "subdir/Containerfile", "."}) 514 session.WaitWithDefaultTimeout() 515 Expect(session).Should(ExitCleanly()) 516 }) 517 518 It("podman remote test .dockerignore", func() { 519 if IsRemote() { 520 podmanTest.StopRemoteService() 521 podmanTest.StartRemoteService() 522 } else { 523 Skip("Only valid at remote test") 524 } 525 // Given 526 // Switch to temp dir and restore it afterwards 527 cwd, err := os.Getwd() 528 Expect(err).ToNot(HaveOccurred()) 529 530 podmanTest.AddImageToRWStore(CITEST_IMAGE) 531 532 // Write target and fake files 533 targetPath := filepath.Join(podmanTest.TempDir, "build") 534 err = os.Mkdir(targetPath, 0755) 535 Expect(err).ToNot(HaveOccurred()) 536 537 containerfile := fmt.Sprintf(`FROM %s 538 ADD . /testfilter/ 539 RUN find /testfilter/`, CITEST_IMAGE) 540 541 containerfilePath := filepath.Join(targetPath, "Containerfile") 542 err = os.WriteFile(containerfilePath, []byte(containerfile), 0644) 543 Expect(err).ToNot(HaveOccurred()) 544 545 targetSubPath := filepath.Join(targetPath, "subdir") 546 err = os.Mkdir(targetSubPath, 0755) 547 Expect(err).ToNot(HaveOccurred()) 548 549 dummyFile1 := filepath.Join(targetPath, "dummy1") 550 err = os.WriteFile(dummyFile1, []byte("dummy1"), 0644) 551 Expect(err).ToNot(HaveOccurred()) 552 553 dummyFile2 := filepath.Join(targetPath, "dummy2") 554 err = os.WriteFile(dummyFile2, []byte("dummy2"), 0644) 555 Expect(err).ToNot(HaveOccurred()) 556 557 dummyFile3 := filepath.Join(targetSubPath, "dummy3") 558 err = os.WriteFile(dummyFile3, []byte("dummy3"), 0644) 559 Expect(err).ToNot(HaveOccurred()) 560 561 defer func() { 562 Expect(os.Chdir(cwd)).To(Succeed()) 563 Expect(os.RemoveAll(targetPath)).To(Succeed()) 564 }() 565 566 // make cwd as context root path 567 Expect(os.Chdir(targetPath)).To(Succeed()) 568 569 dockerignoreContent := `dummy1 570 subdir**` 571 dockerignoreFile := filepath.Join(targetPath, ".dockerignore") 572 573 // test .dockerignore 574 By("Test .dockererignore") 575 err = os.WriteFile(dockerignoreFile, []byte(dockerignoreContent), 0644) 576 Expect(err).ToNot(HaveOccurred()) 577 578 session := podmanTest.Podman([]string{"build", "-t", "test", "."}) 579 session.WaitWithDefaultTimeout() 580 Expect(session).Should(ExitCleanly()) 581 output := session.OutputToString() 582 Expect(output).To(ContainSubstring("/testfilter/dummy2")) 583 Expect(output).NotTo(ContainSubstring("/testfilter/dummy1")) 584 Expect(output).NotTo(ContainSubstring("/testfilter/subdir")) 585 }) 586 587 // See https://github.com/containers/podman/issues/13535 588 It("Remote build .containerignore filtering embedded directory (#13535)", func() { 589 SkipIfNotRemote("Testing remote .containerignore file filtering") 590 podmanTest.RestartRemoteService() 591 592 // Switch to temp dir and restore it afterwards 593 cwd, err := os.Getwd() 594 Expect(err).ToNot(HaveOccurred()) 595 596 podmanTest.AddImageToRWStore(CITEST_IMAGE) 597 598 contents := bytes.Buffer{} 599 contents.WriteString("FROM " + CITEST_IMAGE + "\n") 600 contents.WriteString("ADD . /testfilter/\n") 601 contents.WriteString("RUN find /testfilter/ -print\n") 602 603 containerfile := filepath.Join(tempdir, "Containerfile") 604 Expect(os.WriteFile(containerfile, contents.Bytes(), 0644)).ToNot(HaveOccurred()) 605 606 contextDir := filepath.Join(podmanTest.TempDir, "context") 607 err = os.MkdirAll(contextDir, os.ModePerm) 608 Expect(err).ToNot(HaveOccurred()) 609 610 Expect(os.WriteFile(filepath.Join(contextDir, "expected"), contents.Bytes(), 0644)). 611 ToNot(HaveOccurred()) 612 613 subdirPath := filepath.Join(contextDir, "subdir") 614 Expect(os.MkdirAll(subdirPath, 0755)).ToNot(HaveOccurred()) 615 Expect(os.WriteFile(filepath.Join(subdirPath, "extra"), contents.Bytes(), 0644)). 616 ToNot(HaveOccurred()) 617 randomFile := filepath.Join(subdirPath, "randomFile") 618 dd := exec.Command("dd", "if=/dev/urandom", "of="+randomFile, "bs=1G", "count=1") 619 ddSession, err := Start(dd, GinkgoWriter, GinkgoWriter) 620 Expect(err).ToNot(HaveOccurred()) 621 Eventually(ddSession, "30s", "1s").Should(Exit(0)) 622 623 // make cwd as context root path 624 Expect(os.Chdir(contextDir)).ToNot(HaveOccurred()) 625 defer func() { 626 err := os.Chdir(cwd) 627 Expect(err).ToNot(HaveOccurred()) 628 }() 629 630 By("Test .containerignore filtering subdirectory") 631 err = os.WriteFile(filepath.Join(contextDir, ".containerignore"), []byte(`subdir/`), 0644) 632 Expect(err).ToNot(HaveOccurred()) 633 634 session := podmanTest.Podman([]string{"build", "-f", containerfile, contextDir}) 635 session.WaitWithDefaultTimeout() 636 Expect(session).To(ExitCleanly()) 637 638 output := session.OutputToString() 639 Expect(output).To(ContainSubstring("/testfilter/expected")) 640 Expect(output).NotTo(ContainSubstring("subdir")) 641 }) 642 643 It("podman remote test context dir contains empty dirs and symlinks", func() { 644 SkipIfNotRemote("Testing remote contextDir empty") 645 podmanTest.RestartRemoteService() 646 647 // Switch to temp dir and restore it afterwards 648 cwd, err := os.Getwd() 649 Expect(err).ToNot(HaveOccurred()) 650 651 podmanTest.AddImageToRWStore(CITEST_IMAGE) 652 653 // Write target and fake files 654 targetPath := podmanTest.TempDir 655 targetSubPath := filepath.Join(targetPath, "subdir") 656 err = os.Mkdir(targetSubPath, 0755) 657 Expect(err).ToNot(HaveOccurred()) 658 dummyFile := filepath.Join(targetSubPath, "dummy") 659 err = os.WriteFile(dummyFile, []byte("dummy"), 0644) 660 Expect(err).ToNot(HaveOccurred()) 661 662 emptyDir := filepath.Join(targetSubPath, "emptyDir") 663 err = os.Mkdir(emptyDir, 0755) 664 Expect(err).ToNot(HaveOccurred()) 665 Expect(os.Chdir(targetSubPath)).To(Succeed()) 666 Expect(os.Symlink("dummy", "dummy-symlink")).To(Succeed()) 667 668 containerfile := fmt.Sprintf(`FROM %s 669 ADD . /test 670 RUN find /test 671 RUN [[ -L /test/dummy-symlink ]] && echo SYMLNKOK || echo SYMLNKERR`, CITEST_IMAGE) 672 673 containerfilePath := filepath.Join(targetSubPath, "Containerfile") 674 err = os.WriteFile(containerfilePath, []byte(containerfile), 0644) 675 Expect(err).ToNot(HaveOccurred()) 676 677 defer func() { 678 Expect(os.Chdir(cwd)).To(Succeed()) 679 }() 680 681 // make cwd as context root path 682 Expect(os.Chdir(targetPath)).To(Succeed()) 683 684 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", targetSubPath}) 685 session.WaitWithDefaultTimeout() 686 Expect(session).Should(ExitCleanly()) 687 Expect(session.OutputToString()).To(ContainSubstring("/test/dummy")) 688 Expect(session.OutputToString()).To(ContainSubstring("/test/emptyDir")) 689 Expect(session.OutputToString()).To(ContainSubstring("/test/dummy-symlink")) 690 Expect(session.OutputToString()).To(ContainSubstring("SYMLNKOK")) 691 }) 692 693 It("podman build --from, --add-host, --cap-drop, --cap-add", func() { 694 targetPath := podmanTest.TempDir 695 696 containerFile := filepath.Join(targetPath, "Containerfile") 697 content := `FROM scratch 698 RUN cat /etc/hosts 699 RUN grep CapEff /proc/self/status` 700 701 Expect(os.WriteFile(containerFile, []byte(content), 0755)).To(Succeed()) 702 703 defer func() { 704 Expect(os.RemoveAll(containerFile)).To(Succeed()) 705 }() 706 707 // When 708 session := podmanTest.Podman([]string{ 709 "build", "--pull-never", "--cap-drop=all", "--cap-add=net_bind_service", "--add-host", "testhost:1.2.3.4", "--from", CITEST_IMAGE, targetPath, 710 }) 711 session.WaitWithDefaultTimeout() 712 713 // Then 714 Expect(session).Should(ExitCleanly()) 715 Expect(strings.Fields(session.OutputToString())). 716 To(ContainElement(CITEST_IMAGE)) 717 Expect(strings.Fields(session.OutputToString())). 718 To(ContainElement("testhost")) 719 Expect(strings.Fields(session.OutputToString())). 720 To(ContainElement("0000000000000400")) 721 }) 722 723 It("podman build --isolation && --arch", func() { 724 targetPath := podmanTest.TempDir 725 containerFile := filepath.Join(targetPath, "Containerfile") 726 Expect(os.WriteFile(containerFile, []byte(fmt.Sprintf("FROM %s", CITEST_IMAGE)), 0755)).To(Succeed()) 727 728 defer func() { 729 Expect(os.RemoveAll(containerFile)).To(Succeed()) 730 }() 731 732 // When 733 session := podmanTest.Podman([]string{ 734 "build", "-q", "--isolation", "oci", "--arch", "arm64", targetPath, 735 }) 736 session.WaitWithDefaultTimeout() 737 // Then 738 Expect(session).Should(ExitCleanly()) 739 740 // When 741 session = podmanTest.Podman([]string{ 742 "build", "-q", "--isolation", "chroot", "--arch", "arm64", targetPath, 743 }) 744 session.WaitWithDefaultTimeout() 745 // Then 746 Expect(session).Should(ExitCleanly()) 747 748 // When 749 session = podmanTest.Podman([]string{ 750 "build", "-q", "--pull-never", "--isolation", "rootless", "--arch", "arm64", targetPath, 751 }) 752 session.WaitWithDefaultTimeout() 753 // Then 754 Expect(session).Should(ExitCleanly()) 755 756 // When 757 session = podmanTest.Podman([]string{ 758 "build", "-q", "--pull-never", "--isolation", "bogus", "--arch", "arm64", targetPath, 759 }) 760 session.WaitWithDefaultTimeout() 761 // Then 762 Expect(session).Should(Exit(125)) 763 }) 764 765 It("podman build --timestamp flag", func() { 766 containerfile := fmt.Sprintf(`FROM %s 767 RUN echo hello`, CITEST_IMAGE) 768 769 containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") 770 err := os.WriteFile(containerfilePath, []byte(containerfile), 0755) 771 Expect(err).ToNot(HaveOccurred()) 772 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--timestamp", "0", "--file", containerfilePath, podmanTest.TempDir}) 773 session.WaitWithDefaultTimeout() 774 Expect(session).Should(ExitCleanly()) 775 776 inspect := podmanTest.Podman([]string{"image", "inspect", "--format", "{{ .Created }}", "test"}) 777 inspect.WaitWithDefaultTimeout() 778 Expect(inspect.OutputToString()).To(Equal("1970-01-01 00:00:00 +0000 UTC")) 779 }) 780 781 It("podman build --log-rusage", func() { 782 targetPath := podmanTest.TempDir 783 784 containerFile := filepath.Join(targetPath, "Containerfile") 785 content := `FROM scratch` 786 787 Expect(os.WriteFile(containerFile, []byte(content), 0755)).To(Succeed()) 788 789 session := podmanTest.Podman([]string{"build", "--log-rusage", "--pull-never", targetPath}) 790 session.WaitWithDefaultTimeout() 791 Expect(session).Should(ExitCleanly()) 792 Expect(session.OutputToString()).To(ContainSubstring("(system)")) 793 Expect(session.OutputToString()).To(ContainSubstring("(user)")) 794 Expect(session.OutputToString()).To(ContainSubstring("(elapsed)")) 795 }) 796 797 It("podman build --arch --os flag", func() { 798 containerfile := `FROM scratch` 799 containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") 800 err := os.WriteFile(containerfilePath, []byte(containerfile), 0755) 801 Expect(err).ToNot(HaveOccurred()) 802 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--arch", "foo", "--os", "bar", "--file", containerfilePath, podmanTest.TempDir}) 803 session.WaitWithDefaultTimeout() 804 Expect(session).Should(ExitCleanly()) 805 806 inspect := podmanTest.Podman([]string{"image", "inspect", "--format", "{{ .Architecture }}", "test"}) 807 inspect.WaitWithDefaultTimeout() 808 Expect(inspect.OutputToString()).To(Equal("foo")) 809 810 inspect = podmanTest.Podman([]string{"image", "inspect", "--format", "{{ .Os }}", "test"}) 811 inspect.WaitWithDefaultTimeout() 812 Expect(inspect.OutputToString()).To(Equal("bar")) 813 814 }) 815 816 It("podman build --os windows flag", func() { 817 containerfile := `FROM scratch` 818 containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") 819 err := os.WriteFile(containerfilePath, []byte(containerfile), 0755) 820 Expect(err).ToNot(HaveOccurred()) 821 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--os", "windows", "--file", containerfilePath, podmanTest.TempDir}) 822 session.WaitWithDefaultTimeout() 823 Expect(session).Should(ExitCleanly()) 824 825 inspect := podmanTest.Podman([]string{"image", "inspect", "--format", "{{ .Architecture }}", "test"}) 826 inspect.WaitWithDefaultTimeout() 827 Expect(inspect.OutputToString()).To(Equal(runtime.GOARCH)) 828 829 inspect = podmanTest.Podman([]string{"image", "inspect", "--format", "{{ .Os }}", "test"}) 830 inspect.WaitWithDefaultTimeout() 831 Expect(inspect.OutputToString()).To(Equal("windows")) 832 833 }) 834 835 It("podman build device test", func() { 836 if _, err := os.Lstat("/dev/fuse"); err != nil { 837 Skip(fmt.Sprintf("test requires stat /dev/fuse to work: %v", err)) 838 } 839 containerfile := fmt.Sprintf(`FROM %s 840 RUN ls /dev/fuse`, CITEST_IMAGE) 841 containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") 842 err := os.WriteFile(containerfilePath, []byte(containerfile), 0755) 843 Expect(err).ToNot(HaveOccurred()) 844 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) 845 session.WaitWithDefaultTimeout() 846 Expect(session).Should(Exit(1)) 847 848 session = podmanTest.Podman([]string{"build", "--pull-never", "--device", "/dev/fuse", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) 849 session.WaitWithDefaultTimeout() 850 Expect(session).Should(ExitCleanly()) 851 }) 852 853 It("podman build device rename test", func() { 854 SkipIfRootless("rootless builds do not currently support renaming devices") 855 containerfile := fmt.Sprintf(`FROM %s 856 RUN ls /dev/test1`, CITEST_IMAGE) 857 containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") 858 err := os.WriteFile(containerfilePath, []byte(containerfile), 0755) 859 Expect(err).ToNot(HaveOccurred()) 860 session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) 861 session.WaitWithDefaultTimeout() 862 Expect(session).Should(Exit(1)) 863 864 session = podmanTest.Podman([]string{"build", "--pull-never", "--device", "/dev/zero:/dev/test1", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) 865 session.WaitWithDefaultTimeout() 866 Expect(session).Should(ExitCleanly()) 867 }) 868 869 It("podman build use absolute path even if given relative", func() { 870 containerFile := fmt.Sprintf(`FROM %s`, CITEST_IMAGE) 871 relativeDir := filepath.Join(podmanTest.TempDir, "relativeDir") 872 containerFilePath := filepath.Join(relativeDir, "Containerfile") 873 buildRoot := filepath.Join(relativeDir, "build-root") 874 875 err = os.Mkdir(relativeDir, 0755) 876 Expect(err).ToNot(HaveOccurred()) 877 err = os.Mkdir(buildRoot, 0755) 878 Expect(err).ToNot(HaveOccurred()) 879 err = os.WriteFile(containerFilePath, []byte(containerFile), 0755) 880 Expect(err).ToNot(HaveOccurred()) 881 build := podmanTest.Podman([]string{"build", "-f", containerFilePath, buildRoot}) 882 build.WaitWithDefaultTimeout() 883 Expect(build).To(ExitCleanly()) 884 }) 885 886 // system reset must run serial: https://github.com/containers/podman/issues/17903 887 It("podman system reset must clean host shared cache", Serial, func() { 888 SkipIfRemote("podman-remote does not have system reset -f") 889 useCustomNetworkDir(podmanTest, tempdir) 890 podmanTest.AddImageToRWStore(ALPINE) 891 session := podmanTest.Podman([]string{"build", "--pull-never", "--file", "build/cache/Dockerfilecachewrite", "build/cache/"}) 892 session.WaitWithDefaultTimeout() 893 Expect(session).Should(ExitCleanly()) 894 895 session = podmanTest.Podman([]string{"system", "reset", "-f"}) 896 session.WaitWithDefaultTimeout() 897 Expect(session).Should(ExitCleanly()) 898 899 session = podmanTest.Podman([]string{"build", "--pull-never", "--file", "build/cache/Dockerfilecacheread", "build/cache/"}) 900 session.WaitWithDefaultTimeout() 901 Expect(session).Should(Exit(1)) 902 }) 903 })