1
0
Эх сурвалжийг харах

Add v2 configuration tests

Signed-off-by: Joffrey F <[email protected]>
Joffrey F 10 жил өмнө
parent
commit
ecef5d37a7

+ 1 - 1
compose/config/validation.py

@@ -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)
 
 

+ 1 - 0
compose/service.py

@@ -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

+ 80 - 0
tests/integration/project_test.py

@@ -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()

+ 169 - 7
tests/unit/config/config_test.py

@@ -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):

+ 0 - 23
tests/unit/project_test.py

@@ -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, [
             {