|
1 | 1 | package integration |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "encoding/json" |
4 | 5 | "fmt" |
5 | 6 | "os" |
6 | 7 | "os/exec" |
7 | 8 | "os/user" |
8 | 9 | "path/filepath" |
| 10 | + "strconv" |
9 | 11 | "strings" |
10 | 12 |
|
11 | 13 | . "github.com/containers/podman/v4/test/utils" |
12 | 14 | . "github.com/onsi/ginkgo" |
13 | 15 | . "github.com/onsi/gomega" |
14 | 16 | . "github.com/onsi/gomega/gexec" |
| 17 | + "github.com/opencontainers/runtime-spec/specs-go" |
15 | 18 | ) |
16 | 19 |
|
17 | 20 | // in-container mount point: using a path that is definitely not present |
@@ -451,9 +454,27 @@ var _ = Describe("Podman run with volumes", func() { |
451 | 454 | Expect(separateVolumeSession).Should(Exit(0)) |
452 | 455 | Expect(separateVolumeSession.OutputToString()).To(Equal(baselineOutput)) |
453 | 456 |
|
454 | | - copySession := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol3:/etc/apk:copy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch"}) |
455 | | - copySession.WaitWithDefaultTimeout() |
456 | | - Expect(copySession).Should(Exit(0)) |
| 457 | + podmanTest.PodmanExitCleanly("run", "--name", "testctr", "-v", "testvol3:/etc/apk:copy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch") |
| 458 | + |
| 459 | + inspect := podmanTest.PodmanExitCleanly("container", "inspect", "testctr", "--format", "{{.OCIConfigPath}}") |
| 460 | + |
| 461 | + // Make extra check that the OCI config does not contain the copy opt, runc 1.3.0 fails on that while crun does not. |
| 462 | + // We only test crun upstream so make sure the spec is sane: https://github.com/containers/podman/issues/26938 |
| 463 | + f, err := os.Open(inspect.OutputToString()) |
| 464 | + Expect(err).ToNot(HaveOccurred()) |
| 465 | + defer f.Close() |
| 466 | + var spec specs.Spec |
| 467 | + err = json.NewDecoder(f).Decode(&spec) |
| 468 | + Expect(err).ToNot(HaveOccurred()) |
| 469 | + |
| 470 | + found := false |
| 471 | + for _, m := range spec.Mounts { |
| 472 | + if m.Destination == "/etc/apk" { |
| 473 | + found = true |
| 474 | + Expect(m.Options).To(Equal([]string{"rprivate", "nosuid", "nodev", "rbind"})) |
| 475 | + } |
| 476 | + } |
| 477 | + Expect(found).To(BeTrue(), "OCI spec contains /etc/apk mount") |
457 | 478 |
|
458 | 479 | noCopySession := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol4:/etc/apk:nocopy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch"}) |
459 | 480 | noCopySession.WaitWithDefaultTimeout() |
@@ -875,14 +896,18 @@ VOLUME /test/`, ALPINE) |
875 | 896 | It("podman run with --mount and named volume with driver-opts", func() { |
876 | 897 | // anonymous volume mount with driver opts |
877 | 898 | vol := "type=volume,source=test_vol,dst=/test,volume-opt=type=tmpfs,volume-opt=device=tmpfs,volume-opt=o=nodev" |
878 | | - session := podmanTest.Podman([]string{"run", "--rm", "--mount", vol, ALPINE, "echo", "hello"}) |
879 | | - session.WaitWithDefaultTimeout() |
880 | | - Expect(session).Should(Exit(0)) |
881 | 899 |
|
882 | | - inspectVol := podmanTest.Podman([]string{"volume", "inspect", "test_vol"}) |
883 | | - inspectVol.WaitWithDefaultTimeout() |
884 | | - Expect(inspectVol).Should(Exit(0)) |
885 | | - Expect(inspectVol.OutputToString()).To(ContainSubstring("nodev")) |
| 900 | + // Loop twice to cover both the initial code path that creates the volume and the ones which reuses it. |
| 901 | + for i := range 2 { |
| 902 | + name := "testctr" + strconv.Itoa(i) |
| 903 | + podmanTest.PodmanExitCleanly("run", "--name", name, "--mount", vol, ALPINE, "echo", "hello") |
| 904 | + |
| 905 | + inspectVol := podmanTest.PodmanExitCleanly("volume", "inspect", "test_vol") |
| 906 | + Expect(inspectVol.OutputToString()).To(ContainSubstring("nodev")) |
| 907 | + |
| 908 | + inspect := podmanTest.PodmanExitCleanly("container", "inspect", name, "--format", "{{range .Mounts}}{{.Options}}{{end}}") |
| 909 | + Expect(inspect.OutputToString()).To(ContainSubstring("[nosuid nodev rbind]")) |
| 910 | + } |
886 | 911 | }) |
887 | 912 |
|
888 | 913 | It("volume permissions after run", func() { |
|
0 commit comments