mirror of https://github.com/docker/docker-py.git
Merge 820769e23c
into db7f8b8bb6
This commit is contained in:
commit
96c28a54e4
|
@ -242,6 +242,7 @@ class Mount(dict):
|
||||||
for the ``volume`` type.
|
for the ``volume`` type.
|
||||||
driver_config (DriverConfig): Volume driver configuration. Only valid
|
driver_config (DriverConfig): Volume driver configuration. Only valid
|
||||||
for the ``volume`` type.
|
for the ``volume`` type.
|
||||||
|
subpath (str): Path inside a volume to mount instead of the volume root.
|
||||||
tmpfs_size (int or string): The size for the tmpfs mount in bytes.
|
tmpfs_size (int or string): The size for the tmpfs mount in bytes.
|
||||||
tmpfs_mode (int): The permission mode for the tmpfs mount.
|
tmpfs_mode (int): The permission mode for the tmpfs mount.
|
||||||
"""
|
"""
|
||||||
|
@ -249,7 +250,7 @@ class Mount(dict):
|
||||||
def __init__(self, target, source, type='volume', read_only=False,
|
def __init__(self, target, source, type='volume', read_only=False,
|
||||||
consistency=None, propagation=None, no_copy=False,
|
consistency=None, propagation=None, no_copy=False,
|
||||||
labels=None, driver_config=None, tmpfs_size=None,
|
labels=None, driver_config=None, tmpfs_size=None,
|
||||||
tmpfs_mode=None):
|
tmpfs_mode=None, subpath=None):
|
||||||
self['Target'] = target
|
self['Target'] = target
|
||||||
self['Source'] = source
|
self['Source'] = source
|
||||||
if type not in ('bind', 'volume', 'tmpfs', 'npipe'):
|
if type not in ('bind', 'volume', 'tmpfs', 'npipe'):
|
||||||
|
@ -267,7 +268,7 @@ class Mount(dict):
|
||||||
self['BindOptions'] = {
|
self['BindOptions'] = {
|
||||||
'Propagation': propagation
|
'Propagation': propagation
|
||||||
}
|
}
|
||||||
if any([labels, driver_config, no_copy, tmpfs_size, tmpfs_mode]):
|
if any([labels, driver_config, no_copy, tmpfs_size, tmpfs_mode, subpath]):
|
||||||
raise errors.InvalidArgument(
|
raise errors.InvalidArgument(
|
||||||
'Incompatible options have been provided for the bind '
|
'Incompatible options have been provided for the bind '
|
||||||
'type mount.'
|
'type mount.'
|
||||||
|
@ -280,6 +281,8 @@ class Mount(dict):
|
||||||
volume_opts['Labels'] = labels
|
volume_opts['Labels'] = labels
|
||||||
if driver_config:
|
if driver_config:
|
||||||
volume_opts['DriverConfig'] = driver_config
|
volume_opts['DriverConfig'] = driver_config
|
||||||
|
if subpath:
|
||||||
|
volume_opts['Subpath'] = subpath
|
||||||
if volume_opts:
|
if volume_opts:
|
||||||
self['VolumeOptions'] = volume_opts
|
self['VolumeOptions'] = volume_opts
|
||||||
if any([propagation, tmpfs_size, tmpfs_mode]):
|
if any([propagation, tmpfs_size, tmpfs_mode]):
|
||||||
|
|
|
@ -620,6 +620,56 @@ class VolumeBindTest(BaseAPIIntegrationTest):
|
||||||
assert mount['Source'] == mount_data['Name']
|
assert mount['Source'] == mount_data['Name']
|
||||||
assert mount_data['RW'] is True
|
assert mount_data['RW'] is True
|
||||||
|
|
||||||
|
@requires_api_version('1.45')
|
||||||
|
def test_create_with_subpath_volume_mount(self):
|
||||||
|
source_volume = helpers.random_name()
|
||||||
|
self.client.create_volume(name=source_volume)
|
||||||
|
|
||||||
|
setup_container = None
|
||||||
|
test_container = None
|
||||||
|
|
||||||
|
|
||||||
|
# Create a file structure in the volume to test with
|
||||||
|
setup_container = self.client.create_container(
|
||||||
|
TEST_IMG,
|
||||||
|
[
|
||||||
|
"sh",
|
||||||
|
"-c",
|
||||||
|
'mkdir -p /vol/subdir && echo "test content" > /vol/subdir/testfile.txt',
|
||||||
|
],
|
||||||
|
host_config=self.client.create_host_config(
|
||||||
|
binds=[f"{source_volume}:/vol"]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.client.start(setup_container)
|
||||||
|
self.client.wait(setup_container)
|
||||||
|
|
||||||
|
# Now test with subpath
|
||||||
|
mount = docker.types.Mount(
|
||||||
|
type="volume",
|
||||||
|
source=source_volume,
|
||||||
|
target=self.mount_dest,
|
||||||
|
read_only=True,
|
||||||
|
subpath="subdir",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
host_config = self.client.create_host_config(mounts=[mount])
|
||||||
|
test_container = self.client.create_container(
|
||||||
|
TEST_IMG,
|
||||||
|
["cat", os.path.join(self.mount_dest, "testfile.txt")],
|
||||||
|
host_config=host_config,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.client.start(test_container)
|
||||||
|
self.client.wait(test_container) # Wait for container to finish
|
||||||
|
output = self.client.logs(test_container).decode("utf-8").strip()
|
||||||
|
|
||||||
|
# If the subpath feature is working, we should be able to see the content
|
||||||
|
# of the file in the subdir
|
||||||
|
assert output == "test content"
|
||||||
|
|
||||||
|
|
||||||
def check_container_data(self, inspect_data, rw, propagation='rprivate'):
|
def check_container_data(self, inspect_data, rw, propagation='rprivate'):
|
||||||
assert 'Mounts' in inspect_data
|
assert 'Mounts' in inspect_data
|
||||||
filtered = list(filter(
|
filtered = list(filter(
|
||||||
|
|
Loading…
Reference in New Issue