mirror of https://github.com/docker/compose.git
Merge pull request #1855 from mnowster/number-is-a-valid-service-name
A number is a valid service name
This commit is contained in:
commit
a806d9e77b
|
@ -13,7 +13,11 @@ from .errors import (
|
||||||
CircularReference,
|
CircularReference,
|
||||||
ComposeFileNotFound,
|
ComposeFileNotFound,
|
||||||
)
|
)
|
||||||
from .validation import validate_against_schema
|
from .validation import (
|
||||||
|
validate_against_schema,
|
||||||
|
validate_service_names,
|
||||||
|
validate_top_level_object
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
DOCKER_CONFIG_KEYS = [
|
DOCKER_CONFIG_KEYS = [
|
||||||
|
@ -122,19 +126,26 @@ def get_config_path(base_dir):
|
||||||
return os.path.join(path, winner)
|
return os.path.join(path, winner)
|
||||||
|
|
||||||
|
|
||||||
|
@validate_top_level_object
|
||||||
|
@validate_service_names
|
||||||
|
def pre_process_config(config):
|
||||||
|
"""
|
||||||
|
Pre validation checks and processing of the config file to interpolate env
|
||||||
|
vars returning a config dict ready to be tested against the schema.
|
||||||
|
"""
|
||||||
|
config = interpolate_environment_variables(config)
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
def load(config_details):
|
def load(config_details):
|
||||||
config, working_dir, filename = config_details
|
config, working_dir, filename = config_details
|
||||||
if not isinstance(config, dict):
|
|
||||||
raise ConfigurationError(
|
|
||||||
"Top level object needs to be a dictionary. Check your .yml file that you have defined a service at the top level."
|
|
||||||
)
|
|
||||||
|
|
||||||
config = interpolate_environment_variables(config)
|
processed_config = pre_process_config(config)
|
||||||
validate_against_schema(config)
|
validate_against_schema(processed_config)
|
||||||
|
|
||||||
service_dicts = []
|
service_dicts = []
|
||||||
|
|
||||||
for service_name, service_dict in list(config.items()):
|
for service_name, service_dict in list(processed_config.items()):
|
||||||
loader = ServiceLoader(working_dir=working_dir, filename=filename)
|
loader = ServiceLoader(working_dir=working_dir, filename=filename)
|
||||||
service_dict = loader.make_service_dict(service_name, service_dict)
|
service_dict = loader.make_service_dict(service_name, service_dict)
|
||||||
validate_paths(service_dict)
|
validate_paths(service_dict)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from functools import wraps
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from docker.utils.ports import split_port
|
from docker.utils.ports import split_port
|
||||||
|
@ -36,6 +37,29 @@ def format_ports(instance):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def validate_service_names(func):
|
||||||
|
@wraps(func)
|
||||||
|
def func_wrapper(config):
|
||||||
|
for service_name in config.keys():
|
||||||
|
if type(service_name) is int:
|
||||||
|
raise ConfigurationError(
|
||||||
|
"Service name: {} needs to be a string, eg '{}'".format(service_name, service_name)
|
||||||
|
)
|
||||||
|
return func(config)
|
||||||
|
return func_wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def validate_top_level_object(func):
|
||||||
|
@wraps(func)
|
||||||
|
def func_wrapper(config):
|
||||||
|
if not isinstance(config, dict):
|
||||||
|
raise ConfigurationError(
|
||||||
|
"Top level object needs to be a dictionary. Check your .yml file that you have defined a service at the top level."
|
||||||
|
)
|
||||||
|
return func(config)
|
||||||
|
return func_wrapper
|
||||||
|
|
||||||
|
|
||||||
def get_unsupported_config_msg(service_name, error_key):
|
def get_unsupported_config_msg(service_name, error_key):
|
||||||
msg = "Unsupported config option for '{}' service: '{}'".format(service_name, error_key)
|
msg = "Unsupported config option for '{}' service: '{}'".format(service_name, error_key)
|
||||||
if error_key in DOCKER_CONFIG_HINTS:
|
if error_key in DOCKER_CONFIG_HINTS:
|
||||||
|
|
|
@ -64,6 +64,17 @@ class ConfigTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_config_integer_service_name_raise_validation_error(self):
|
||||||
|
expected_error_msg = "Service name: 1 needs to be a string, eg '1'"
|
||||||
|
with self.assertRaisesRegexp(ConfigurationError, expected_error_msg):
|
||||||
|
config.load(
|
||||||
|
config.ConfigDetails(
|
||||||
|
{1: {'image': 'busybox'}},
|
||||||
|
'working_dir',
|
||||||
|
'filename.yml'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def test_config_valid_service_names(self):
|
def test_config_valid_service_names(self):
|
||||||
for valid_name in ['_', '-', '.__.', '_what-up.', 'what_.up----', 'whatup']:
|
for valid_name in ['_', '-', '.__.', '_what-up.', 'what_.up----', 'whatup']:
|
||||||
config.load(
|
config.load(
|
||||||
|
|
Loading…
Reference in New Issue