added support for propagation (with flake conformity)

Signed-off-by: Janne Jakob Fleischer <janne.fleischer@ils-forschung.de>
This commit is contained in:
Janne Jakob Fleischer 2023-08-09 10:03:52 +02:00
parent 84414e343e
commit 52ad76905f
3 changed files with 52 additions and 3 deletions

View File

@ -317,6 +317,11 @@ class ContainerApiMixin:
'/var/www': { '/var/www': {
'bind': '/mnt/vol1', 'bind': '/mnt/vol1',
'mode': 'ro', 'mode': 'ro',
},
'/autofs/user1': {
'bind': '/mnt/vol3',
'mode': 'rw',
'propagation': 'shared'
} }
}) })
) )
@ -327,10 +332,11 @@ class ContainerApiMixin:
.. code-block:: python .. code-block:: python
container_id = client.api.create_container( container_id = client.api.create_container(
'busybox', 'ls', volumes=['/mnt/vol1', '/mnt/vol2'], 'busybox', 'ls', volumes=['/mnt/vol1', '/mnt/vol2', '/mnt/vol3'],
host_config=client.api.create_host_config(binds=[ host_config=client.api.create_host_config(binds=[
'/home/user1/:/mnt/vol2', '/home/user1/:/mnt/vol2',
'/var/www:/mnt/vol1:ro', '/var/www:/mnt/vol1:ro',
'/autofs/user1:/mnt/vol3:rw,shared',
]) ])
) )

View File

@ -17,7 +17,6 @@ from ..tls import TLSConfig
from urllib.parse import urlparse, urlunparse from urllib.parse import urlparse, urlunparse
URLComponents = collections.namedtuple( URLComponents = collections.namedtuple(
'URLComponents', 'URLComponents',
'scheme netloc url params query fragment', 'scheme netloc url params query fragment',
@ -116,6 +115,7 @@ def convert_port_bindings(port_bindings):
def convert_volume_binds(binds): def convert_volume_binds(binds):
if isinstance(binds, list): if isinstance(binds, list):
return binds return binds
@ -141,6 +141,13 @@ def convert_volume_binds(binds):
mode = v['mode'] mode = v['mode']
else: else:
mode = 'rw' mode = 'rw'
#this is only relevant for linux-hosts; doesn't work in Docker Desktop
if 'propagation' in v and v['propagation'] in ('rshared','shared','rslave','slave','rprivate','private'):
if mode:
mode = ','.join([mode, v['propagation']])
else:
mode = v['propagation']
result.append( result.append(
f'{k}:{bind}:{mode}' f'{k}:{bind}:{mode}'

View File

@ -542,6 +542,24 @@ class VolumeBindTest(BaseAPIIntegrationTest):
inspect_data = self.client.inspect_container(container) inspect_data = self.client.inspect_container(container)
self.check_container_data(inspect_data, False) self.check_container_data(inspect_data, False)
def test_create_with_binds_rw_rshared(self):
self.run_with_volume_propagation(
False,
'rshared',
TEST_IMG,
['touch', os.path.join(self.mount_dest, self.filename)],
)
container = self.run_with_volume_propagation(
True,
'rshared',
TEST_IMG,
['ls', self.mount_dest],
)
logs = self.client.logs(container).decode('utf-8')
assert self.filename in logs
inspect_data = self.client.inspect_container(container)
self.check_container_data(inspect_data, True, 'rshared')
@requires_api_version('1.30') @requires_api_version('1.30')
def test_create_with_mounts(self): def test_create_with_mounts(self):
mount = docker.types.Mount( mount = docker.types.Mount(
@ -597,7 +615,7 @@ 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
def check_container_data(self, inspect_data, rw): 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(
lambda x: x['Destination'] == self.mount_dest, lambda x: x['Destination'] == self.mount_dest,
@ -607,6 +625,7 @@ class VolumeBindTest(BaseAPIIntegrationTest):
mount_data = filtered[0] mount_data = filtered[0]
assert mount_data['Source'] == self.mount_origin assert mount_data['Source'] == self.mount_origin
assert mount_data['RW'] == rw assert mount_data['RW'] == rw
assert mount_data['Propagation'] == propagation
def run_with_volume(self, ro, *args, **kwargs): def run_with_volume(self, ro, *args, **kwargs):
return self.run_container( return self.run_container(
@ -624,6 +643,23 @@ class VolumeBindTest(BaseAPIIntegrationTest):
**kwargs **kwargs
) )
def run_with_volume_propagation(self, ro, propagation, *args, **kwargs):
return self.run_container(
*args,
volumes={self.mount_dest: {}},
host_config=self.client.create_host_config(
binds={
self.mount_origin: {
'bind': self.mount_dest,
'ro': ro,
'propagation': propagation
},
},
network_mode='none'
),
**kwargs
)
class ArchiveTest(BaseAPIIntegrationTest): class ArchiveTest(BaseAPIIntegrationTest):
def test_get_file_archive_from_container(self): def test_get_file_archive_from_container(self):