Skip to content

Commit 0f0b20a

Browse files
committed
Merge branch 'jannefleischer/main'
Manually merging #3164. Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2 parents 8b9ad78 + bea6322 commit 0f0b20a

File tree

4 files changed

+77
-4
lines changed

4 files changed

+77
-4
lines changed

docker/api/container.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,11 @@ def create_container(self, image, command=None, hostname=None, user=None,
319319
'/var/www': {
320320
'bind': '/mnt/vol1',
321321
'mode': 'ro',
322+
},
323+
'/autofs/user1': {
324+
'bind': '/mnt/vol3',
325+
'mode': 'rw',
326+
'propagation': 'shared'
322327
}
323328
})
324329
)
@@ -329,10 +334,11 @@ def create_container(self, image, command=None, hostname=None, user=None,
329334
.. code-block:: python
330335
331336
container_id = client.api.create_container(
332-
'busybox', 'ls', volumes=['/mnt/vol1', '/mnt/vol2'],
337+
'busybox', 'ls', volumes=['/mnt/vol1', '/mnt/vol2', '/mnt/vol3'],
333338
host_config=client.api.create_host_config(binds=[
334339
'/home/user1/:/mnt/vol2',
335340
'/var/www:/mnt/vol1:ro',
341+
'/autofs/user1:/mnt/vol3:rw,shared',
336342
])
337343
)
338344

docker/utils/utils.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
from urllib.parse import urlparse, urlunparse
1919

20-
2120
URLComponents = collections.namedtuple(
2221
'URLComponents',
2322
'scheme netloc url params query fragment',
@@ -141,6 +140,22 @@ def convert_volume_binds(binds):
141140
else:
142141
mode = 'rw'
143142

143+
# NOTE: this is only relevant for Linux hosts
144+
# (doesn't apply in Docker Desktop)
145+
propagation_modes = [
146+
'rshared',
147+
'shared',
148+
'rslave',
149+
'slave',
150+
'rprivate',
151+
'private',
152+
]
153+
if 'propagation' in v and v['propagation'] in propagation_modes:
154+
if mode:
155+
mode = ','.join([mode, v['propagation']])
156+
else:
157+
mode = v['propagation']
158+
144159
result.append(
145160
f'{k}:{bind}:{mode}'
146161
)

tests/helpers.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ def untar_file(tardata, filename):
4646
return result
4747

4848

49+
def skip_if_desktop():
50+
def fn(f):
51+
@functools.wraps(f)
52+
def wrapped(self, *args, **kwargs):
53+
info = self.client.info()
54+
if info['Name'] == 'docker-desktop':
55+
pytest.skip('Test does not support Docker Desktop')
56+
return f(self, *args, **kwargs)
57+
58+
return wrapped
59+
60+
return fn
61+
4962
def requires_api_version(version):
5063
test_version = os.environ.get(
5164
'DOCKER_TEST_API_VERSION', docker.constants.DEFAULT_DOCKER_API_VERSION

tests/integration/api_container_test.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from .. import helpers
1313
from ..helpers import assert_cat_socket_detached_with_keys
1414
from ..helpers import ctrl_with
15-
from ..helpers import requires_api_version
15+
from ..helpers import requires_api_version, skip_if_desktop
1616
from .base import BaseAPIIntegrationTest
1717
from .base import TEST_IMG
1818
from docker.constants import IS_WINDOWS_PLATFORM
@@ -542,6 +542,27 @@ def test_create_with_binds_ro(self):
542542
inspect_data = self.client.inspect_container(container)
543543
self.check_container_data(inspect_data, False)
544544

545+
@skip_if_desktop()
546+
def test_create_with_binds_rw_rshared(self):
547+
container = self.run_with_volume_propagation(
548+
False,
549+
'rshared',
550+
TEST_IMG,
551+
['touch', os.path.join(self.mount_dest, self.filename)],
552+
)
553+
inspect_data = self.client.inspect_container(container)
554+
self.check_container_data(inspect_data, True, 'rshared')
555+
container = self.run_with_volume_propagation(
556+
True,
557+
'rshared',
558+
TEST_IMG,
559+
['ls', self.mount_dest],
560+
)
561+
logs = self.client.logs(container).decode('utf-8')
562+
assert self.filename in logs
563+
inspect_data = self.client.inspect_container(container)
564+
self.check_container_data(inspect_data, False, 'rshared')
565+
545566
@requires_api_version('1.30')
546567
def test_create_with_mounts(self):
547568
mount = docker.types.Mount(
@@ -597,7 +618,7 @@ def test_create_with_volume_mount(self):
597618
assert mount['Source'] == mount_data['Name']
598619
assert mount_data['RW'] is True
599620

600-
def check_container_data(self, inspect_data, rw):
621+
def check_container_data(self, inspect_data, rw, propagation='rprivate'):
601622
assert 'Mounts' in inspect_data
602623
filtered = list(filter(
603624
lambda x: x['Destination'] == self.mount_dest,
@@ -607,6 +628,7 @@ def check_container_data(self, inspect_data, rw):
607628
mount_data = filtered[0]
608629
assert mount_data['Source'] == self.mount_origin
609630
assert mount_data['RW'] == rw
631+
assert mount_data['Propagation'] == propagation
610632

611633
def run_with_volume(self, ro, *args, **kwargs):
612634
return self.run_container(
@@ -624,6 +646,23 @@ def run_with_volume(self, ro, *args, **kwargs):
624646
**kwargs
625647
)
626648

649+
def run_with_volume_propagation(self, ro, propagation, *args, **kwargs):
650+
return self.run_container(
651+
*args,
652+
volumes={self.mount_dest: {}},
653+
host_config=self.client.create_host_config(
654+
binds={
655+
self.mount_origin: {
656+
'bind': self.mount_dest,
657+
'ro': ro,
658+
'propagation': propagation
659+
},
660+
},
661+
network_mode='none'
662+
),
663+
**kwargs
664+
)
665+
627666

628667
class ArchiveTest(BaseAPIIntegrationTest):
629668
def test_get_file_archive_from_container(self):

0 commit comments

Comments
 (0)