mirror of
https://github.com/containers/podman.git
synced 2025-06-23 02:18:13 +08:00
Merge pull request #7702 from Luap99/fix#7701
Fix incorrect parsing of create/run --volumes-from
This commit is contained in:
@ -509,7 +509,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
|
|||||||
"volume", "v", containerConfig.Volumes(),
|
"volume", "v", containerConfig.Volumes(),
|
||||||
"Bind mount a volume into the container",
|
"Bind mount a volume into the container",
|
||||||
)
|
)
|
||||||
createFlags.StringSliceVar(
|
createFlags.StringArrayVar(
|
||||||
&cf.VolumesFrom,
|
&cf.VolumesFrom,
|
||||||
"volumes-from", []string{},
|
"volumes-from", []string{},
|
||||||
"Mount volumes from the specified container(s)",
|
"Mount volumes from the specified container(s)",
|
||||||
|
@ -1070,11 +1070,11 @@ change propagation properties of source mount. Say `/` is source mount for
|
|||||||
|
|
||||||
**--volumes-from**[=*CONTAINER*[:*OPTIONS*]]
|
**--volumes-from**[=*CONTAINER*[:*OPTIONS*]]
|
||||||
|
|
||||||
Mount volumes from the specified container(s).
|
Mount volumes from the specified container(s). Used to share volumes between
|
||||||
*OPTIONS* is a comma delimited list with the following available elements:
|
containers. The *options* is a comma delimited list with the following available elements:
|
||||||
|
|
||||||
* [rw|ro]
|
* **rw**|**ro**
|
||||||
* z
|
* **z**
|
||||||
|
|
||||||
Mounts already mounted volumes from a source container onto another
|
Mounts already mounted volumes from a source container onto another
|
||||||
container. You must supply the source's container-id or container-name.
|
container. You must supply the source's container-id or container-name.
|
||||||
@ -1083,9 +1083,8 @@ the target container. You can share volumes even if the source container
|
|||||||
is not running.
|
is not running.
|
||||||
|
|
||||||
By default, Podman mounts the volumes in the same mode (read-write or
|
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
|
read-only) as it is mounted in the source container.
|
||||||
can change this by suffixing the container-id with either the `ro` or
|
You can change this by adding a `ro` or `rw` _option_.
|
||||||
`rw` keyword.
|
|
||||||
|
|
||||||
Labeling systems like SELinux require that proper labels are placed on volume
|
Labeling systems like SELinux require that proper labels are placed on volume
|
||||||
content mounted into a container. Without a label, the security system might
|
content mounted into a container. Without a label, the security system might
|
||||||
|
@ -1100,7 +1100,7 @@ will convert /foo into a shared mount point. Alternatively, one can directly
|
|||||||
change propagation properties of source mount. Say, if _/_ is source mount for
|
change propagation properties of source mount. Say, if _/_ is source mount for
|
||||||
_/foo_, then use **mount --make-shared /** to convert _/_ into a shared mount.
|
_/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
|
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:
|
containers. The *options* is a comma delimited list with the following available elements:
|
||||||
@ -1108,19 +1108,23 @@ containers. The *options* is a comma delimited list with the following available
|
|||||||
* **rw**|**ro**
|
* **rw**|**ro**
|
||||||
* **z**
|
* **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
|
By default, Podman mounts the volumes in the same mode (read-write or
|
||||||
read-only) as it is mounted in the source container.
|
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
|
Labeling systems like SELinux require that proper labels are placed on volume
|
||||||
content mounted into a container. Without a label, the security system might
|
content mounted into a container. Without a label, the security system might
|
||||||
prevent the processes running inside the container from using the content. By
|
prevent the processes running inside the container from using the content. By
|
||||||
default, Podman does not change the labels set by the OS.
|
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.
|
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**
|
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,
|
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
|
podman labels the content with a shared content label. Shared volume labels allow
|
||||||
all containers to read/write content.
|
all containers to read/write content.
|
||||||
|
@ -195,9 +195,9 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s
|
|||||||
splitVol := strings.SplitN(volume, ":", 2)
|
splitVol := strings.SplitN(volume, ":", 2)
|
||||||
if len(splitVol) == 2 {
|
if len(splitVol) == 2 {
|
||||||
splitOpts := strings.Split(splitVol[1], ",")
|
splitOpts := strings.Split(splitVol[1], ",")
|
||||||
for _, opt := range splitOpts {
|
|
||||||
setRORW := false
|
setRORW := false
|
||||||
setZ := false
|
setZ := false
|
||||||
|
for _, opt := range splitOpts {
|
||||||
switch opt {
|
switch opt {
|
||||||
case "z":
|
case "z":
|
||||||
if setZ {
|
if setZ {
|
||||||
|
@ -733,23 +733,85 @@ USER mail`
|
|||||||
err := os.MkdirAll(vol, 0755)
|
err := os.MkdirAll(vol, 0755)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
volFile := filepath.Join(vol, "test.txt")
|
filename := "test.txt"
|
||||||
|
volFile := filepath.Join(vol, filename)
|
||||||
data := "Testing --volumes-from!!!"
|
data := "Testing --volumes-from!!!"
|
||||||
err = ioutil.WriteFile(volFile, []byte(data), 0755)
|
err = ioutil.WriteFile(volFile, []byte(data), 0755)
|
||||||
Expect(err).To(BeNil())
|
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()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
ctrID := session.OutputToString()
|
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, ALPINE, "sh", "-c", "echo test >> " + mountpoint + filename})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":z", ALPINE, "ls"})
|
session = podmanTest.Podman([]string{"start", "--attach", ctrID})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
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() {
|
It("podman run --volumes-from flag with built-in volumes", func() {
|
||||||
|
Reference in New Issue
Block a user