From c7ffbf97c8827025a5d7567cf076a83894eb256a Mon Sep 17 00:00:00 2001 From: Karol Duleba <mr.fuxi@gmail.com> Date: Thu, 24 Sep 2015 22:49:38 +0100 Subject: [PATCH] Extend oneOf error handling. Issue #1989 Signed-off-by: Karol Duleba <mr.fuxi@gmail.com> --- compose/config/validation.py | 18 +++++++++++++++++- tests/unit/config/config_test.py | 12 +++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/compose/config/validation.py b/compose/config/validation.py index 959465e98..33b660268 100644 --- a/compose/config/validation.py +++ b/compose/config/validation.py @@ -4,6 +4,7 @@ import os import sys from functools import wraps +import six from docker.utils.ports import split_port from jsonschema import Draft4Validator from jsonschema import FormatChecker @@ -162,10 +163,25 @@ def process_errors(errors, service_name=None): Inspecting the context value of a ValidationError gives us information about which sub schema failed and which kind of error it is. """ + + required = [context for context in error.context if context.validator == 'required'] + if required: + return required[0].message + + additionalProperties = [context for context in error.context if context.validator == 'additionalProperties'] + if additionalProperties: + invalid_config_key = _parse_key_from_error_msg(additionalProperties[0]) + return "contains unsupported option: '{}'".format(invalid_config_key) + constraint = [context for context in error.context if len(context.path) > 0] if constraint: valid_types = _parse_valid_types_from_validator(constraint[0].validator_value) - msg = "contains {}, which is an invalid type, it should be {}".format( + invalid_config_key = "".join( + "'{}' ".format(fragment) for fragment in constraint[0].path + if isinstance(fragment, six.string_types) + ) + msg = "{}contains {}, which is an invalid type, it should be {}".format( + invalid_config_key, constraint[0].instance, valid_types ) diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 2c3c5a3a1..7b31038f5 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -335,7 +335,7 @@ class ConfigTest(unittest.TestCase): self.assertTrue(expected_warning_msg in mock_logging.warn.call_args[0][0]) def test_config_invalid_environment_dict_key_raises_validation_error(self): - expected_error_msg = "Service 'web' configuration key 'environment' contains an invalid type" + expected_error_msg = "Service 'web' configuration key 'environment' contains unsupported option: '---'" with self.assertRaisesRegexp(ConfigurationError, expected_error_msg): config.load( @@ -957,7 +957,10 @@ class ExtendsTest(unittest.TestCase): ) def test_extends_validation_invalid_key(self): - expected_error_msg = "Unsupported config option for 'web' service: 'rogue_key'" + expected_error_msg = ( + "Service 'web' configuration key 'extends' " + "contains unsupported option: 'rogue_key'" + ) with self.assertRaisesRegexp(ConfigurationError, expected_error_msg): config.load( build_config_details( @@ -977,7 +980,10 @@ 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" + expected_error_msg = ( + "Service 'web' configuration key 'extends' 'file' contains 1, " + "which is an invalid type, it should be a string" + ) with self.assertRaisesRegexp(ConfigurationError, expected_error_msg): config.load( build_config_details(