Skip to content

Commit 64c2101

Browse files
committed
feat(docker/api/container): add support for subpath in volume_opts
TESTED: Yes, added unit tests to verify subpath functionality Signed-off-by: Khushiyant <[email protected]>
1 parent db7f8b8 commit 64c2101

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

docker/types/services.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -242,14 +242,15 @@ class Mount(dict):
242242
for the ``volume`` type.
243243
driver_config (DriverConfig): Volume driver configuration. Only valid
244244
for the ``volume`` type.
245+
subpath (str): Path inside a volume to mount instead of the volume root.
245246
tmpfs_size (int or string): The size for the tmpfs mount in bytes.
246247
tmpfs_mode (int): The permission mode for the tmpfs mount.
247248
"""
248249

249250
def __init__(self, target, source, type='volume', read_only=False,
250251
consistency=None, propagation=None, no_copy=False,
251252
labels=None, driver_config=None, tmpfs_size=None,
252-
tmpfs_mode=None):
253+
tmpfs_mode=None, subpath=None):
253254
self['Target'] = target
254255
self['Source'] = source
255256
if type not in ('bind', 'volume', 'tmpfs', 'npipe'):
@@ -267,7 +268,7 @@ def __init__(self, target, source, type='volume', read_only=False,
267268
self['BindOptions'] = {
268269
'Propagation': propagation
269270
}
270-
if any([labels, driver_config, no_copy, tmpfs_size, tmpfs_mode]):
271+
if any([labels, driver_config, no_copy, tmpfs_size, tmpfs_mode, subpath]):
271272
raise errors.InvalidArgument(
272273
'Incompatible options have been provided for the bind '
273274
'type mount.'
@@ -280,6 +281,8 @@ def __init__(self, target, source, type='volume', read_only=False,
280281
volume_opts['Labels'] = labels
281282
if driver_config:
282283
volume_opts['DriverConfig'] = driver_config
284+
if subpath:
285+
volume_opts['Subpath'] = subpath
283286
if volume_opts:
284287
self['VolumeOptions'] = volume_opts
285288
if any([propagation, tmpfs_size, tmpfs_mode]):

tests/integration/api_container_test.py

+50
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,56 @@ def test_create_with_volume_mount(self):
620620
assert mount['Source'] == mount_data['Name']
621621
assert mount_data['RW'] is True
622622

623+
@requires_api_version('1.45')
624+
def test_create_with_subpath_volume_mount(self):
625+
source_volume = helpers.random_name()
626+
self.client.create_volume(name=source_volume)
627+
628+
setup_container = None
629+
test_container = None
630+
631+
632+
# Create a file structure in the volume to test with
633+
setup_container = self.client.create_container(
634+
TEST_IMG,
635+
[
636+
"sh",
637+
"-c",
638+
'mkdir -p /vol/subdir && echo "test content" > /vol/subdir/testfile.txt',
639+
],
640+
host_config=self.client.create_host_config(
641+
binds=[f"{source_volume}:/vol"]
642+
),
643+
)
644+
self.client.start(setup_container)
645+
self.client.wait(setup_container)
646+
647+
# Now test with subpath
648+
mount = docker.types.Mount(
649+
type="volume",
650+
source=source_volume,
651+
target=self.mount_dest,
652+
read_only=True,
653+
subpath="subdir",
654+
)
655+
656+
657+
host_config = self.client.create_host_config(mounts=[mount])
658+
test_container = self.client.create_container(
659+
TEST_IMG,
660+
["cat", os.path.join(self.mount_dest, "testfile.txt")],
661+
host_config=host_config,
662+
)
663+
664+
self.client.start(test_container)
665+
self.client.wait(test_container) # Wait for container to finish
666+
output = self.client.logs(test_container).decode("utf-8").strip()
667+
668+
# If the subpath feature is working, we should be able to see the content
669+
# of the file in the subdir
670+
assert output == "test content"
671+
672+
623673
def check_container_data(self, inspect_data, rw, propagation='rprivate'):
624674
assert 'Mounts' in inspect_data
625675
filtered = list(filter(

0 commit comments

Comments
 (0)