Preserve comments in INI files
config_template currently strips comments out from the INI files. This commit adds support for comments. The default ConfigParser supports reading comments but it doesn't writes them back. There are other libraries that have better support for comments, however, adopting another library would require a bigger refactor of this code. Change-Id: I376be69cd2cf34dc147f9ade716791125a424e2c
This commit is contained in:
parent
7145937250
commit
3f5a274374
@ -134,6 +134,7 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
||||
key = var2
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._comments = {}
|
||||
self.ignore_none_type = bool(kwargs.pop('ignore_none_type', True))
|
||||
ConfigParser.RawConfigParser.__init__(self, *args, **kwargs)
|
||||
|
||||
@ -163,21 +164,31 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
||||
self._write(fp, section, key, value, entry)
|
||||
|
||||
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:
|
||||
_write_comments('DEFAULT')
|
||||
fp.write("[%s]\n" % 'DEFAULT')
|
||||
for key, value in self._defaults.items():
|
||||
_write_comments('DEFAULT', optname=key)
|
||||
self._write_check(fp, key=key, value=value)
|
||||
else:
|
||||
fp.write("\n")
|
||||
|
||||
for section in self._sections:
|
||||
_write_comments(section)
|
||||
fp.write("[%s]\n" % section)
|
||||
for key, value in self._sections[section].items():
|
||||
_write_comments(section, optname=key)
|
||||
self._write_check(fp, key=key, value=value, section=True)
|
||||
else:
|
||||
fp.write("\n")
|
||||
|
||||
def _read(self, fp, fpname):
|
||||
comments = []
|
||||
cursect = None
|
||||
optname = None
|
||||
lineno = 0
|
||||
@ -187,8 +198,15 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
||||
if not line:
|
||||
break
|
||||
lineno += 1
|
||||
if line.strip() == '' or line[0] in '#;':
|
||||
if line.strip() == '':
|
||||
if comments:
|
||||
comments.append('')
|
||||
continue
|
||||
|
||||
if line[0] in '#;':
|
||||
comments.append(line)
|
||||
continue
|
||||
|
||||
if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
|
||||
continue
|
||||
if line[0].isspace() and cursect is not None and optname:
|
||||
@ -215,6 +233,13 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
||||
cursect = self._dict()
|
||||
self._sections[sectname] = cursect
|
||||
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:
|
||||
raise ConfigParser.MissingSectionHeaderError(
|
||||
fpname,
|
||||
@ -235,6 +260,9 @@ class ConfigTemplateParser(ConfigParser.RawConfigParser):
|
||||
if optval == '""':
|
||||
optval = ''
|
||||
cursect[optname] = optval
|
||||
if comments:
|
||||
comsect[optname] = comments
|
||||
comments = []
|
||||
else:
|
||||
if not e:
|
||||
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)^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:
|
||||
test_config_ini_overrides:
|
||||
DEFAULT:
|
||||
|
Loading…
x
Reference in New Issue
Block a user