| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 | from __future__ import absolute_importfrom __future__ import unicode_literalsimport pytestfrom compose.config.environment import Environmentfrom compose.config.interpolation import interpolate_environment_variablesfrom compose.config.interpolation import Interpolatorfrom compose.config.interpolation import InvalidInterpolationfrom compose.config.interpolation import TemplateWithDefaultsfrom compose.const import COMPOSEFILE_V2_0 as V2_0from compose.const import COMPOSEFILE_V2_3 as V2_3from compose.const import COMPOSEFILE_V3_4 as V3_4@pytest.fixturedef mock_env():    return Environment({        'USER': 'jenny',        'FOO': 'bar',        'TRUE': 'True',        'FALSE': 'OFF',        'POSINT': '50',        'NEGINT': '-200',        'FLOAT': '0.145',        'MODE': '0600',    })@pytest.fixturedef variable_mapping():    return Environment({'FOO': 'first', 'BAR': ''})@pytest.fixturedef defaults_interpolator(variable_mapping):    return Interpolator(TemplateWithDefaults, variable_mapping).interpolatedef test_interpolate_environment_variables_in_services(mock_env):    services = {        'servicea': {            'image': 'example:${USER}',            'volumes': ['$FOO:/target'],            'logging': {                'driver': '${FOO}',                'options': {                    'user': '$USER',                }            }        }    }    expected = {        'servicea': {            'image': 'example:jenny',            'volumes': ['bar:/target'],            'logging': {                'driver': 'bar',                'options': {                    'user': 'jenny',                }            }        }    }    value = interpolate_environment_variables(V2_0, services, 'service', mock_env)    assert value == expecteddef test_interpolate_environment_variables_in_volumes(mock_env):    volumes = {        'data': {            'driver': '$FOO',            'driver_opts': {                'max': 2,                'user': '${USER}'            }        },        'other': None,    }    expected = {        'data': {            'driver': 'bar',            'driver_opts': {                'max': 2,                'user': 'jenny'            }        },        'other': {},    }    value = interpolate_environment_variables(V2_0, volumes, 'volume', mock_env)    assert value == expecteddef test_interpolate_environment_variables_in_secrets(mock_env):    secrets = {        'secretservice': {            'file': '$FOO',            'labels': {                'max': 2,                'user': '${USER}'            }        },        'other': None,    }    expected = {        'secretservice': {            'file': 'bar',            'labels': {                'max': 2,                'user': 'jenny'            }        },        'other': {},    }    value = interpolate_environment_variables(V3_4, secrets, 'secret', mock_env)    assert value == expecteddef test_interpolate_environment_services_convert_types_v2(mock_env):    entry = {        'service1': {            'blkio_config': {                'weight': '${POSINT}',                'weight_device': [{'file': '/dev/sda1', 'weight': '${POSINT}'}]            },            'cpus': '${FLOAT}',            'cpu_count': '$POSINT',            'healthcheck': {                'retries': '${POSINT:-3}',                'disable': '${FALSE}',                'command': 'true'            },            'mem_swappiness': '${DEFAULT:-127}',            'oom_score_adj': '${NEGINT}',            'scale': '${POSINT}',            'ulimits': {                'nproc': '${POSINT}',                'nofile': {                    'soft': '${POSINT}',                    'hard': '${DEFAULT:-40000}'                },            },            'privileged': '${TRUE}',            'read_only': '${DEFAULT:-no}',            'tty': '${DEFAULT:-N}',            'stdin_open': '${DEFAULT-on}',        }    }    expected = {        'service1': {            'blkio_config': {                'weight': 50,                'weight_device': [{'file': '/dev/sda1', 'weight': 50}]            },            'cpus': 0.145,            'cpu_count': 50,            'healthcheck': {                'retries': 50,                'disable': False,                'command': 'true'            },            'mem_swappiness': 127,            'oom_score_adj': -200,            'scale': 50,            'ulimits': {                'nproc': 50,                'nofile': {                    'soft': 50,                    'hard': 40000                },            },            'privileged': True,            'read_only': False,            'tty': False,            'stdin_open': True,        }    }    value = interpolate_environment_variables(V2_3, entry, 'service', mock_env)    assert value == expecteddef test_interpolate_environment_services_convert_types_v3(mock_env):    entry = {        'service1': {            'healthcheck': {                'retries': '${POSINT:-3}',                'disable': '${FALSE}',                'command': 'true'            },            'ulimits': {                'nproc': '${POSINT}',                'nofile': {                    'soft': '${POSINT}',                    'hard': '${DEFAULT:-40000}'                },            },            'privileged': '${TRUE}',            'read_only': '${DEFAULT:-no}',            'tty': '${DEFAULT:-N}',            'stdin_open': '${DEFAULT-on}',            'deploy': {                'update_config': {                    'parallelism': '${DEFAULT:-2}',                    'max_failure_ratio': '${FLOAT}',                },                'restart_policy': {                    'max_attempts': '$POSINT',                },                'replicas': '${DEFAULT-3}'            },            'ports': [{'target': '${POSINT}', 'published': '${DEFAULT:-5000}'}],            'configs': [{'mode': '${MODE}', 'source': 'config1'}],            'secrets': [{'mode': '${MODE}', 'source': 'secret1'}],        }    }    expected = {        'service1': {            'healthcheck': {                'retries': 50,                'disable': False,                'command': 'true'            },            'ulimits': {                'nproc': 50,                'nofile': {                    'soft': 50,                    'hard': 40000                },            },            'privileged': True,            'read_only': False,            'tty': False,            'stdin_open': True,            'deploy': {                'update_config': {                    'parallelism': 2,                    'max_failure_ratio': 0.145,                },                'restart_policy': {                    'max_attempts': 50,                },                'replicas': 3            },            'ports': [{'target': 50, 'published': 5000}],            'configs': [{'mode': 0o600, 'source': 'config1'}],            'secrets': [{'mode': 0o600, 'source': 'secret1'}],        }    }    value = interpolate_environment_variables(V3_4, entry, 'service', mock_env)    assert value == expecteddef test_interpolate_environment_network_convert_types(mock_env):    entry = {        'network1': {            'external': '${FALSE}',            'attachable': '${TRUE}',            'internal': '${DEFAULT:-false}'        }    }    expected = {        'network1': {            'external': False,            'attachable': True,            'internal': False,        }    }    value = interpolate_environment_variables(V3_4, entry, 'network', mock_env)    assert value == expecteddef test_interpolate_environment_external_resource_convert_types(mock_env):    entry = {        'resource1': {            'external': '${TRUE}',        }    }    expected = {        'resource1': {            'external': True,        }    }    value = interpolate_environment_variables(V3_4, entry, 'network', mock_env)    assert value == expected    value = interpolate_environment_variables(V3_4, entry, 'volume', mock_env)    assert value == expected    value = interpolate_environment_variables(V3_4, entry, 'secret', mock_env)    assert value == expected    value = interpolate_environment_variables(V3_4, entry, 'config', mock_env)    assert value == expecteddef test_escaped_interpolation(defaults_interpolator):    assert defaults_interpolator('$${foo}') == '${foo}'def test_invalid_interpolation(defaults_interpolator):    with pytest.raises(InvalidInterpolation):        defaults_interpolator('${')    with pytest.raises(InvalidInterpolation):        defaults_interpolator('$}')    with pytest.raises(InvalidInterpolation):        defaults_interpolator('${}')    with pytest.raises(InvalidInterpolation):        defaults_interpolator('${ }')    with pytest.raises(InvalidInterpolation):        defaults_interpolator('${ foo}')    with pytest.raises(InvalidInterpolation):        defaults_interpolator('${foo }')    with pytest.raises(InvalidInterpolation):        defaults_interpolator('${foo!}')def test_interpolate_missing_no_default(defaults_interpolator):    assert defaults_interpolator("This ${missing} var") == "This  var"    assert defaults_interpolator("This ${BAR} var") == "This  var"def test_interpolate_with_value(defaults_interpolator):    assert defaults_interpolator("This $FOO var") == "This first var"    assert defaults_interpolator("This ${FOO} var") == "This first var"def test_interpolate_missing_with_default(defaults_interpolator):    assert defaults_interpolator("ok ${missing:-def}") == "ok def"    assert defaults_interpolator("ok ${missing-def}") == "ok def"    assert defaults_interpolator("ok ${BAR:-/non:-alphanumeric}") == "ok /non:-alphanumeric"def test_interpolate_with_empty_and_default_value(defaults_interpolator):    assert defaults_interpolator("ok ${BAR:-def}") == "ok def"    assert defaults_interpolator("ok ${BAR-def}") == "ok "
 |