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  })