diff options
-rw-r--r-- | cloudinit/distros/parsers/sys_conf.py | 17 | ||||
-rw-r--r-- | tests/unittests/test_distros/test_sysconfig.py | 5 |
2 files changed, 18 insertions, 4 deletions
diff --git a/cloudinit/distros/parsers/sys_conf.py b/cloudinit/distros/parsers/sys_conf.py index 7549c7a3..80c305fe 100644 --- a/cloudinit/distros/parsers/sys_conf.py +++ b/cloudinit/distros/parsers/sys_conf.py @@ -31,6 +31,12 @@ import re import configobj +def _contains_shell_variable(text): + if (re.search(r"\$\{.+\}", text) or + re.search(r"\$[a-zA-Z_]+[a-zA-Z0-9_]*", text)): + return True + return False + class SysConf(configobj.ConfigObj): def __init__(self, contents): @@ -62,7 +68,16 @@ class SysConf(configobj.ConfigObj): if value.strip().startswith("$(") and value.strip().endswith(")"): white_space_ok = True if re.search(r"[\t\r\n ]", value) and not white_space_ok: - quot_func = pipes.quote + if _contains_shell_variable(value): + # If it contains shell variables then we likely want to + # leave it alone since the pipes.quote function likes to + # use single quotes which won't get expanded... + if re.search(r"[\n\"']", value): + quot_func = (lambda x: self._get_triple_quote(x) % x) + else: + quot_func = (lambda x: self._get_single_quote(x) % x) + else: + quot_func = pipes.quote return quot_func(value) def _write_line(self, indent_string, entry, this_entry, comment): diff --git a/tests/unittests/test_distros/test_sysconfig.py b/tests/unittests/test_distros/test_sysconfig.py index a07a251e..21e161ad 100644 --- a/tests/unittests/test_distros/test_sysconfig.py +++ b/tests/unittests/test_distros/test_sysconfig.py @@ -24,7 +24,7 @@ NETMASK0=255.255.255.0 # Inline comment LIST=$LOGROOT/incremental-list IPV6TO4_ROUTING='eth0-:0004::1/64 eth1-:0005::1/64' -ETHTOOL_OPTS='-K ${DEVICE} tso on; -G ${DEVICE} rx 256 tx 256' +ETHTOOL_OPTS="-K ${DEVICE} tso on; -G ${DEVICE} rx 256 tx 256" USEMD5=no''' conf = SysConf(contents.splitlines()) self.assertEquals(conf['HOSTNAME'], 'blahblah') @@ -32,7 +32,6 @@ USEMD5=no''' # Should be unquoted self.assertEquals(conf['ETHTOOL_OPTS'], ('-K ${DEVICE} tso on; ' '-G ${DEVICE} rx 256 tx 256')) - # This is harmless convertion self.assertEquals(contents, str(conf)) def test_parse_adjust(self): @@ -44,7 +43,7 @@ USEMD5=no''' conf['IPV6TO4_ROUTING'] = "blah \tblah" contents2 = str(conf).strip() # Should be requoted due to whitespace - self.assertRegexpMatches(contents2, r'IPV6TO4_ROUTING=["\']blah \tblah["\']') + self.assertRegexpMatches(contents2, r'IPV6TO4_ROUTING=[\']blah\s+blah[\']') def test_parse_no_adjust_shell(self): conf = SysConf(''.splitlines()) |