Mount with same container path and different mode should override

Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
Joffrey F 2017-09-27 17:10:13 -07:00
parent aecd0a9483
commit f74838676d
2 changed files with 60 additions and 13 deletions

View File

@ -1137,23 +1137,29 @@ def resolve_volume_paths(working_dir, service_dict):
def resolve_volume_path(working_dir, volume): def resolve_volume_path(working_dir, volume):
mount_params = None
if isinstance(volume, dict): if isinstance(volume, dict):
host_path = volume.get('source')
container_path = volume.get('target') container_path = volume.get('target')
host_path = volume.get('source')
mode = None
if host_path: if host_path:
if volume.get('read_only'): if volume.get('read_only'):
container_path += ':ro' mode = 'ro'
if volume.get('volume', {}).get('nocopy'): if volume.get('volume', {}).get('nocopy'):
container_path += ':nocopy' mode = 'nocopy'
mount_params = (host_path, mode)
else: else:
container_path, host_path = split_path_mapping(volume) container_path, mount_params = split_path_mapping(volume)
if host_path is not None: if mount_params is not None:
host_path, mode = mount_params
if host_path is None:
return container_path
if host_path.startswith('.'): if host_path.startswith('.'):
host_path = expand_path(working_dir, host_path) host_path = expand_path(working_dir, host_path)
host_path = os.path.expanduser(host_path) host_path = os.path.expanduser(host_path)
return u"{}:{}".format(host_path, container_path) return u"{}:{}{}".format(host_path, container_path, (':' + mode if mode else ''))
else:
return container_path return container_path
@ -1234,7 +1240,12 @@ def split_path_mapping(volume_path):
if ':' in volume_config: if ':' in volume_config:
(host, container) = volume_config.split(':', 1) (host, container) = volume_config.split(':', 1)
return (container, drive + host) container_drive, container_path = splitdrive(container)
mode = None
if ':' in container_path:
container_path, mode = container_path.rsplit(':', 1)
return (container_drive + container_path, (drive + host, mode))
else: else:
return (volume_path, None) return (volume_path, None)
@ -1246,7 +1257,11 @@ def join_path_mapping(pair):
elif host is None: elif host is None:
return container return container
else: else:
return ":".join((host, container)) host, mode = host
result = ":".join((host, container))
if mode:
result += ":" + mode
return result
def expand_path(working_dir, path): def expand_path(working_dir, path):

View File

@ -1101,6 +1101,38 @@ class ConfigTest(unittest.TestCase):
['/anonymous', '/c:/b:rw', 'vol:/x:ro'] ['/anonymous', '/c:/b:rw', 'vol:/x:ro']
) )
@mock.patch.dict(os.environ)
def test_volume_mode_override(self):
os.environ['COMPOSE_CONVERT_WINDOWS_PATHS'] = 'true'
base_file = config.ConfigFile(
'base.yaml',
{
'version': '2.3',
'services': {
'web': {
'image': 'example/web',
'volumes': ['/c:/b:rw']
}
},
}
)
override_file = config.ConfigFile(
'override.yaml',
{
'version': '2.3',
'services': {
'web': {
'volumes': ['/c:/b:ro']
}
}
}
)
details = config.ConfigDetails('.', [base_file, override_file])
service_dicts = config.load(details).services
svc_volumes = list(map(lambda v: v.repr(), service_dicts[0]['volumes']))
assert svc_volumes == ['/c:/b:ro']
def test_undeclared_volume_v2(self): def test_undeclared_volume_v2(self):
base_file = config.ConfigFile( base_file = config.ConfigFile(
'base.yaml', 'base.yaml',
@ -4018,7 +4050,7 @@ class VolumePathTest(unittest.TestCase):
def test_split_path_mapping_with_windows_path(self): def test_split_path_mapping_with_windows_path(self):
host_path = "c:\\Users\\msamblanet\\Documents\\anvil\\connect\\config" host_path = "c:\\Users\\msamblanet\\Documents\\anvil\\connect\\config"
windows_volume_path = host_path + ":/opt/connect/config:ro" windows_volume_path = host_path + ":/opt/connect/config:ro"
expected_mapping = ("/opt/connect/config:ro", host_path) expected_mapping = ("/opt/connect/config", (host_path, 'ro'))
mapping = config.split_path_mapping(windows_volume_path) mapping = config.split_path_mapping(windows_volume_path)
assert mapping == expected_mapping assert mapping == expected_mapping
@ -4026,7 +4058,7 @@ class VolumePathTest(unittest.TestCase):
def test_split_path_mapping_with_windows_path_in_container(self): def test_split_path_mapping_with_windows_path_in_container(self):
host_path = 'c:\\Users\\remilia\\data' host_path = 'c:\\Users\\remilia\\data'
container_path = 'c:\\scarletdevil\\data' container_path = 'c:\\scarletdevil\\data'
expected_mapping = (container_path, host_path) expected_mapping = (container_path, (host_path, None))
mapping = config.split_path_mapping('{0}:{1}'.format(host_path, container_path)) mapping = config.split_path_mapping('{0}:{1}'.format(host_path, container_path))
assert mapping == expected_mapping assert mapping == expected_mapping
@ -4034,7 +4066,7 @@ class VolumePathTest(unittest.TestCase):
def test_split_path_mapping_with_root_mount(self): def test_split_path_mapping_with_root_mount(self):
host_path = '/' host_path = '/'
container_path = '/var/hostroot' container_path = '/var/hostroot'
expected_mapping = (container_path, host_path) expected_mapping = (container_path, (host_path, None))
mapping = config.split_path_mapping('{0}:{1}'.format(host_path, container_path)) mapping = config.split_path_mapping('{0}:{1}'.format(host_path, container_path))
assert mapping == expected_mapping assert mapping == expected_mapping