mirror of https://github.com/docker/compose.git
Properly escape values coming from env_files, fixes #6871
Signed-off-by: Florian Apolloner <florian@apolloner.eu>
This commit is contained in:
parent
73551d5a92
commit
f17e7268b0
|
@ -408,7 +408,7 @@ def load(config_details, compatibility=False, interpolate=True):
|
||||||
configs = load_mapping(
|
configs = load_mapping(
|
||||||
config_details.config_files, 'get_configs', 'Config', config_details.working_dir
|
config_details.config_files, 'get_configs', 'Config', config_details.working_dir
|
||||||
)
|
)
|
||||||
service_dicts = load_services(config_details, main_file, compatibility)
|
service_dicts = load_services(config_details, main_file, compatibility, interpolate=interpolate)
|
||||||
|
|
||||||
if main_file.version != V1:
|
if main_file.version != V1:
|
||||||
for service_dict in service_dicts:
|
for service_dict in service_dicts:
|
||||||
|
@ -460,7 +460,7 @@ def validate_external(entity_type, name, config, version):
|
||||||
entity_type, name, ', '.join(k for k in config if k != 'external')))
|
entity_type, name, ', '.join(k for k in config if k != 'external')))
|
||||||
|
|
||||||
|
|
||||||
def load_services(config_details, config_file, compatibility=False):
|
def load_services(config_details, config_file, compatibility=False, interpolate=True):
|
||||||
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(
|
||||||
config_details.working_dir,
|
config_details.working_dir,
|
||||||
|
@ -479,7 +479,8 @@ def load_services(config_details, config_file, compatibility=False):
|
||||||
service_names,
|
service_names,
|
||||||
config_file.version,
|
config_file.version,
|
||||||
config_details.environment,
|
config_details.environment,
|
||||||
compatibility
|
compatibility,
|
||||||
|
interpolate
|
||||||
)
|
)
|
||||||
return service_dict
|
return service_dict
|
||||||
|
|
||||||
|
@ -679,13 +680,13 @@ class ServiceExtendsResolver(object):
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
def resolve_environment(service_dict, environment=None):
|
def resolve_environment(service_dict, environment=None, interpolate=True):
|
||||||
"""Unpack any environment variables from an env_file, if set.
|
"""Unpack any environment variables from an env_file, if set.
|
||||||
Interpolate environment values if set.
|
Interpolate environment values if set.
|
||||||
"""
|
"""
|
||||||
env = {}
|
env = {}
|
||||||
for env_file in service_dict.get('env_file', []):
|
for env_file in service_dict.get('env_file', []):
|
||||||
env.update(env_vars_from_file(env_file))
|
env.update(env_vars_from_file(env_file, interpolate))
|
||||||
|
|
||||||
env.update(parse_environment(service_dict.get('environment')))
|
env.update(parse_environment(service_dict.get('environment')))
|
||||||
return dict(resolve_env_var(k, v, environment) for k, v in six.iteritems(env))
|
return dict(resolve_env_var(k, v, environment) for k, v in six.iteritems(env))
|
||||||
|
@ -881,11 +882,12 @@ def finalize_service_volumes(service_dict, environment):
|
||||||
return service_dict
|
return service_dict
|
||||||
|
|
||||||
|
|
||||||
def finalize_service(service_config, service_names, version, environment, compatibility):
|
def finalize_service(service_config, service_names, version, environment, compatibility,
|
||||||
|
interpolate=True):
|
||||||
service_dict = dict(service_config.config)
|
service_dict = dict(service_config.config)
|
||||||
|
|
||||||
if 'environment' in service_dict or 'env_file' in service_dict:
|
if 'environment' in service_dict or 'env_file' in service_dict:
|
||||||
service_dict['environment'] = resolve_environment(service_dict, environment)
|
service_dict['environment'] = resolve_environment(service_dict, environment, interpolate)
|
||||||
service_dict.pop('env_file', None)
|
service_dict.pop('env_file', None)
|
||||||
|
|
||||||
if 'volumes_from' in service_dict:
|
if 'volumes_from' in service_dict:
|
||||||
|
|
|
@ -30,7 +30,7 @@ def split_env(env):
|
||||||
return key, value
|
return key, value
|
||||||
|
|
||||||
|
|
||||||
def env_vars_from_file(filename):
|
def env_vars_from_file(filename, interpolate=True):
|
||||||
"""
|
"""
|
||||||
Read in a line delimited file of environment variables.
|
Read in a line delimited file of environment variables.
|
||||||
"""
|
"""
|
||||||
|
@ -39,6 +39,7 @@ def env_vars_from_file(filename):
|
||||||
elif not os.path.isfile(filename):
|
elif not os.path.isfile(filename):
|
||||||
raise EnvFileNotFound("{} is not a file.".format(filename))
|
raise EnvFileNotFound("{} is not a file.".format(filename))
|
||||||
|
|
||||||
|
# TODO: now we should do something with interpolate here, but what?
|
||||||
return dotenv.dotenv_values(dotenv_path=filename, encoding='utf-8-sig')
|
return dotenv.dotenv_values(dotenv_path=filename, encoding='utf-8-sig')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
FOO=NO $ENV VAR
|
||||||
|
DOO=NO ${ENV} VAR
|
|
@ -5420,15 +5420,19 @@ class SerializeTest(unittest.TestCase):
|
||||||
'environment': {
|
'environment': {
|
||||||
'CURRENCY': '$'
|
'CURRENCY': '$'
|
||||||
},
|
},
|
||||||
|
'env_file': ['tests/fixtures/env/three.env'],
|
||||||
'entrypoint': ['$SHELL', '-c'],
|
'entrypoint': ['$SHELL', '-c'],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
config_dict = config.load(build_config_details(cfg), interpolate=False)
|
config_dict = config.load(build_config_details(cfg, working_dir='.'), interpolate=False)
|
||||||
|
|
||||||
serialized_config = yaml.safe_load(serialize_config(config_dict, escape_dollar=False))
|
serialized_config = yaml.safe_load(serialize_config(config_dict, escape_dollar=False))
|
||||||
serialized_service = serialized_config['services']['web']
|
serialized_service = serialized_config['services']['web']
|
||||||
assert serialized_service['environment']['CURRENCY'] == '$'
|
assert serialized_service['environment']['CURRENCY'] == '$'
|
||||||
|
# Values coming from env_files are not allowed to have variables
|
||||||
|
assert serialized_service['environment']['FOO'] == 'NO $$ENV VAR'
|
||||||
|
assert serialized_service['environment']['DOO'] == 'NO $${ENV} VAR'
|
||||||
assert serialized_service['command'] == 'echo $FOO'
|
assert serialized_service['command'] == 'echo $FOO'
|
||||||
assert serialized_service['entrypoint'][0] == '$SHELL'
|
assert serialized_service['entrypoint'][0] == '$SHELL'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue