summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cloudinit/distros/parsers/sys_conf.py24
-rw-r--r--tests/unittests/test_distros/test_sysconfig.py14
2 files changed, 21 insertions, 17 deletions
diff --git a/cloudinit/distros/parsers/sys_conf.py b/cloudinit/distros/parsers/sys_conf.py
index 3d8802b8..7549c7a3 100644
--- a/cloudinit/distros/parsers/sys_conf.py
+++ b/cloudinit/distros/parsers/sys_conf.py
@@ -18,6 +18,7 @@
from StringIO import StringIO
+import pipes
import re
# This library is used to parse/write
@@ -30,6 +31,7 @@ import re
import configobj
+
class SysConf(configobj.ConfigObj):
def __init__(self, contents):
configobj.ConfigObj.__init__(self, contents,
@@ -50,24 +52,18 @@ class SysConf(configobj.ConfigObj):
raise ValueError('Value "%s" is not a string' % (value))
if len(value) == 0:
return ''
- if re.search(r"[\n\r]", value):
- raise ValueError('Value "%s" cannot be safely quoted.' % (value))
- quot = "%s"
- if '#' in value:
- quot = self._get_single_quote(value)
- elif value[0] in ['"', "'"] and value[-1] in ['"', "'"]:
- # Already quoted, leave it be
- pass
- elif "'" in value and '"' in value:
- quot = self._get_triple_quote(value)
+ quot_func = (lambda x: str(x))
+ if value[0] in ['"', "'"] and value[-1] in ['"', "'"]:
+ if len(value) == 1:
+ quot_func = self._get_single_quote
else:
- # Quote whitespace if it isn't the start+end of a shell command
+ # Quote whitespace if it isn't the start + end of a shell command
white_space_ok = False
if value.strip().startswith("$(") and value.strip().endswith(")"):
white_space_ok = True
- if re.search(r"[\t ]", value) and not white_space_ok:
- quot = self._get_single_quote(value)
- return quot % (value)
+ if re.search(r"[\t\r\n ]", value) and not white_space_ok:
+ quot_func = pipes.quote
+ return quot_func(value)
def _write_line(self, indent_string, entry, this_entry, comment):
# Ensure it is formatted fine for
diff --git a/tests/unittests/test_distros/test_sysconfig.py b/tests/unittests/test_distros/test_sysconfig.py
index 196d090d..a07a251e 100644
--- a/tests/unittests/test_distros/test_sysconfig.py
+++ b/tests/unittests/test_distros/test_sysconfig.py
@@ -1,5 +1,7 @@
from mocker import MockerTestCase
+import re
+
from cloudinit.distros.parsers.sys_conf import SysConf
@@ -7,6 +9,11 @@ from cloudinit.distros.parsers.sys_conf import SysConf
# http://content.hccfl.edu/pollock/AUnix1/SysconfigFilesDesc.txt
class TestSysConfHelper(MockerTestCase):
+ def assertRegexpMatches(self, text, regexp):
+ regexp = re.compile(regexp)
+ self.assertTrue(regexp.search(text),
+ msg="%s must match %s!" % (text, regexp.pattern))
+
def test_parse_no_change(self):
contents = '''# A comment
USESMBAUTH=no
@@ -16,8 +23,8 @@ HOSTNAME=blahblah
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"
+IPV6TO4_ROUTING='eth0-:0004::1/64 eth1-:0005::1/64'
+ETHTOOL_OPTS='-K ${DEVICE} tso on; -G ${DEVICE} rx 256 tx 256'
USEMD5=no'''
conf = SysConf(contents.splitlines())
self.assertEquals(conf['HOSTNAME'], 'blahblah')
@@ -25,6 +32,7 @@ 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):
@@ -36,7 +44,7 @@ USEMD5=no'''
conf['IPV6TO4_ROUTING'] = "blah \tblah"
contents2 = str(conf).strip()
# Should be requoted due to whitespace
- self.assertEquals('IPV6TO4_ROUTING="blah \tblah"', contents2)
+ self.assertRegexpMatches(contents2, r'IPV6TO4_ROUTING=["\']blah \tblah["\']')
def test_parse_no_adjust_shell(self):
conf = SysConf(''.splitlines())