Merge pull request #5530 from docker/5527-convert-errors

Gracefully handle errors and provide helpful error message in type conversion
This commit is contained in:
Joffrey F 2018-01-03 16:02:11 -08:00 committed by GitHub
commit bcc13d7fae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 4 deletions

View File

@ -138,14 +138,24 @@ def to_int(s):
# We must be able to handle octal representation for `mode` values notably
if six.PY3 and re.match('^0[0-9]+$', s.strip()):
s = '0o' + s[1:]
return int(s, base=0)
try:
return int(s, base=0)
except ValueError:
raise ValueError('"{}" is not a valid integer'.format(s))
def to_float(s):
try:
return float(s)
except ValueError:
raise ValueError('"{}" is not a valid float'.format(s))
class ConversionMap(object):
map = {
service_path('blkio_config', 'weight'): to_int,
service_path('blkio_config', 'weight_device', 'weight'): to_int,
service_path('cpus'): float,
service_path('cpus'): to_float,
service_path('cpu_count'): to_int,
service_path('configs', 'mode'): to_int,
service_path('secrets', 'mode'): to_int,
@ -153,7 +163,7 @@ class ConversionMap(object):
service_path('healthcheck', 'disable'): to_boolean,
service_path('deploy', 'replicas'): to_int,
service_path('deploy', 'update_config', 'parallelism'): to_int,
service_path('deploy', 'update_config', 'max_failure_ratio'): float,
service_path('deploy', 'update_config', 'max_failure_ratio'): to_float,
service_path('deploy', 'restart_policy', 'max_attempts'): to_int,
service_path('mem_swappiness'): to_int,
service_path('oom_kill_disable'): to_boolean,
@ -181,7 +191,14 @@ class ConversionMap(object):
def convert(self, path, value):
for rexp in self.map.keys():
if rexp.match(path):
return self.map[rexp](value)
try:
return self.map[rexp](value)
except ValueError as e:
raise ConfigurationError(
'Error while attempting to convert {} to appropriate type: {}'.format(
path, e
)
)
return value

View File

@ -4,6 +4,7 @@ from __future__ import unicode_literals
import pytest
from compose.config.environment import Environment
from compose.config.errors import ConfigurationError
from compose.config.interpolation import interpolate_environment_variables
from compose.config.interpolation import Interpolator
from compose.config.interpolation import InvalidInterpolation
@ -254,6 +255,30 @@ def test_interpolate_environment_services_convert_types_v3(mock_env):
assert value == expected
def test_interpolate_environment_services_convert_types_invalid(mock_env):
entry = {'service1': {'privileged': '${POSINT}'}}
with pytest.raises(ConfigurationError) as exc:
interpolate_environment_variables(V2_3, entry, 'service', mock_env)
assert 'Error while attempting to convert service.service1.privileged to '\
'appropriate type: "50" is not a valid boolean value' in exc.exconly()
entry = {'service1': {'cpus': '${TRUE}'}}
with pytest.raises(ConfigurationError) as exc:
interpolate_environment_variables(V2_3, entry, 'service', mock_env)
assert 'Error while attempting to convert service.service1.cpus to '\
'appropriate type: "True" is not a valid float' in exc.exconly()
entry = {'service1': {'ulimits': {'nproc': '${FLOAT}'}}}
with pytest.raises(ConfigurationError) as exc:
interpolate_environment_variables(V2_3, entry, 'service', mock_env)
assert 'Error while attempting to convert service.service1.ulimits.nproc to '\
'appropriate type: "0.145" is not a valid integer' in exc.exconly()
def test_interpolate_environment_network_convert_types(mock_env):
entry = {
'network1': {