mirror of
https://github.com/docker/compose.git
synced 2025-07-25 14:44:29 +02:00
Constraint build argument types. Numbers are cast into strings
Numerical driver_opts are also valid and typecast into strings. Additional config tests. Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
parent
8d7b1e9047
commit
fcf78fe3de
@ -16,6 +16,7 @@ from cached_property import cached_property
|
|||||||
|
|
||||||
from ..const import COMPOSEFILE_V1 as V1
|
from ..const import COMPOSEFILE_V1 as V1
|
||||||
from ..const import COMPOSEFILE_V2_0 as V2_0
|
from ..const import COMPOSEFILE_V2_0 as V2_0
|
||||||
|
from ..utils import build_string_dict
|
||||||
from .errors import CircularReference
|
from .errors import CircularReference
|
||||||
from .errors import ComposeFileNotFound
|
from .errors import ComposeFileNotFound
|
||||||
from .errors import ConfigurationError
|
from .errors import ConfigurationError
|
||||||
@ -291,7 +292,7 @@ def load(config_details):
|
|||||||
config_details = config_details._replace(config_files=processed_files)
|
config_details = config_details._replace(config_files=processed_files)
|
||||||
|
|
||||||
main_file = config_details.config_files[0]
|
main_file = config_details.config_files[0]
|
||||||
volumes = load_mapping(config_details.config_files, 'get_volumes', 'Volume')
|
volumes = load_volumes(config_details.config_files)
|
||||||
networks = load_mapping(config_details.config_files, 'get_networks', 'Network')
|
networks = load_mapping(config_details.config_files, 'get_networks', 'Network')
|
||||||
service_dicts = load_services(
|
service_dicts = load_services(
|
||||||
config_details.working_dir,
|
config_details.working_dir,
|
||||||
@ -335,6 +336,14 @@ def load_mapping(config_files, get_func, entity_type):
|
|||||||
return mapping
|
return mapping
|
||||||
|
|
||||||
|
|
||||||
|
def load_volumes(config_files):
|
||||||
|
volumes = load_mapping(config_files, 'get_volumes', 'Volume')
|
||||||
|
for volume_name, volume in volumes.items():
|
||||||
|
if 'driver_opts' in volume:
|
||||||
|
volume['driver_opts'] = build_string_dict(volume['driver_opts'])
|
||||||
|
return volumes
|
||||||
|
|
||||||
|
|
||||||
def load_services(working_dir, config_file, service_configs):
|
def load_services(working_dir, config_file, service_configs):
|
||||||
def build_service(service_name, service_dict, service_names):
|
def build_service(service_name, service_dict, service_names):
|
||||||
service_config = ServiceConfig.with_abs_paths(
|
service_config = ServiceConfig.with_abs_paths(
|
||||||
@ -854,7 +863,7 @@ def normalize_build(service_dict, working_dir):
|
|||||||
else:
|
else:
|
||||||
build.update(service_dict['build'])
|
build.update(service_dict['build'])
|
||||||
if 'args' in build:
|
if 'args' in build:
|
||||||
build['args'] = resolve_build_args(build)
|
build['args'] = build_string_dict(resolve_build_args(build))
|
||||||
|
|
||||||
service_dict['build'] = build
|
service_dict['build'] = build
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
"driver_opts": {
|
"driver_opts": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"patternProperties": {
|
"patternProperties": {
|
||||||
"^.+$": {"type": "string"}
|
"^.+$": {"type": ["string", "number"]}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"external": {
|
"external": {
|
||||||
|
@ -23,7 +23,20 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"context": {"type": "string"},
|
"context": {"type": "string"},
|
||||||
"dockerfile": {"type": "string"},
|
"dockerfile": {"type": "string"},
|
||||||
"args": {"$ref": "#/definitions/list_or_dict"}
|
"args": {
|
||||||
|
"oneOf": [
|
||||||
|
{"$ref": "#/definitions/list_of_strings"},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"patternProperties": {
|
||||||
|
"^.+$": {
|
||||||
|
"type": ["string", "number"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
@ -92,3 +92,7 @@ def json_hash(obj):
|
|||||||
|
|
||||||
def microseconds_from_time_nano(time_nano):
|
def microseconds_from_time_nano(time_nano):
|
||||||
return int(time_nano % 1000000000 / 1000)
|
return int(time_nano % 1000000000 / 1000)
|
||||||
|
|
||||||
|
|
||||||
|
def build_string_dict(source_dict):
|
||||||
|
return dict([(k, str(v)) for k, v in source_dict.items()])
|
||||||
|
@ -231,7 +231,7 @@ class ConfigTest(unittest.TestCase):
|
|||||||
assert volumes['simple'] == {}
|
assert volumes['simple'] == {}
|
||||||
assert volumes['other'] == {}
|
assert volumes['other'] == {}
|
||||||
|
|
||||||
def test_volume_invalid_driver_opt(self):
|
def test_volume_numeric_driver_opt(self):
|
||||||
config_details = build_config_details({
|
config_details = build_config_details({
|
||||||
'version': '2',
|
'version': '2',
|
||||||
'services': {
|
'services': {
|
||||||
@ -241,6 +241,19 @@ class ConfigTest(unittest.TestCase):
|
|||||||
'simple': {'driver_opts': {'size': 42}},
|
'simple': {'driver_opts': {'size': 42}},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
cfg = config.load(config_details)
|
||||||
|
assert cfg.volumes['simple']['driver_opts']['size'] == '42'
|
||||||
|
|
||||||
|
def test_volume_invalid_driver_opt(self):
|
||||||
|
config_details = build_config_details({
|
||||||
|
'version': '2',
|
||||||
|
'services': {
|
||||||
|
'simple': {'image': 'busybox'}
|
||||||
|
},
|
||||||
|
'volumes': {
|
||||||
|
'simple': {'driver_opts': {'size': True}},
|
||||||
|
}
|
||||||
|
})
|
||||||
with pytest.raises(ConfigurationError) as exc:
|
with pytest.raises(ConfigurationError) as exc:
|
||||||
config.load(config_details)
|
config.load(config_details)
|
||||||
assert 'driver_opts.size contains an invalid type' in exc.exconly()
|
assert 'driver_opts.size contains an invalid type' in exc.exconly()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user