mirror of https://github.com/docker/compose.git
Add v2 configuration tests
Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
df6877a277
commit
ecef5d37a7
|
@ -290,7 +290,7 @@ def validate_against_fields_schema(config, filename, version):
|
|||
_validate_against_schema(
|
||||
config,
|
||||
schema_filename,
|
||||
format_checker=["ports", "environment", "bool-value-in-mapping"],
|
||||
format_checker=["ports", "expose", "bool-value-in-mapping"],
|
||||
filename=filename)
|
||||
|
||||
|
||||
|
|
|
@ -868,6 +868,7 @@ def get_container_data_volumes(container, volumes_option):
|
|||
continue
|
||||
|
||||
mount = container_mounts.get(volume.internal)
|
||||
|
||||
# New volume, doesn't exist in the old container
|
||||
if not mount:
|
||||
continue
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import random
|
||||
|
||||
from .testcases import DockerClientTestCase
|
||||
from compose.cli.docker_client import docker_client
|
||||
from compose.config import config
|
||||
|
@ -508,3 +510,81 @@ class ProjectTest(DockerClientTestCase):
|
|||
project.up()
|
||||
service = project.get_service('web')
|
||||
self.assertEqual(len(service.containers()), 1)
|
||||
|
||||
def test_project_up_volumes(self):
|
||||
vol_name = 'composetests_{0:x}'.format(random.getrandbits(32))
|
||||
config_data = config.Config(
|
||||
2, [{
|
||||
'name': 'web',
|
||||
'image': 'busybox:latest',
|
||||
'command': 'top'
|
||||
}], {vol_name: {'driver': 'local'}}
|
||||
)
|
||||
|
||||
project = Project.from_config(
|
||||
name='composetest',
|
||||
config_data=config_data, client=self.client
|
||||
)
|
||||
project.up()
|
||||
self.assertEqual(len(project.containers()), 1)
|
||||
|
||||
volume_data = self.client.inspect_volume(vol_name)
|
||||
self.assertEqual(volume_data['Name'], vol_name)
|
||||
self.assertEqual(volume_data['Driver'], 'local')
|
||||
|
||||
def test_initialize_volumes(self):
|
||||
vol_name = 'composetests_{0:x}'.format(random.getrandbits(32))
|
||||
config_data = config.Config(
|
||||
2, [{
|
||||
'name': 'web',
|
||||
'image': 'busybox:latest',
|
||||
'command': 'top'
|
||||
}], {vol_name: {}}
|
||||
)
|
||||
|
||||
project = Project.from_config(
|
||||
name='composetest',
|
||||
config_data=config_data, client=self.client
|
||||
)
|
||||
project.initialize_volumes()
|
||||
|
||||
volume_data = self.client.inspect_volume(vol_name)
|
||||
self.assertEqual(volume_data['Name'], vol_name)
|
||||
self.assertEqual(volume_data['Driver'], 'local')
|
||||
|
||||
def test_project_up_implicit_volume_driver(self):
|
||||
vol_name = 'composetests_{0:x}'.format(random.getrandbits(32))
|
||||
config_data = config.Config(
|
||||
2, [{
|
||||
'name': 'web',
|
||||
'image': 'busybox:latest',
|
||||
'command': 'top'
|
||||
}], {vol_name: {}}
|
||||
)
|
||||
|
||||
project = Project.from_config(
|
||||
name='composetest',
|
||||
config_data=config_data, client=self.client
|
||||
)
|
||||
project.up()
|
||||
|
||||
volume_data = self.client.inspect_volume(vol_name)
|
||||
self.assertEqual(volume_data['Name'], vol_name)
|
||||
self.assertEqual(volume_data['Driver'], 'local')
|
||||
|
||||
def test_project_up_invalid_volume_driver(self):
|
||||
vol_name = 'composetests_{0:x}'.format(random.getrandbits(32))
|
||||
config_data = config.Config(
|
||||
2, [{
|
||||
'name': 'web',
|
||||
'image': 'busybox:latest',
|
||||
'command': 'top'
|
||||
}], {vol_name: {'driver': 'foobar'}}
|
||||
)
|
||||
|
||||
project = Project.from_config(
|
||||
name='composetest',
|
||||
config_data=config_data, client=self.client
|
||||
)
|
||||
with self.assertRaises(config.ConfigurationError):
|
||||
project.initialize_volumes()
|
||||
|
|
|
@ -26,7 +26,7 @@ def make_service_dict(name, service_dict, working_dir, filename=None):
|
|||
working_dir=working_dir,
|
||||
filename=filename,
|
||||
name=name,
|
||||
config=service_dict))
|
||||
config=service_dict), version=1)
|
||||
return config.process_service(resolver.run())
|
||||
|
||||
|
||||
|
@ -68,6 +68,85 @@ class ConfigTest(unittest.TestCase):
|
|||
])
|
||||
)
|
||||
|
||||
def test_load_v2(self):
|
||||
config_data = config.load(
|
||||
build_config_details({
|
||||
'version': 2,
|
||||
'services': {
|
||||
'foo': {'image': 'busybox'},
|
||||
'bar': {'image': 'busybox', 'environment': ['FOO=1']},
|
||||
},
|
||||
'volumes': {
|
||||
'hello': {
|
||||
'driver': 'default',
|
||||
'driver_opts': {'beep': 'boop'}
|
||||
}
|
||||
}
|
||||
}, 'working_dir', 'filename.yml')
|
||||
)
|
||||
service_dicts = config_data.services
|
||||
volume_dict = config_data.volumes
|
||||
self.assertEqual(
|
||||
service_sort(service_dicts),
|
||||
service_sort([
|
||||
{
|
||||
'name': 'bar',
|
||||
'image': 'busybox',
|
||||
'environment': {'FOO': '1'},
|
||||
},
|
||||
{
|
||||
'name': 'foo',
|
||||
'image': 'busybox',
|
||||
}
|
||||
])
|
||||
)
|
||||
self.assertEqual(volume_dict, {
|
||||
'hello': {
|
||||
'driver': 'default',
|
||||
'driver_opts': {'beep': 'boop'}
|
||||
}
|
||||
})
|
||||
|
||||
def test_load_service_with_name_version(self):
|
||||
config_data = config.load(
|
||||
build_config_details({
|
||||
'version': {
|
||||
'image': 'busybox'
|
||||
}
|
||||
}, 'working_dir', 'filename.yml')
|
||||
)
|
||||
service_dicts = config_data.services
|
||||
self.assertEqual(
|
||||
service_sort(service_dicts),
|
||||
service_sort([
|
||||
{
|
||||
'name': 'version',
|
||||
'image': 'busybox',
|
||||
}
|
||||
])
|
||||
)
|
||||
|
||||
def test_load_invalid_version(self):
|
||||
with self.assertRaises(ConfigurationError):
|
||||
config.load(
|
||||
build_config_details({
|
||||
'version': 18,
|
||||
'services': {
|
||||
'foo': {'image': 'busybox'}
|
||||
}
|
||||
}, 'working_dir', 'filename.yml')
|
||||
)
|
||||
|
||||
with self.assertRaises(ConfigurationError):
|
||||
config.load(
|
||||
build_config_details({
|
||||
'version': 'two point oh',
|
||||
'services': {
|
||||
'foo': {'image': 'busybox'}
|
||||
}
|
||||
}, 'working_dir', 'filename.yml')
|
||||
)
|
||||
|
||||
def test_load_throws_error_when_not_dict(self):
|
||||
with self.assertRaises(ConfigurationError):
|
||||
config.load(
|
||||
|
@ -78,6 +157,16 @@ class ConfigTest(unittest.TestCase):
|
|||
)
|
||||
)
|
||||
|
||||
def test_load_throws_error_when_not_dict_v2(self):
|
||||
with self.assertRaises(ConfigurationError):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{'version': 2, 'services': {'web': 'busybox:latest'}},
|
||||
'working_dir',
|
||||
'filename.yml'
|
||||
)
|
||||
)
|
||||
|
||||
def test_load_config_invalid_service_names(self):
|
||||
for invalid_name in ['?not?allowed', ' ', '', '!', '/', '\xe2']:
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
|
@ -87,6 +176,17 @@ class ConfigTest(unittest.TestCase):
|
|||
'filename.yml'))
|
||||
assert 'Invalid service name \'%s\'' % invalid_name in exc.exconly()
|
||||
|
||||
def test_config_invalid_service_names_v2(self):
|
||||
for invalid_name in ['?not?allowed', ' ', '', '!', '/', '\xe2']:
|
||||
with pytest.raises(ConfigurationError) as exc:
|
||||
config.load(
|
||||
build_config_details({
|
||||
'version': 2,
|
||||
'services': {invalid_name: {'image': 'busybox'}}
|
||||
}, 'working_dir', 'filename.yml')
|
||||
)
|
||||
assert 'Invalid service name \'%s\'' % invalid_name in exc.exconly()
|
||||
|
||||
def test_load_with_invalid_field_name(self):
|
||||
config_details = build_config_details(
|
||||
{'web': {'image': 'busybox', 'name': 'bogus'}},
|
||||
|
@ -120,6 +220,22 @@ class ConfigTest(unittest.TestCase):
|
|||
)
|
||||
)
|
||||
|
||||
def test_config_integer_service_name_raise_validation_error_v2(self):
|
||||
expected_error_msg = ("In file 'filename.yml' service name: 1 needs to "
|
||||
"be a string, eg '1'")
|
||||
|
||||
with self.assertRaisesRegexp(ConfigurationError, expected_error_msg):
|
||||
config.load(
|
||||
build_config_details(
|
||||
{
|
||||
'version': 2,
|
||||
'services': {1: {'image': 'busybox'}}
|
||||
},
|
||||
'working_dir',
|
||||
'filename.yml'
|
||||
)
|
||||
)
|
||||
|
||||
@pytest.mark.xfail(IS_WINDOWS_PLATFORM, reason='paths use slash')
|
||||
def test_load_with_multiple_files(self):
|
||||
base_file = config.ConfigFile(
|
||||
|
@ -248,12 +364,55 @@ class ConfigTest(unittest.TestCase):
|
|||
'volumes': ['/tmp'],
|
||||
}
|
||||
})
|
||||
services = config.load(config_details)
|
||||
services = config.load(config_details).services
|
||||
|
||||
assert services[0]['name'] == 'volume'
|
||||
assert services[1]['name'] == 'db'
|
||||
assert services[2]['name'] == 'web'
|
||||
|
||||
def test_load_with_multiple_files_v2(self):
|
||||
base_file = config.ConfigFile(
|
||||
'base.yaml',
|
||||
{
|
||||
'version': 2,
|
||||
'services': {
|
||||
'web': {
|
||||
'image': 'example/web',
|
||||
'links': ['db'],
|
||||
},
|
||||
'db': {
|
||||
'image': 'example/db',
|
||||
}
|
||||
},
|
||||
})
|
||||
override_file = config.ConfigFile(
|
||||
'override.yaml',
|
||||
{
|
||||
'version': 2,
|
||||
'services': {
|
||||
'web': {
|
||||
'build': '/',
|
||||
'volumes': ['/home/user/project:/code'],
|
||||
},
|
||||
}
|
||||
})
|
||||
details = config.ConfigDetails('.', [base_file, override_file])
|
||||
|
||||
service_dicts = config.load(details).services
|
||||
expected = [
|
||||
{
|
||||
'name': 'web',
|
||||
'build': os.path.abspath('/'),
|
||||
'links': ['db'],
|
||||
'volumes': [VolumeSpec.parse('/home/user/project:/code')],
|
||||
},
|
||||
{
|
||||
'name': 'db',
|
||||
'image': 'example/db',
|
||||
},
|
||||
]
|
||||
self.assertEqual(service_sort(service_dicts), service_sort(expected))
|
||||
|
||||
def test_config_valid_service_names(self):
|
||||
for valid_name in ['_', '-', '.__.', '_what-up.', 'what_.up----', 'whatup']:
|
||||
services = config.load(
|
||||
|
@ -742,7 +901,7 @@ class VolumeConfigTest(unittest.TestCase):
|
|||
None,
|
||||
)
|
||||
).services[0]
|
||||
self.assertEqual(d['volumes'], ['/host/path:/container/path'])
|
||||
self.assertEqual(d['volumes'], [VolumeSpec.parse('/host/path:/container/path')])
|
||||
|
||||
@pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='posix paths')
|
||||
@mock.patch.dict(os.environ)
|
||||
|
@ -1130,9 +1289,10 @@ class EnvTest(unittest.TestCase):
|
|||
{'foo': {'build': '.', 'volumes': ['$HOSTENV:$CONTAINERENV']}},
|
||||
"tests/fixtures/env",
|
||||
)
|
||||
|
||||
).services[0]
|
||||
self.assertEqual(set(service_dict['volumes']), set(['/tmp:/host/tmp']))
|
||||
self.assertEqual(
|
||||
set(service_dict['volumes']),
|
||||
set([VolumeSpec.parse('/tmp:/host/tmp')]))
|
||||
|
||||
service_dict = config.load(
|
||||
build_config_details(
|
||||
|
@ -1140,7 +1300,9 @@ class EnvTest(unittest.TestCase):
|
|||
"tests/fixtures/env",
|
||||
)
|
||||
).services[0]
|
||||
self.assertEqual(set(service_dict['volumes']), set(['/opt/tmp:/opt/host/tmp']))
|
||||
self.assertEqual(
|
||||
set(service_dict['volumes']),
|
||||
set([VolumeSpec.parse('/opt/tmp:/opt/host/tmp')]))
|
||||
|
||||
|
||||
def load_from_filename(filename):
|
||||
|
@ -1595,7 +1757,7 @@ class BuildPathTest(unittest.TestCase):
|
|||
for valid_url in valid_urls:
|
||||
service_dict = config.load(build_config_details({
|
||||
'validurl': {'build': valid_url},
|
||||
}, '.', None))
|
||||
}, '.', None)).services
|
||||
assert service_dict[0]['build'] == valid_url
|
||||
|
||||
def test_invalid_url_in_build_path(self):
|
||||
|
|
|
@ -35,29 +35,6 @@ class ProjectTest(unittest.TestCase):
|
|||
self.assertEqual(project.get_service('db').name, 'db')
|
||||
self.assertEqual(project.get_service('db').options['image'], 'busybox:latest')
|
||||
|
||||
def test_from_dict_sorts_in_dependency_order(self):
|
||||
project = Project.from_config('composetest', Config(None, [
|
||||
{
|
||||
'name': 'web',
|
||||
'image': 'busybox:latest',
|
||||
'links': ['db'],
|
||||
},
|
||||
{
|
||||
'name': 'db',
|
||||
'image': 'busybox:latest',
|
||||
'volumes_from': ['volume']
|
||||
},
|
||||
{
|
||||
'name': 'volume',
|
||||
'image': 'busybox:latest',
|
||||
'volumes': ['/tmp'],
|
||||
}
|
||||
], None), None)
|
||||
|
||||
self.assertEqual(project.services[0].name, 'volume')
|
||||
self.assertEqual(project.services[1].name, 'db')
|
||||
self.assertEqual(project.services[2].name, 'web')
|
||||
|
||||
def test_from_config(self):
|
||||
dicts = Config(None, [
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue