diff options
-rw-r--r-- | pkg/spec/storage.go | 38 | ||||
-rw-r--r-- | pkg/util/mountOpts.go | 16 | ||||
-rw-r--r-- | test/e2e/run_volume_test.go | 18 |
3 files changed, 51 insertions, 21 deletions
diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go index 283585ef8..ed767f5ba 100644 --- a/pkg/spec/storage.go +++ b/pkg/spec/storage.go @@ -251,9 +251,11 @@ func (config *CreateConfig) getVolumesFrom(runtime *libpod.Runtime) (map[string] return nil, nil, errors.Errorf("invalid options %q, can only specify 'ro', 'rw', and 'z", splitVol[1]) } options = strings.Split(splitVol[1], ",") - if err := ValidateVolumeOpts(options); err != nil { + opts, err := ValidateVolumeOpts(options) + if err != nil { return nil, nil, err } + options = opts } ctr, err := runtime.LookupContainer(splitVol[0]) if err != nil { @@ -447,9 +449,11 @@ func getBindMount(args []string) (spec.Mount, error) { newMount.Source = newMount.Destination } - if err := ValidateVolumeOpts(newMount.Options); err != nil { + opts, err := ValidateVolumeOpts(newMount.Options) + if err != nil { return newMount, err } + newMount.Options = opts return newMount, nil } @@ -575,35 +579,45 @@ func ValidateVolumeCtrDir(ctrDir string) error { } // ValidateVolumeOpts validates a volume's options -func ValidateVolumeOpts(options []string) error { +func ValidateVolumeOpts(options []string) ([]string, error) { var foundRootPropagation, foundRWRO, foundLabelChange, bindType int + finalOpts := make([]string, 0, len(options)) for _, opt := range options { switch opt { case "rw", "ro": foundRWRO++ if foundRWRO > 1 { - return errors.Errorf("invalid options %q, can only specify 1 'rw' or 'ro' option", strings.Join(options, ", ")) + return nil, errors.Errorf("invalid options %q, can only specify 1 'rw' or 'ro' option", strings.Join(options, ", ")) } case "z", "Z": foundLabelChange++ if foundLabelChange > 1 { - return errors.Errorf("invalid options %q, can only specify 1 'z' or 'Z' option", strings.Join(options, ", ")) + return nil, errors.Errorf("invalid options %q, can only specify 1 'z' or 'Z' option", strings.Join(options, ", ")) } case "private", "rprivate", "shared", "rshared", "slave", "rslave": foundRootPropagation++ if foundRootPropagation > 1 { - return errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private' or '[r]slave' option", strings.Join(options, ", ")) + return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private' or '[r]slave' option", strings.Join(options, ", ")) } case "bind", "rbind": bindType++ if bindType > 1 { - return errors.Errorf("invalid options %q, can only specify 1 '[r]bind' option", strings.Join(options, ", ")) - } + return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]bind' option", strings.Join(options, ", ")) + } + case "cached", "delegated": + // The discarded ops are OS X specific volume options + // introduced in a recent Docker version. + // They have no meaning on Linux, so here we silently + // drop them. This matches Docker's behavior (the options + // are intended to be always safe to use, even not on OS + // X). + continue default: - return errors.Errorf("invalid option type %q", opt) + return nil, errors.Errorf("invalid mount option %q", opt) } + finalOpts = append(finalOpts, opt) } - return nil + return finalOpts, nil } // GetVolumeMounts takes user provided input for bind mounts and creates Mount structs @@ -633,9 +647,11 @@ func (config *CreateConfig) getVolumeMounts() (map[string]spec.Mount, map[string } if len(splitVol) > 2 { options = strings.Split(splitVol[2], ",") - if err := ValidateVolumeOpts(options); err != nil { + opts, err := ValidateVolumeOpts(options) + if err != nil { return nil, nil, err } + options = opts } if err := ValidateVolumeHostDir(src); err != nil { diff --git a/pkg/util/mountOpts.go b/pkg/util/mountOpts.go index 489e7eeef..40c99384d 100644 --- a/pkg/util/mountOpts.go +++ b/pkg/util/mountOpts.go @@ -20,26 +20,22 @@ func ProcessOptions(options []string) []string { foundbind, foundrw, foundro bool rootProp string ) + for _, opt := range options { switch opt { case "bind", "rbind": foundbind = true - break - } - } - if !foundbind { - options = append(options, "rbind") - } - for _, opt := range options { - switch opt { - case "rw": - foundrw = true case "ro": foundro = true + case "rw": + foundrw = true case "private", "rprivate", "slave", "rslave", "shared", "rshared": rootProp = opt } } + if !foundbind { + options = append(options, "rbind") + } if !foundrw && !foundro { options = append(options, "rw") } diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index d89c80909..9e160e73c 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -63,6 +63,24 @@ var _ = Describe("Podman run with volumes", func() { Expect(found).Should(BeTrue()) Expect(matches[0]).To(ContainSubstring("rw")) Expect(matches[0]).To(ContainSubstring("shared")) + + // Cached is ignored + session = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/run/test:cached", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + found, matches = session.GrepString("/run/test") + Expect(found).Should(BeTrue()) + Expect(matches[0]).To(ContainSubstring("rw")) + Expect(matches[0]).To(Not(ContainSubstring("cached"))) + + // Delegated is ignored + session = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/run/test:delegated", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + found, matches = session.GrepString("/run/test") + Expect(found).Should(BeTrue()) + Expect(matches[0]).To(ContainSubstring("rw")) + Expect(matches[0]).To(Not(ContainSubstring("delegated"))) }) It("podman run with --mount flag", func() { |