Merge "Preserve comments in INI files"
This commit is contained in:
commit
0bc785dd50
@ -134,6 +134,7 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
|||||||
key = var2
|
key = var2
|
||||||
"""
|
"""
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
self._comments = {}
|
||||||
self.ignore_none_type = bool(kwargs.pop('ignore_none_type', True))
|
self.ignore_none_type = bool(kwargs.pop('ignore_none_type', True))
|
||||||
ConfigParser.RawConfigParser.__init__(self, *args, **kwargs)
|
ConfigParser.RawConfigParser.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
@ -163,21 +164,31 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
|||||||
self._write(fp, section, key, value, entry)
|
self._write(fp, section, key, value, entry)
|
||||||
|
|
||||||
def write(self, fp):
|
def write(self, fp):
|
||||||
|
def _write_comments(section, optname=None):
|
||||||
|
comsect = self._comments.get(section, {})
|
||||||
|
if optname in comsect:
|
||||||
|
fp.write(''.join(comsect[optname]))
|
||||||
|
|
||||||
if self._defaults:
|
if self._defaults:
|
||||||
|
_write_comments('DEFAULT')
|
||||||
fp.write("[%s]\n" % 'DEFAULT')
|
fp.write("[%s]\n" % 'DEFAULT')
|
||||||
for key, value in self._defaults.items():
|
for key, value in self._defaults.items():
|
||||||
|
_write_comments('DEFAULT', optname=key)
|
||||||
self._write_check(fp, key=key, value=value)
|
self._write_check(fp, key=key, value=value)
|
||||||
else:
|
else:
|
||||||
fp.write("\n")
|
fp.write("\n")
|
||||||
|
|
||||||
for section in self._sections:
|
for section in self._sections:
|
||||||
|
_write_comments(section)
|
||||||
fp.write("[%s]\n" % section)
|
fp.write("[%s]\n" % section)
|
||||||
for key, value in self._sections[section].items():
|
for key, value in self._sections[section].items():
|
||||||
|
_write_comments(section, optname=key)
|
||||||
self._write_check(fp, key=key, value=value, section=True)
|
self._write_check(fp, key=key, value=value, section=True)
|
||||||
else:
|
else:
|
||||||
fp.write("\n")
|
fp.write("\n")
|
||||||
|
|
||||||
def _read(self, fp, fpname):
|
def _read(self, fp, fpname):
|
||||||
|
comments = []
|
||||||
cursect = None
|
cursect = None
|
||||||
optname = None
|
optname = None
|
||||||
lineno = 0
|
lineno = 0
|
||||||
@ -187,8 +198,15 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
|||||||
if not line:
|
if not line:
|
||||||
break
|
break
|
||||||
lineno += 1
|
lineno += 1
|
||||||
if line.strip() == '' or line[0] in '#;':
|
if line.strip() == '':
|
||||||
|
if comments:
|
||||||
|
comments.append('')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if line[0] in '#;':
|
||||||
|
comments.append(line)
|
||||||
|
continue
|
||||||
|
|
||||||
if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
|
if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
|
||||||
continue
|
continue
|
||||||
if line[0].isspace() and cursect is not None and optname:
|
if line[0].isspace() and cursect is not None and optname:
|
||||||
@ -215,6 +233,13 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
|||||||
cursect = self._dict()
|
cursect = self._dict()
|
||||||
self._sections[sectname] = cursect
|
self._sections[sectname] = cursect
|
||||||
optname = None
|
optname = None
|
||||||
|
|
||||||
|
comsect = self._comments.setdefault(sectname, {})
|
||||||
|
if comments:
|
||||||
|
# NOTE(flaper87): Using none as the key for
|
||||||
|
# section level comments
|
||||||
|
comsect[None] = comments
|
||||||
|
comments = []
|
||||||
elif cursect is None:
|
elif cursect is None:
|
||||||
raise ConfigParser.MissingSectionHeaderError(
|
raise ConfigParser.MissingSectionHeaderError(
|
||||||
fpname,
|
fpname,
|
||||||
@ -235,6 +260,9 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
|||||||
if optval == '""':
|
if optval == '""':
|
||||||
optval = ''
|
optval = ''
|
||||||
cursect[optname] = optval
|
cursect[optname] = optval
|
||||||
|
if comments:
|
||||||
|
comsect[optname] = comments
|
||||||
|
comments = []
|
||||||
else:
|
else:
|
||||||
if not e:
|
if not e:
|
||||||
e = ConfigParser.ParsingError(fpname)
|
e = ConfigParser.ParsingError(fpname)
|
||||||
|
9
tests/templates/test_with_comments.ini
Normal file
9
tests/templates/test_with_comments.ini
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# A default section comment
|
||||||
|
# broken into multiple lines
|
||||||
|
[DEFAULT]
|
||||||
|
|
||||||
|
[foo]
|
||||||
|
#This is a comment
|
||||||
|
baz = baz
|
||||||
|
|
||||||
|
[bar]
|
@ -177,6 +177,32 @@
|
|||||||
- "{{ test_ignore_none_type.content | b64decode | search('(?m)^india$') }}"
|
- "{{ test_ignore_none_type.content | b64decode | search('(?m)^india$') }}"
|
||||||
- "{{ test_ignore_none_type.content | b64decode | search('(?m)^juliett kilo$') }}"
|
- "{{ test_ignore_none_type.content | b64decode | search('(?m)^juliett kilo$') }}"
|
||||||
|
|
||||||
|
# Test basic function of config_template
|
||||||
|
- name: Template test INI comments
|
||||||
|
config_template:
|
||||||
|
src: "{{ playbook_dir }}/templates/test_with_comments.ini"
|
||||||
|
dest: "/tmp/test_with_comments.ini"
|
||||||
|
config_overrides: "{{ test_config_ini_overrides }}"
|
||||||
|
config_type: "ini"
|
||||||
|
tags: test
|
||||||
|
|
||||||
|
- name: Read test.ini
|
||||||
|
slurp:
|
||||||
|
src: /tmp/test_with_comments.ini
|
||||||
|
register: ini_file
|
||||||
|
tags: test
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "ini - {{ ini_file.content | b64decode }}"
|
||||||
|
- name: Validate output
|
||||||
|
tags: test
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "(lookup('ini', 'new_key section=DEFAULT file=/tmp/test_with_comments.ini')) == 'new_value'"
|
||||||
|
- "(lookup('ini', 'baz section=foo file=/tmp/test_with_comments.ini')) == 'bar'"
|
||||||
|
- "{{ ini_file.content | b64decode | search('#This is a comment')}}"
|
||||||
|
- "{{ ini_file.content | b64decode | search('# A default section comment\n# broken into multiple lines\n\\[DEFAULT\\]')}}"
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
test_config_ini_overrides:
|
test_config_ini_overrides:
|
||||||
DEFAULT:
|
DEFAULT:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user