summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAditya Rajan <arajan@redhat.com>2021-09-20 15:38:51 +0530
committerAditya Rajan <arajan@redhat.com>2021-09-21 13:06:23 +0530
commitae5de8b390693784fc383b4d1df85aa92104f481 (patch)
tree2f5d3705ba132ad99cd394fb7a85c1d4ac0e5353
parentb925d707fa768245b3bd50d570b91992c1814dba (diff)
downloadpodman-ae5de8b390693784fc383b4d1df85aa92104f481.tar.gz
podman-ae5de8b390693784fc383b4d1df85aa92104f481.tar.bz2
podman-ae5de8b390693784fc383b4d1df85aa92104f481.zip
volume: Add support for overlay on named volumes
Following PR allows containers to create and mount overlays on top of named volumes instead of mounting actual volumes via already documented `:O`. Signed-off-by: Aditya Rajan <arajan@redhat.com>
-rw-r--r--libpod/container_internal_linux.go45
-rw-r--r--test/e2e/run_volume_test.go33
2 files changed, 72 insertions, 6 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index dbecea031..0a663200a 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -369,13 +369,46 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
if err != nil {
return nil, err
}
- volMount := spec.Mount{
- Type: "bind",
- Source: mountPoint,
- Destination: namedVol.Dest,
- Options: namedVol.Options,
+
+ overlayFlag := false
+ for _, o := range namedVol.Options {
+ if o == "O" {
+ overlayFlag = true
+ }
+ }
+
+ if overlayFlag {
+ contentDir, err := overlay.TempDir(c.config.StaticDir, c.RootUID(), c.RootGID())
+ if err != nil {
+ return nil, err
+ }
+ overlayMount, err := overlay.Mount(contentDir, mountPoint, namedVol.Dest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions())
+ if err != nil {
+ return nil, errors.Wrapf(err, "mounting overlay failed %q", mountPoint)
+ }
+
+ for _, o := range namedVol.Options {
+ switch o {
+ case "U":
+ if err := chown.ChangeHostPathOwnership(mountPoint, true, int(hostUID), int(hostGID)); err != nil {
+ return nil, err
+ }
+
+ if err := chown.ChangeHostPathOwnership(contentDir, true, int(hostUID), int(hostGID)); err != nil {
+ return nil, err
+ }
+ }
+ }
+ g.AddMount(overlayMount)
+ } else {
+ volMount := spec.Mount{
+ Type: "bind",
+ Source: mountPoint,
+ Destination: namedVol.Dest,
+ Options: namedVol.Options,
+ }
+ g.AddMount(volMount)
}
- g.AddMount(volMount)
}
// Check if the spec file mounts contain the options z, Z or U.
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 59937b6c0..4264e1efe 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -242,6 +242,39 @@ var _ = Describe("Podman run with volumes", func() {
Expect(session).Should(Exit(0))
})
+ It("podman support overlay on named volume", func() {
+ SkipIfRemote("Overlay volumes only work locally")
+ if os.Getenv("container") != "" {
+ Skip("Overlay mounts not supported when running in a container")
+ }
+ if rootless.IsRootless() {
+ if _, err := exec.LookPath("fuse-overlayfs"); err != nil {
+ Skip("Fuse-Overlayfs required for rootless overlay mount test")
+ }
+ }
+ session := podmanTest.Podman([]string{"volume", "create", "myvolume"})
+ session.WaitWithDefaultTimeout()
+ volName := session.OutputToString()
+ Expect(session).Should(Exit(0))
+
+ // create file on actual volume
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data", ALPINE, "sh", "-c", "echo hello >> " + "/data/test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // create file on overlayed volume
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O", ALPINE, "sh", "-c", "echo hello >> " + "/data/overlayed"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // volume should contain only `test` not `overlayed`
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data", ALPINE, "sh", "-c", "ls /data"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(Not(ContainSubstring("overlayed")))
+ Expect(session.OutputToString()).To(ContainSubstring("test"))
+
+ })
+
It("podman run with noexec can't exec", func() {
session := podmanTest.Podman([]string{"run", "--rm", "-v", "/bin:/hostbin:noexec", ALPINE, "/hostbin/ls", "/"})
session.WaitWithDefaultTimeout()