mirror of https://github.com/docker/compose.git
Make config validation error messages more consistent.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
4b2a666231
commit
0d218c34c7
|
@ -111,30 +111,29 @@ def validate_config_section(filename, config, section):
|
||||||
"""
|
"""
|
||||||
if not isinstance(config, dict):
|
if not isinstance(config, dict):
|
||||||
raise ConfigurationError(
|
raise ConfigurationError(
|
||||||
"In file '{filename}' {section} must be a mapping, not "
|
"In file '{filename}', {section} must be a mapping, not "
|
||||||
"'{type}'.".format(
|
"{type}.".format(
|
||||||
filename=filename,
|
filename=filename,
|
||||||
section=section,
|
section=section,
|
||||||
type=python_type_to_yaml_type(config)))
|
type=anglicize_json_type(python_type_to_yaml_type(config))))
|
||||||
|
|
||||||
for key, value in config.items():
|
for key, value in config.items():
|
||||||
if not isinstance(key, six.string_types):
|
if not isinstance(key, six.string_types):
|
||||||
raise ConfigurationError(
|
raise ConfigurationError(
|
||||||
"In file '{filename}' {section} name {name} needs to be a "
|
"In file '{filename}', the {section} name {name} must be a "
|
||||||
"string, eg '{name}'".format(
|
"quoted string, i.e. '{name}'.".format(
|
||||||
filename=filename,
|
filename=filename,
|
||||||
section=section,
|
section=section,
|
||||||
name=key))
|
name=key))
|
||||||
|
|
||||||
if not isinstance(value, (dict, type(None))):
|
if not isinstance(value, (dict, type(None))):
|
||||||
raise ConfigurationError(
|
raise ConfigurationError(
|
||||||
"In file '{filename}' {section} '{name}' is the wrong type. "
|
"In file '{filename}', {section} '{name}' must be a mapping not "
|
||||||
"It should be a mapping of configuration options, it is a "
|
"{type}.".format(
|
||||||
"'{type}'.".format(
|
|
||||||
filename=filename,
|
filename=filename,
|
||||||
section=section,
|
section=section,
|
||||||
name=key,
|
name=key,
|
||||||
type=python_type_to_yaml_type(value)))
|
type=anglicize_json_type(python_type_to_yaml_type(value))))
|
||||||
|
|
||||||
|
|
||||||
def validate_top_level_object(config_file):
|
def validate_top_level_object(config_file):
|
||||||
|
@ -203,10 +202,10 @@ def get_unsupported_config_msg(path, error_key):
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
def anglicize_validator(validator):
|
def anglicize_json_type(json_type):
|
||||||
if validator in ["array", "object"]:
|
if json_type.startswith(('a', 'e', 'i', 'o', 'u')):
|
||||||
return 'an ' + validator
|
return 'an ' + json_type
|
||||||
return 'a ' + validator
|
return 'a ' + json_type
|
||||||
|
|
||||||
|
|
||||||
def is_service_dict_schema(schema_id):
|
def is_service_dict_schema(schema_id):
|
||||||
|
@ -314,14 +313,14 @@ def _parse_valid_types_from_validator(validator):
|
||||||
a valid type. Parse the valid types and prefix with the correct article.
|
a valid type. Parse the valid types and prefix with the correct article.
|
||||||
"""
|
"""
|
||||||
if not isinstance(validator, list):
|
if not isinstance(validator, list):
|
||||||
return anglicize_validator(validator)
|
return anglicize_json_type(validator)
|
||||||
|
|
||||||
if len(validator) == 1:
|
if len(validator) == 1:
|
||||||
return anglicize_validator(validator[0])
|
return anglicize_json_type(validator[0])
|
||||||
|
|
||||||
return "{}, or {}".format(
|
return "{}, or {}".format(
|
||||||
", ".join([anglicize_validator(validator[0])] + validator[1:-1]),
|
", ".join([anglicize_json_type(validator[0])] + validator[1:-1]),
|
||||||
anglicize_validator(validator[-1]))
|
anglicize_json_type(validator[-1]))
|
||||||
|
|
||||||
|
|
||||||
def _parse_oneof_validator(error):
|
def _parse_oneof_validator(error):
|
||||||
|
|
|
@ -477,7 +477,7 @@ Networks to join, referencing entries under the
|
||||||
|
|
||||||
#### aliases
|
#### aliases
|
||||||
|
|
||||||
Aliases (alternative hostnames) for this service on the network. Other containers on the same network can use either the service name or this alias to connect to one of the service's containers.
|
Aliases (alternative hostnames) for this service on the network. Other containers on the same network can use either the service name or this alias to connect to one of the service's containers.
|
||||||
|
|
||||||
Since `aliases` is network-scoped, the same service can have different aliases on different networks.
|
Since `aliases` is network-scoped, the same service can have different aliases on different networks.
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ class CLITestCase(DockerClientTestCase):
|
||||||
'-f', 'tests/fixtures/invalid-composefile/invalid.yml',
|
'-f', 'tests/fixtures/invalid-composefile/invalid.yml',
|
||||||
'config', '-q'
|
'config', '-q'
|
||||||
], returncode=1)
|
], returncode=1)
|
||||||
assert "'notaservice' is the wrong type" in result.stderr
|
assert "'notaservice' must be a mapping" in result.stderr
|
||||||
|
|
||||||
# TODO: this shouldn't be v2-dependent
|
# TODO: this shouldn't be v2-dependent
|
||||||
@v2_only()
|
@v2_only()
|
||||||
|
|
|
@ -268,7 +268,7 @@ class ConfigTest(unittest.TestCase):
|
||||||
})
|
})
|
||||||
with pytest.raises(ConfigurationError) as exc:
|
with pytest.raises(ConfigurationError) as exc:
|
||||||
config.load(config_details)
|
config.load(config_details)
|
||||||
assert "volume must be a mapping, not 'array'" in exc.exconly()
|
assert "volume must be a mapping, not an array" in exc.exconly()
|
||||||
|
|
||||||
def test_networks_invalid_type_list(self):
|
def test_networks_invalid_type_list(self):
|
||||||
config_details = build_config_details({
|
config_details = build_config_details({
|
||||||
|
@ -280,7 +280,7 @@ class ConfigTest(unittest.TestCase):
|
||||||
})
|
})
|
||||||
with pytest.raises(ConfigurationError) as exc:
|
with pytest.raises(ConfigurationError) as exc:
|
||||||
config.load(config_details)
|
config.load(config_details)
|
||||||
assert "network must be a mapping, not 'array'" in exc.exconly()
|
assert "network must be a mapping, not an array" in exc.exconly()
|
||||||
|
|
||||||
def test_load_service_with_name_version(self):
|
def test_load_service_with_name_version(self):
|
||||||
with mock.patch('compose.config.config.log') as mock_logging:
|
with mock.patch('compose.config.config.log') as mock_logging:
|
||||||
|
@ -392,8 +392,7 @@ class ConfigTest(unittest.TestCase):
|
||||||
'filename.yml')
|
'filename.yml')
|
||||||
with pytest.raises(ConfigurationError) as exc:
|
with pytest.raises(ConfigurationError) as exc:
|
||||||
config.load(config_details)
|
config.load(config_details)
|
||||||
error_msg = "service 'web' is the wrong type"
|
assert "service 'web' must be a mapping not a string." in exc.exconly()
|
||||||
assert error_msg in exc.exconly()
|
|
||||||
|
|
||||||
def test_config_integer_service_name_raise_validation_error(self):
|
def test_config_integer_service_name_raise_validation_error(self):
|
||||||
with pytest.raises(ConfigurationError) as excinfo:
|
with pytest.raises(ConfigurationError) as excinfo:
|
||||||
|
@ -405,8 +404,10 @@ class ConfigTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
assert "In file 'filename.yml' service name 1 needs to be a string, eg '1'" \
|
assert (
|
||||||
in excinfo.exconly()
|
"In file 'filename.yml', the service name 1 must be a quoted string, i.e. '1'" in
|
||||||
|
excinfo.exconly()
|
||||||
|
)
|
||||||
|
|
||||||
def test_config_integer_service_name_raise_validation_error_v2(self):
|
def test_config_integer_service_name_raise_validation_error_v2(self):
|
||||||
with pytest.raises(ConfigurationError) as excinfo:
|
with pytest.raises(ConfigurationError) as excinfo:
|
||||||
|
@ -421,8 +422,10 @@ class ConfigTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
assert "In file 'filename.yml' service name 1 needs to be a string, eg '1'" \
|
assert (
|
||||||
in excinfo.exconly()
|
"In file 'filename.yml', the service name 1 must be a quoted string, i.e. '1'." in
|
||||||
|
excinfo.exconly()
|
||||||
|
)
|
||||||
|
|
||||||
def test_load_with_multiple_files_v1(self):
|
def test_load_with_multiple_files_v1(self):
|
||||||
base_file = config.ConfigFile(
|
base_file = config.ConfigFile(
|
||||||
|
@ -556,7 +559,7 @@ class ConfigTest(unittest.TestCase):
|
||||||
|
|
||||||
with pytest.raises(ConfigurationError) as exc:
|
with pytest.raises(ConfigurationError) as exc:
|
||||||
config.load(details)
|
config.load(details)
|
||||||
assert "service 'bogus' is the wrong type" in exc.exconly()
|
assert "service 'bogus' must be a mapping not a string." in exc.exconly()
|
||||||
assert "In file 'override.yaml'" in exc.exconly()
|
assert "In file 'override.yaml'" in exc.exconly()
|
||||||
|
|
||||||
def test_load_sorts_in_dependency_order(self):
|
def test_load_sorts_in_dependency_order(self):
|
||||||
|
|
Loading…
Reference in New Issue