diff --git a/compose/config/validation.py b/compose/config/validation.py index 7347c0128..aa2e0fcf4 100644 --- a/compose/config/validation.py +++ b/compose/config/validation.py @@ -99,12 +99,14 @@ def process_errors(errors): if error.validator_value == "array": msg = "an" - try: - config_key = error.path[1] - type_errors.append("Service '{}' has an invalid value for '{}', it should be {} {}".format(service_name, config_key, msg, error.validator_value)) - except IndexError: - config_key = error.path[0] - root_msgs.append("Service '{}' doesn\'t have any configuration options. All top level keys in your docker-compose.yml must map to a dictionary of configuration options.'".format(config_key)) + # pop the service name off our path + error.path.popleft() + + if len(error.path) > 0: + config_key = " ".join(["'%s'" % k for k in error.path]) + type_errors.append("Service '{}' configuration key {} contains an invalid type, it should be {} {}".format(service_name, config_key, msg, error.validator_value)) + else: + root_msgs.append("Service '{}' doesn\'t have any configuration options. All top level keys in your docker-compose.yml must map to a dictionary of configuration options.'".format(service_name)) elif error.validator == 'required': config_key = error.path[1] required.append("Service '{}' option '{}' is invalid, {}".format(service_name, config_key, _clean_error_message(error.message))) diff --git a/tests/unit/config_test.py b/tests/unit/config_test.py index e023153a3..0ea375db4 100644 --- a/tests/unit/config_test.py +++ b/tests/unit/config_test.py @@ -124,7 +124,7 @@ class ConfigTest(unittest.TestCase): ) def test_invalid_config_type_should_be_an_array(self): - expected_error_msg = "Service 'foo' has an invalid value for 'links', it should be an array" + expected_error_msg = "Service 'foo' configuration key 'links' contains an invalid type, it should be an array" with self.assertRaisesRegexp(ConfigurationError, expected_error_msg): config.load( config.ConfigDetails( @@ -690,6 +690,25 @@ class ExtendsTest(unittest.TestCase): ) ) + def test_extends_validation_sub_property_key(self): + expected_error_msg = "Service 'web' configuration key 'extends' 'file' contains an invalid type" + with self.assertRaisesRegexp(ConfigurationError, expected_error_msg): + config.load( + config.ConfigDetails( + { + 'web': { + 'image': 'busybox', + 'extends': { + 'file': 1, + 'service': 'web', + } + }, + }, + 'tests/fixtures/extends', + 'filename.yml' + ) + ) + def test_extends_validation_no_file_key_no_filename_set(self): dictionary = {'extends': {'service': 'web'}}