mirror of
https://github.com/containers/podman.git
synced 2025-07-24 16:04:50 +08:00
Merge pull request #13788 from flouthoc/support-volume-opts
run, mount: allow setting driver specific option using `volume-opt=`
This commit is contained in:
@ -475,6 +475,26 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
|
|||||||
if isAnonymous {
|
if isAnonymous {
|
||||||
volOptions = append(volOptions, withSetAnon())
|
volOptions = append(volOptions, withSetAnon())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If volume-opts are set parse and add driver opts.
|
||||||
|
if len(vol.Options) > 0 {
|
||||||
|
isDriverOpts := false
|
||||||
|
driverOpts := make(map[string]string)
|
||||||
|
for _, opts := range vol.Options {
|
||||||
|
if strings.HasPrefix(opts, "volume-opt") {
|
||||||
|
isDriverOpts = true
|
||||||
|
driverOptKey, driverOptValue, err := util.ParseDriverOpts(opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
driverOpts[driverOptKey] = driverOptValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isDriverOpts {
|
||||||
|
parsedOptions := []VolumeCreateOption{WithVolumeOptions(driverOpts)}
|
||||||
|
volOptions = append(volOptions, parsedOptions...)
|
||||||
|
}
|
||||||
|
}
|
||||||
newVol, err := r.newVolume(ctx, volOptions...)
|
newVol, err := r.newVolume(ctx, volOptions...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error creating named volume %q", vol.Name)
|
return nil, errors.Wrapf(err, "error creating named volume %q", vol.Name)
|
||||||
|
@ -523,6 +523,8 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) {
|
|||||||
for _, val := range args {
|
for _, val := range args {
|
||||||
kv := strings.SplitN(val, "=", 2)
|
kv := strings.SplitN(val, "=", 2)
|
||||||
switch kv[0] {
|
switch kv[0] {
|
||||||
|
case "volume-opt":
|
||||||
|
newVolume.Options = append(newVolume.Options, val)
|
||||||
case "ro", "rw":
|
case "ro", "rw":
|
||||||
if setRORW {
|
if setRORW {
|
||||||
return nil, errors.Wrapf(optionArgError, "cannot pass 'ro' and 'rw' options more than once")
|
return nil, errors.Wrapf(optionArgError, "cannot pass 'ro' and 'rw' options more than once")
|
||||||
|
@ -57,6 +57,9 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string
|
|||||||
switch splitOpt[0] {
|
switch splitOpt[0] {
|
||||||
case "O":
|
case "O":
|
||||||
foundOverlay = true
|
foundOverlay = true
|
||||||
|
case "volume-opt":
|
||||||
|
// Volume-opt should be relayed and processed by driver.
|
||||||
|
newOptions = append(newOptions, opt)
|
||||||
case "exec", "noexec":
|
case "exec", "noexec":
|
||||||
if foundExec {
|
if foundExec {
|
||||||
return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'noexec' and 'exec' can be used")
|
return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'noexec' and 'exec' can be used")
|
||||||
@ -175,3 +178,15 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string
|
|||||||
|
|
||||||
return newOptions, nil
|
return newOptions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseDriverOpts(option string) (string, string, error) {
|
||||||
|
token := strings.SplitN(option, "=", 2)
|
||||||
|
if len(token) != 2 {
|
||||||
|
return "", "", errors.Wrapf(ErrBadMntOption, "cannot parse driver opts")
|
||||||
|
}
|
||||||
|
opt := strings.SplitN(token[1], "=", 2)
|
||||||
|
if len(opt) != 2 {
|
||||||
|
return "", "", errors.Wrapf(ErrBadMntOption, "cannot parse driver opts")
|
||||||
|
}
|
||||||
|
return opt[0], opt[1], nil
|
||||||
|
}
|
||||||
|
@ -797,6 +797,19 @@ VOLUME /test/`, ALPINE)
|
|||||||
Expect(session.OutputToString()).Should(Equal("888:888"))
|
Expect(session.OutputToString()).Should(Equal("888:888"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman run with --mount and named volume with driver-opts", func() {
|
||||||
|
// anonymous volume mount with driver opts
|
||||||
|
vol := "type=volume,source=test_vol,dst=/test,volume-opt=type=tmpfs,volume-opt=device=tmpfs,volume-opt=o=nodev"
|
||||||
|
session := podmanTest.Podman([]string{"run", "--rm", "--mount", vol, ALPINE, "echo", "hello"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
|
||||||
|
inspectVol := podmanTest.Podman([]string{"volume", "inspect", "test_vol"})
|
||||||
|
inspectVol.WaitWithDefaultTimeout()
|
||||||
|
Expect(inspectVol).Should(Exit(0))
|
||||||
|
Expect(inspectVol.OutputToString()).To(ContainSubstring("nodev"))
|
||||||
|
})
|
||||||
|
|
||||||
It("volume permissions after run", func() {
|
It("volume permissions after run", func() {
|
||||||
imgName := "testimg"
|
imgName := "testimg"
|
||||||
dockerfile := fmt.Sprintf(`FROM %s
|
dockerfile := fmt.Sprintf(`FROM %s
|
||||||
|
Reference in New Issue
Block a user