From 36757cde1cbe38d9673f00af0f515038b8280cfe Mon Sep 17 00:00:00 2001 From: Mazz Mosley Date: Tue, 25 Aug 2015 17:54:06 +0100 Subject: [PATCH] Validate extended service against our schema Signed-off-by: Mazz Mosley --- compose/config/config.py | 7 +-- tests/fixtures/extends/invalid-links.yml | 9 ++++ tests/fixtures/extends/invalid-net.yml | 8 ++++ tests/fixtures/extends/invalid-volumes.yml | 9 ++++ .../extends/service-with-invalid-schema.yml | 5 +++ tests/unit/config_test.py | 45 ++++++++----------- 6 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 tests/fixtures/extends/invalid-links.yml create mode 100644 tests/fixtures/extends/invalid-net.yml create mode 100644 tests/fixtures/extends/invalid-volumes.yml create mode 100644 tests/fixtures/extends/service-with-invalid-schema.yml diff --git a/compose/config/config.py b/compose/config/config.py index 0f3099dc07..65a5b5472d 100644 --- a/compose/config/config.py +++ b/compose/config/config.py @@ -182,6 +182,8 @@ class ServiceLoader(object): self.extended_config_path = self.get_extended_config_path( self.service_dict['extends'] ) + extended_config = load_yaml(self.extended_config_path) + validate_against_schema(extended_config) def detect_cycle(self, name): if self.signature(name) in self.already_seen: @@ -217,10 +219,9 @@ class ServiceLoader(object): extends_options = self.service_dict['extends'] service_name = self.service_dict['name'] + other_config_path = self.extended_config_path - other_config_path = self.get_extended_config_path(extends_options) - - other_working_dir = os.path.dirname(other_config_path) + other_working_dir = os.path.dirname(self.extended_config_path) other_already_seen = self.already_seen + [self.signature(service_name)] base_service = extends_options['service'] diff --git a/tests/fixtures/extends/invalid-links.yml b/tests/fixtures/extends/invalid-links.yml new file mode 100644 index 0000000000..edfeb8b231 --- /dev/null +++ b/tests/fixtures/extends/invalid-links.yml @@ -0,0 +1,9 @@ +myweb: + build: '.' + extends: + service: web + command: top +web: + build: '.' + links: + - "mydb:db" diff --git a/tests/fixtures/extends/invalid-net.yml b/tests/fixtures/extends/invalid-net.yml new file mode 100644 index 0000000000..fbcd020bcf --- /dev/null +++ b/tests/fixtures/extends/invalid-net.yml @@ -0,0 +1,8 @@ +myweb: + build: '.' + extends: + service: web + command: top +web: + build: '.' + net: "container:db" diff --git a/tests/fixtures/extends/invalid-volumes.yml b/tests/fixtures/extends/invalid-volumes.yml new file mode 100644 index 0000000000..3db0118e0e --- /dev/null +++ b/tests/fixtures/extends/invalid-volumes.yml @@ -0,0 +1,9 @@ +myweb: + build: '.' + extends: + service: web + command: top +web: + build: '.' + volumes_from: + - "db" diff --git a/tests/fixtures/extends/service-with-invalid-schema.yml b/tests/fixtures/extends/service-with-invalid-schema.yml new file mode 100644 index 0000000000..90dc76a0ea --- /dev/null +++ b/tests/fixtures/extends/service-with-invalid-schema.yml @@ -0,0 +1,5 @@ +myweb: + extends: + service: web +web: + command: top diff --git a/tests/unit/config_test.py b/tests/unit/config_test.py index f3a4bd306a..98ae513854 100644 --- a/tests/unit/config_test.py +++ b/tests/unit/config_test.py @@ -867,6 +867,12 @@ class ExtendsTest(unittest.TestCase): self.assertEquals(len(service), 1) self.assertIsInstance(service[0], dict) + def test_extended_service_with_invalid_config(self): + expected_error_msg = "Service 'myweb' has neither an image nor a build path specified" + + with self.assertRaisesRegexp(ConfigurationError, expected_error_msg): + load_from_filename('tests/fixtures/extends/service-with-invalid-schema.yml') + def test_extends_file_defaults_to_self(self): """ Test not specifying a file in our extends options that the @@ -891,37 +897,22 @@ class ExtendsTest(unittest.TestCase): } ])) - def test_blacklisted_options(self): - def load_config(): - return make_service_dict('myweb', { - 'extends': { - 'file': 'whatever', - 'service': 'web', - } - }, '.') + def test_invalid_links_in_extended_service(self): + expected_error_msg = "services with 'links' cannot be extended" + with self.assertRaisesRegexp(ConfigurationError, expected_error_msg): + load_from_filename('tests/fixtures/extends/invalid-links.yml') - with self.assertRaisesRegexp(ConfigurationError, 'links'): - other_config = {'web': {'links': ['db']}} + def test_invalid_volumes_from_in_extended_service(self): + expected_error_msg = "services with 'volumes_from' cannot be extended" - with mock.patch.object(config, 'load_yaml', return_value=other_config): - print(load_config()) + with self.assertRaisesRegexp(ConfigurationError, expected_error_msg): + load_from_filename('tests/fixtures/extends/invalid-volumes.yml') - with self.assertRaisesRegexp(ConfigurationError, 'volumes_from'): - other_config = {'web': {'volumes_from': ['db']}} + def test_invalid_net_in_extended_service(self): + expected_error_msg = "services with 'net: container' cannot be extended" - with mock.patch.object(config, 'load_yaml', return_value=other_config): - print(load_config()) - - with self.assertRaisesRegexp(ConfigurationError, 'net'): - other_config = {'web': {'net': 'container:db'}} - - with mock.patch.object(config, 'load_yaml', return_value=other_config): - print(load_config()) - - other_config = {'web': {'net': 'host'}} - - with mock.patch.object(config, 'load_yaml', return_value=other_config): - print(load_config()) + with self.assertRaisesRegexp(ConfigurationError, expected_error_msg): + load_from_filename('tests/fixtures/extends/invalid-net.yml') def test_volume_path(self): dicts = load_from_filename('tests/fixtures/volume-path/docker-compose.yml')