Skip to content

Commit

Permalink
Merge pull request #7702 from Luap99/fix#7701
Browse files Browse the repository at this point in the history
Fix incorrect parsing of create/run --volumes-from
  • Loading branch information
openshift-merge-robot authored Sep 21, 2020
2 parents 8529435 + 44d7270 commit dd4dc4b
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 19 deletions.
2 changes: 1 addition & 1 deletion cmd/podman/common/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
"volume", "v", containerConfig.Volumes(),
"Bind mount a volume into the container",
)
createFlags.StringSliceVar(
createFlags.StringArrayVar(
&cf.VolumesFrom,
"volumes-from", []string{},
"Mount volumes from the specified container(s)",
Expand Down
13 changes: 6 additions & 7 deletions docs/source/markdown/podman-create.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -1070,11 +1070,11 @@ change propagation properties of source mount. Say `/` is source mount for

**--volumes-from**[=*CONTAINER*[:*OPTIONS*]]

Mount volumes from the specified container(s).
*OPTIONS* is a comma delimited list with the following available elements:
Mount volumes from the specified container(s). Used to share volumes between
containers. The *options* is a comma delimited list with the following available elements:

* [rw|ro]
* z
* **rw**|**ro**
* **z**

Mounts already mounted volumes from a source container onto another
container. You must supply the source's container-id or container-name.
Expand All @@ -1083,9 +1083,8 @@ the target container. You can share volumes even if the source container
is not running.

By default, Podman mounts the volumes in the same mode (read-write or
read-only) as it is mounted in the source container. Optionally, you
can change this by suffixing the container-id with either the `ro` or
`rw` keyword.
read-only) as it is mounted in the source container.
You can change this by adding a `ro` or `rw` _option_.

Labeling systems like SELinux require that proper labels are placed on volume
content mounted into a container. Without a label, the security system might
Expand Down
14 changes: 9 additions & 5 deletions docs/source/markdown/podman-run.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -1100,27 +1100,31 @@ will convert /foo into a shared mount point. Alternatively, one can directly
change propagation properties of source mount. Say, if _/_ is source mount for
_/foo_, then use **mount --make-shared /** to convert _/_ into a shared mount.

**--volumes-from**[=*container-id*[:*options*]]
**--volumes-from**[=*CONTAINER*[:*OPTIONS*]]

Mount volumes from the specified container(s). Used to share volumes between
containers. The *options* is a comma delimited list with the following available elements:

* **rw**|**ro**
* **z**

You can share volumes even if the source container is not running.
Mounts already mounted volumes from a source container onto another
container. You must supply the source's container-id or container-name.
To share a volume, use the --volumes-from option when running
the target container. You can share volumes even if the source container
is not running.

By default, Podman mounts the volumes in the same mode (read-write or
read-only) as it is mounted in the source container.
You can change this by adding a **ro** or **rw** _option_.
You can change this by adding a `ro` or `rw` _option_.

Labeling systems like SELinux require that proper labels are placed on volume
content mounted into a container. Without a label, the security system might
prevent the processes running inside the container from using the content. By
default, Podman does not change the labels set by the OS.

To change a label in the container context, you can add **z** to the volume mount.
This suffix tells Podman to relabel file objects on the shared volumes. The **z**
To change a label in the container context, you can add `z` to the volume mount.
This suffix tells Podman to relabel file objects on the shared volumes. The `z`
option tells Podman that two containers share the volume content. As a result,
podman labels the content with a shared content label. Shared volume labels allow
all containers to read/write content.
Expand Down
4 changes: 2 additions & 2 deletions pkg/specgen/generate/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s
splitVol := strings.SplitN(volume, ":", 2)
if len(splitVol) == 2 {
splitOpts := strings.Split(splitVol[1], ",")
setRORW := false
setZ := false
for _, opt := range splitOpts {
setRORW := false
setZ := false
switch opt {
case "z":
if setZ {
Expand Down
70 changes: 66 additions & 4 deletions test/e2e/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -733,23 +733,85 @@ USER mail`
err := os.MkdirAll(vol, 0755)
Expect(err).To(BeNil())

volFile := filepath.Join(vol, "test.txt")
filename := "test.txt"
volFile := filepath.Join(vol, filename)
data := "Testing --volumes-from!!!"
err = ioutil.WriteFile(volFile, []byte(data), 0755)
Expect(err).To(BeNil())
mountpoint := "/myvol/"

session := podmanTest.Podman([]string{"create", "--volume", vol + ":/myvol", redis, "sh"})
session := podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint, ALPINE, "cat", mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
ctrID := session.OutputToString()

session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "echo", "'testing read-write!' >> myvol/test.txt"})
session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "cat", mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal(data))

session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":z", ALPINE, "ls"})
session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "sh", "-c", "echo test >> " + mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))

session = podmanTest.Podman([]string{"start", "--attach", ctrID})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal(data + "test"))
})

It("podman run --volumes-from flag options", func() {
vol := filepath.Join(podmanTest.TempDir, "vol-test")
err := os.MkdirAll(vol, 0755)
Expect(err).To(BeNil())

filename := "test.txt"
volFile := filepath.Join(vol, filename)
data := "Testing --volumes-from!!!"
err = ioutil.WriteFile(volFile, []byte(data), 0755)
Expect(err).To(BeNil())
mountpoint := "/myvol/"

session := podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint, ALPINE, "cat", mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
ctrID := session.OutputToString()

// check that the read only option works
session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro", ALPINE, "touch", mountpoint + "abc.txt"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(1))
Expect(session.ErrorToString()).To(ContainSubstring("Read-only file system"))

// check that both z and ro options work
session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro,z", ALPINE, "cat", mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal(data))

// check that multiple ro/rw are not working
session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro,rw", ALPINE, "cat", mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(125))
Expect(session.ErrorToString()).To(ContainSubstring("cannot set ro or rw options more than once"))

// check that multiple z options are not working
session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":z,z,ro", ALPINE, "cat", mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(125))
Expect(session.ErrorToString()).To(ContainSubstring("cannot set :z more than once in mount options"))

// create new read only volume
session = podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint + ":ro", ALPINE, "cat", mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
ctrID = session.OutputToString()

// check if the original volume was mounted as read only that --volumes-from also mount it as read only
session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "touch", mountpoint + "abc.txt"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(1))
Expect(session.ErrorToString()).To(ContainSubstring("Read-only file system"))
})

It("podman run --volumes-from flag with built-in volumes", func() {
Expand Down

0 comments on commit dd4dc4b

Please sign in to comment.