Make volume host paths relative to file, merge volumes when extending

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
This commit is contained in:
Aanand Prasad 2015-03-18 18:23:17 -07:00
parent 4c582e4352
commit 37efdb1f8b
5 changed files with 80 additions and 12 deletions

View File

@ -166,6 +166,11 @@ def process_container_options(service_dict, working_dir=None):
msg += " (did you mean '%s'?)" % DOCKER_CONFIG_HINTS[k]
raise ConfigurationError(msg)
service_dict = service_dict.copy()
if 'volumes' in service_dict:
service_dict['volumes'] = resolve_host_paths(service_dict['volumes'], working_dir=working_dir)
return service_dict
@ -178,8 +183,14 @@ def merge_service_dicts(base, override):
override.get('environment'),
)
if 'volumes' in base or 'volumes' in override:
d['volumes'] = merge_volumes(
base.get('volumes'),
override.get('volumes'),
)
for k in ALLOWED_KEYS:
if k not in ['environment']:
if k not in ['environment', 'volumes']:
if k in override:
d[k] = override[k]
@ -285,6 +296,42 @@ def env_vars_from_file(filename):
return env
def resolve_host_paths(volumes, working_dir=None):
if working_dir is None:
raise Exception("No working_dir passed to resolve_host_paths()")
return [resolve_host_path(v, working_dir) for v in volumes]
def resolve_host_path(volume, working_dir):
container_path, host_path = split_volume(volume)
if host_path is not None:
return "%s:%s" % (expand_path(working_dir, host_path), container_path)
else:
return container_path
def merge_volumes(base, override):
d = dict_from_volumes(base)
d.update(dict_from_volumes(override))
return volumes_from_dict(d)
def dict_from_volumes(volumes):
return dict(split_volume(v) for v in volumes)
def split_volume(volume):
if ':' in volume:
return reversed(volume.split(':', 1))
else:
return (volume, None)
def volumes_from_dict(d):
return ["%s:%s" % (host_path, container_path) for (container_path, host_path) in d.items()]
def expand_path(working_dir, path):
return os.path.abspath(os.path.join(working_dir, path))

View File

@ -0,0 +1,5 @@
db:
image: busybox
volumes:
- ./foo:/foo
- ./bar:/bar

View File

@ -0,0 +1,6 @@
db:
extends:
file: common/services.yml
service: db
volumes:
- ./bar:/bar

View File

@ -7,18 +7,19 @@ from .testcases import DockerClientTestCase
class ProjectTest(DockerClientTestCase):
def test_volumes_from_service(self):
service_dicts = config.from_dictionary({
'data': {
'image': 'busybox:latest',
'volumes': ['/var/data'],
},
'db': {
'image': 'busybox:latest',
'volumes_from': ['data'],
},
}, working_dir='.')
project = Project.from_dicts(
name='composetest',
service_dicts=config.from_dictionary({
'data': {
'image': 'busybox:latest',
'volumes': ['/var/data'],
},
'db': {
'image': 'busybox:latest',
'volumes_from': ['data'],
},
}),
service_dicts=service_dicts,
client=self.client,
)
db = project.get_service('db')

View File

@ -133,7 +133,6 @@ class EnvTest(unittest.TestCase):
{'FILE_DEF': 'F1', 'FILE_DEF_EMPTY': '', 'ENV_DEF': 'E3', 'NO_DEF': ''},
)
class ExtendsTest(unittest.TestCase):
def test_extends(self):
service_dicts = config.load('tests/fixtures/extends/docker-compose.yml')
@ -241,3 +240,13 @@ class ExtendsTest(unittest.TestCase):
with mock.patch.object(config, 'load_yaml', return_value=other_config):
print load_config()
def test_volume_path(self):
dicts = config.load('tests/fixtures/volume-path/docker-compose.yml')
paths = [
'%s:/foo' % os.path.abspath('tests/fixtures/volume-path/common/foo'),
'%s:/bar' % os.path.abspath('tests/fixtures/volume-path/bar'),
]
self.assertEqual(set(dicts[0]['volumes']), set(paths))