Skip to content

Conversation

@adshmh
Copy link
Contributor

@adshmh adshmh commented Apr 9, 2019

- What I did
Added ability to mount a subdir of a volume. Part of the work required to address #32582

- How I did it
Added the required support to api, volume/mounts package, and the daemon/cluster.

- How to verify it
An integration test has been added under integration/container/mounts_linux_test.go

- Description for the changelog
Allow mounting a sub-directory of a named volume

- A picture of a cute animal (not mandatory but encouraged)

@adshmh
Copy link
Contributor Author

adshmh commented Apr 9, 2019

This feature also needs PRs on docker/swarmkit and docker/cli. I will follow up with PRs for this feature against those 2 repos if this PR is approved as a first draft.

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I only had a quick look at the changes, but left some comments

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should work on a remote daemon as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review. Yes. This was because I was starting a daemon directly, which was not needed. I will update the test to only use a client from the test environment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might need some more test-cases (probably good to combine them in a single test, using subtests). Thinking of;

  • A container using the same volume twice but with different sub-paths (also to make sure reference-counting works correctly (although I'm not sure if that makes a difference - just a quick thought)
  • A test where a non-existing sub-path is used (i.e., make sure if produces an error)
  • Multiple containers using the same volume + sub-paths? (not sure if needed; just thinking out loud; is reference-counting the same?)
  • What happens if the volume is used twice (either the same container or different containers), and the chosen sub-paths lead to "nested mounts"? (i.e. mount sub-path /foo/bar/baz and /foo/bar ?)
    • does this lead to problems, such as "unable to unmount" if one container is stopped?
    • what happens with NoCopy=false if the container that uses /foo/bar happens to have a subdirectory (or file) named /foo/bar/baz ?

Perhaps there's more/other (corner) cases that we should check for.

edit: I just noticed you have a test for the non-existent path below; still might be worth looking for some additional cases 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I will look into adding more test cases (looks like most of these cases need integration tests), while waiting for more review comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I have added a test for one container mounting the same volume twice, with different sub-paths. I think a single container will count as 1 reference to the volume, regardless of how many times it mounts the volume using different sub-paths, since the reference counting for each volume is based on container ID.

  • Non-existent sub-path test, as you mentioned in the comment, is covered by unit tests (I added an integration test too, but perhaps it can be removed once it has served its purpose of verifying the propagation of non-existent sub-path error)

  • With the current implementation proposed by this PR, the sub-path logic is in the MountPoint layer, and thus will not affect the reference counting (volume name + container id combination), i.e. mounting the same volume in different containers will have the same effect on reference counts with or without sub-path option (please let me know if this requires an explicit integration test).

Regarding overlap of sub-paths:

  • With one or multiple containers mounting a single volume, I could not find a scenario where overlap of sub-paths would affect ability to un-mount the volume, as the the reference count remains the same. (unless there is another mechanism/aspect that I have missed). The PR now includes an integration test for verifying.

  • Copying contents from the FS of a container’s image into a volume currently requires the to-be-populated volume to be empty, i.e. there won’t be an overlap between the image’s FS and the specified sub-dir. The checks performed on mounts, prior to any copying to volumes, includes verifying the existence of the specified sub-path. (I have added an integration test to warn against possible changes to this behaviour).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering; does container.Run not fail by itself already? (i.e., do we need the poll.WaitOn to check manually?) 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code (and running a few quick tests), container.Run does not fail if the command running in the container exits with non-zero error code, which is what this test uses to make sure the mounting of the sub-dir was done correctly in the second container.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see there's other lines like this in this file, so probably this is correct (just thinking about the LCOW situation, but not sure if we hit this part of the code for that)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the LCOW parser uses the windows parser, except for a different regular expression for the destination:

type lcowParser struct {
windowsParser
}

func (p *lcowParser) ParseMountSpec(cfg mount.Mount) (*MountPoint, error) {
return p.parseMountSpec(cfg, rxLCOWDestination, false, lcowSpecificValidators)

I will update the test case in parser_test.go to cover the conversion of the path separator.

@thaJeztah
Copy link
Member

@cpuguy83 @kolyshkin ptal

Signed-off-by: Arash Deshmeh <adeshmeh@ca.ibm.com>
@adshmh adshmh force-pushed the feat-32582-mount-subpath branch from cfdcd8b to b51c044 Compare April 16, 2019 17:34
@codecov
Copy link

codecov bot commented Apr 16, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@ad9362b). Click here to learn what that means.
The diff coverage is 64.44%.

@@            Coverage Diff            @@
##             master   #39041   +/-   ##
=========================================
  Coverage          ?   37.04%           
=========================================
  Files             ?      612           
  Lines             ?    45421           
  Branches          ?        0           
=========================================
  Hits              ?    16828           
  Misses            ?    26306           
  Partials          ?     2287

Signed-off-by: Arash Deshmeh <adeshmeh@ca.ibm.com>
@adshmh adshmh force-pushed the feat-32582-mount-subpath branch from b51c044 to f65a159 Compare April 16, 2019 18:04
@adshmh
Copy link
Contributor Author

adshmh commented Apr 16, 2019

Other than the expected failure on vendor, all the other failures are due to the following integration test:

15:44:28 ----------------------------------------------------------------------
15:44:28 FAIL: docker_cli_pull_test.go:273: DockerSuite.TestPullWindowsImageFailsOnLinux
15:44:28 
15:44:28 assertion failed: expected error to contain "cannot be used on this platform", got "\nCommand:  /usr/local/cli/docker pull microsoft/nanoserver\nExitCode: 1\nError:    exit status 1\nStdout:   Using default tag: latest\n\nStderr:   Error response from daemon: manifest for microsoft/nanoserver:latest not found: manifest unknown: manifest unknown\n\n\nFailures:\nExitCode was 1 expected 0\nExpected no error"
15:44:28 

@AkihiroSuda
Copy link
Member

needs rebase

err = client.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
assert.NilError(t, err)
return volumeName
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have tests for SubPath: "../../../../../../../../../.."

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use something like https://github.com/cyphar/filepath-securejoin ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

}

if !strings.HasPrefix(realPath, volumePath) {
return "", errors.Errorf("directory %s outside of the volume root %s", realPath, volumePath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's prohibit all .. symbols statically before calling filepath.Join

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] Allow mounting sub-directories of named volumes

5 participants