mirror of https://github.com/docker/compose.git
Mount with same container path and different mode should override
Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
aecd0a9483
commit
f74838676d
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue