| ... | ... |
@@ -146,6 +146,7 @@ func (container *Container) parseVolumeMountConfig() (map[string]*Mount, error) |
| 146 | 146 |
// Get the rest of the volumes |
| 147 | 147 |
for path := range container.Config.Volumes {
|
| 148 | 148 |
// Check if this is already added as a bind-mount |
| 149 |
+ path = filepath.Clean(path) |
|
| 149 | 150 |
if _, exists := mounts[path]; exists {
|
| 150 | 151 |
continue |
| 151 | 152 |
} |
| ... | ... |
@@ -195,6 +196,8 @@ func parseBindMountSpec(spec string) (string, string, bool, error) {
|
| 195 | 195 |
return "", "", false, fmt.Errorf("cannot bind mount volume: %s volume paths must be absolute.", path)
|
| 196 | 196 |
} |
| 197 | 197 |
|
| 198 |
+ path = filepath.Clean(path) |
|
| 199 |
+ mountToPath = filepath.Clean(mountToPath) |
|
| 198 | 200 |
return path, mountToPath, writable, nil |
| 199 | 201 |
} |
| 200 | 202 |
|
| ... | ... |
@@ -2396,3 +2396,53 @@ func TestRunNoOutputFromPullInStdout(t *testing.T) {
|
| 2396 | 2396 |
} |
| 2397 | 2397 |
logDone("run - no output from pull in stdout")
|
| 2398 | 2398 |
} |
| 2399 |
+ |
|
| 2400 |
+func TestRunVolumesCleanPaths(t *testing.T) {
|
|
| 2401 |
+ defer deleteAllContainers() |
|
| 2402 |
+ |
|
| 2403 |
+ if _, err := buildImage("run_volumes_clean_paths",
|
|
| 2404 |
+ `FROM busybox |
|
| 2405 |
+ VOLUME /foo/`, |
|
| 2406 |
+ true); err != nil {
|
|
| 2407 |
+ t.Fatal(err) |
|
| 2408 |
+ } |
|
| 2409 |
+ defer deleteImages("run_volumes_clean_paths")
|
|
| 2410 |
+ |
|
| 2411 |
+ cmd := exec.Command(dockerBinary, "run", "-v", "/foo", "-v", "/bar/", "--name", "dark_helmet", "run_volumes_clean_paths") |
|
| 2412 |
+ if out, _, err := runCommandWithOutput(cmd); err != nil {
|
|
| 2413 |
+ t.Fatal(err, out) |
|
| 2414 |
+ } |
|
| 2415 |
+ |
|
| 2416 |
+ out, err := inspectFieldMap("dark_helmet", "Volumes", "/foo/")
|
|
| 2417 |
+ if err != nil {
|
|
| 2418 |
+ t.Fatal(err) |
|
| 2419 |
+ } |
|
| 2420 |
+ if out != "<no value>" {
|
|
| 2421 |
+ t.Fatalf("Found unexpected volume entry for '/foo/' in volumes\n%q", out)
|
|
| 2422 |
+ } |
|
| 2423 |
+ |
|
| 2424 |
+ out, err = inspectFieldMap("dark_helmet", "Volumes", "/foo")
|
|
| 2425 |
+ if err != nil {
|
|
| 2426 |
+ t.Fatal(err) |
|
| 2427 |
+ } |
|
| 2428 |
+ if !strings.Contains(out, volumesStoragePath) {
|
|
| 2429 |
+ t.Fatalf("Volume was not defined for /foo\n%q", out)
|
|
| 2430 |
+ } |
|
| 2431 |
+ |
|
| 2432 |
+ out, err = inspectFieldMap("dark_helmet", "Volumes", "/bar/")
|
|
| 2433 |
+ if err != nil {
|
|
| 2434 |
+ t.Fatal(err) |
|
| 2435 |
+ } |
|
| 2436 |
+ if out != "<no value>" {
|
|
| 2437 |
+ t.Fatalf("Found unexpected volume entry for '/bar/' in volumes\n%q", out)
|
|
| 2438 |
+ } |
|
| 2439 |
+ out, err = inspectFieldMap("dark_helmet", "Volumes", "/bar")
|
|
| 2440 |
+ if err != nil {
|
|
| 2441 |
+ t.Fatal(err) |
|
| 2442 |
+ } |
|
| 2443 |
+ if !strings.Contains(out, volumesStoragePath) {
|
|
| 2444 |
+ t.Fatalf("Volume was not defined for /bar\n%q", out)
|
|
| 2445 |
+ } |
|
| 2446 |
+ |
|
| 2447 |
+ logDone("run - volume paths are cleaned")
|
|
| 2448 |
+} |
| ... | ... |
@@ -16,8 +16,10 @@ var ( |
| 16 | 16 |
// the private registry to use for tests |
| 17 | 17 |
privateRegistryURL = "127.0.0.1:5000" |
| 18 | 18 |
|
| 19 |
- execDriverPath = "/var/lib/docker/execdriver/native" |
|
| 20 |
- volumesConfigPath = "/var/lib/docker/volumes" |
|
| 19 |
+ dockerBasePath = "/var/lib/docker" |
|
| 20 |
+ execDriverPath = dockerBasePath + "/execdriver/native" |
|
| 21 |
+ volumesConfigPath = dockerBasePath + "/volumes" |
|
| 22 |
+ volumesStoragePath = dockerBasePath + "/vfs/dir" |
|
| 21 | 23 |
|
| 22 | 24 |
workingDirectory string |
| 23 | 25 |
) |
| ... | ... |
@@ -509,6 +509,16 @@ func inspectFieldJSON(name, field string) (string, error) {
|
| 509 | 509 |
return strings.TrimSpace(out), nil |
| 510 | 510 |
} |
| 511 | 511 |
|
| 512 |
+func inspectFieldMap(name, path, field string) (string, error) {
|
|
| 513 |
+ format := fmt.Sprintf("{{index .%s %q}}", path, field)
|
|
| 514 |
+ inspectCmd := exec.Command(dockerBinary, "inspect", "-f", format, name) |
|
| 515 |
+ out, exitCode, err := runCommandWithOutput(inspectCmd) |
|
| 516 |
+ if err != nil || exitCode != 0 {
|
|
| 517 |
+ return "", fmt.Errorf("failed to inspect %s: %s", name, out)
|
|
| 518 |
+ } |
|
| 519 |
+ return strings.TrimSpace(out), nil |
|
| 520 |
+} |
|
| 521 |
+ |
|
| 512 | 522 |
func getIDByName(name string) (string, error) {
|
| 513 | 523 |
return inspectField(name, "Id") |
| 514 | 524 |
} |
| ... | ... |
@@ -55,6 +55,7 @@ func (r *Repository) newVolume(path string, writable bool) (*Volume, error) {
|
| 55 | 55 |
return nil, err |
| 56 | 56 |
} |
| 57 | 57 |
} |
| 58 |
+ path = filepath.Clean(path) |
|
| 58 | 59 |
|
| 59 | 60 |
path, err = filepath.EvalSymlinks(path) |
| 60 | 61 |
if err != nil {
|
| ... | ... |
@@ -126,7 +127,7 @@ func (r *Repository) get(path string) *Volume {
|
| 126 | 126 |
if err != nil {
|
| 127 | 127 |
return nil |
| 128 | 128 |
} |
| 129 |
- return r.volumes[path] |
|
| 129 |
+ return r.volumes[filepath.Clean(path)] |
|
| 130 | 130 |
} |
| 131 | 131 |
|
| 132 | 132 |
func (r *Repository) Add(volume *Volume) error {
|
| ... | ... |
@@ -160,7 +161,7 @@ func (r *Repository) Delete(path string) error {
|
| 160 | 160 |
if err != nil {
|
| 161 | 161 |
return err |
| 162 | 162 |
} |
| 163 |
- volume := r.get(path) |
|
| 163 |
+ volume := r.get(filepath.Clean(path)) |
|
| 164 | 164 |
if volume == nil {
|
| 165 | 165 |
return fmt.Errorf("Volume %s does not exist", path)
|
| 166 | 166 |
} |