From 7abae9f5368fed01e9d30cce915bbfd71df471c8 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Tue, 25 Jul 2017 16:42:31 -0700 Subject: [PATCH] Escape dollar sign in serialized config output Signed-off-by: Joffrey F --- compose/config/serialize.py | 5 ++++- tests/unit/config/config_test.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/compose/config/serialize.py b/compose/config/serialize.py index 84521848d..dca0affb2 100644 --- a/compose/config/serialize.py +++ b/compose/config/serialize.py @@ -21,8 +21,11 @@ def serialize_dict_type(dumper, data): def serialize_string(dumper, data): - """ Ensure boolean-like strings are quoted in the output """ + """ Ensure boolean-like strings are quoted in the output and escape $ characters """ representer = dumper.represent_str if six.PY3 else dumper.represent_unicode + + data = data.replace('$', '$$') + if data.lower() in ('y', 'n', 'yes', 'no', 'on', 'off', 'true', 'false'): # Empirically only y/n appears to be an issue, but this might change # depending on which PyYaml version is being used. Err on safe side. diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index 9d42f2b59..63cb7eaef 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -4185,3 +4185,25 @@ class SerializeTest(unittest.TestCase): assert 'command: "true"\n' in serialized_config assert 'FOO: "Y"\n' in serialized_config assert 'BAR: "on"\n' in serialized_config + + def test_serialize_escape_dollar_sign(self): + cfg = { + 'version': '2.2', + 'services': { + 'web': { + 'image': 'busybox', + 'command': 'echo $$FOO', + 'environment': { + 'CURRENCY': '$$' + }, + 'entrypoint': ['$$SHELL', '-c'], + } + } + } + config_dict = config.load(build_config_details(cfg)) + + serialized_config = yaml.load(serialize_config(config_dict)) + serialized_service = serialized_config['services']['web'] + assert serialized_service['environment']['CURRENCY'] == '$$' + assert serialized_service['command'] == 'echo $$FOO' + assert serialized_service['entrypoint'][0] == '$$SHELL'