Support parsing ini files with no sections

Services such as Zookeeper and Kafka use ini files which do not
explicitly specify sections. This change supports merging ini
files with no sections, so that the configuration for these
services follows the example configuration provided for them
as closely as possible.

Closes-Bug: #1756101
Partially-Implements: blueprint monasca-roles
Change-Id: I1061729875e5545c7af7d80779f9c2124b6c7134
This commit is contained in:
Doug Szumski 2018-03-15 16:58:54 +00:00
parent a909943bf3
commit d32c708290
2 changed files with 83 additions and 2 deletions

View File

@ -25,6 +25,8 @@ from six import StringIO
from oslo_config import iniparser
_ORPHAN_SECTION = 'TEMPORARY_ORPHAN_VARIABLE_SECTION'
class OverrideConfigParser(iniparser.BaseParser):
@ -34,6 +36,8 @@ class OverrideConfigParser(iniparser.BaseParser):
self._cur_section = None
def assignment(self, key, value):
if self._cur_section is None:
self.new_section(_ORPHAN_SECTION)
cur_value = self._cur_section.get(key)
if len(value) == 1 and value[0] == '':
value = []
@ -44,6 +48,7 @@ class OverrideConfigParser(iniparser.BaseParser):
def parse(self, lineiter):
self._cur_sections = collections.OrderedDict()
self._cur_section = None
super(OverrideConfigParser, self).parse(lineiter)
# merge _cur_sections into _sections
@ -77,7 +82,8 @@ class OverrideConfigParser(iniparser.BaseParser):
write_key_value(key, values)
for section in self._sections:
fp.write('[{}]\n'.format(section))
if section != _ORPHAN_SECTION:
fp.write('[{}]\n'.format(section))
write_section(self._sections[section])
fp.write('\n')

View File

@ -86,11 +86,68 @@ c_key2 = 1 2 3
'''
TESTA_NO_SECTIONS = '''key1 = a
key2 = b
'''
TESTB_NO_SECTIONS = '''key3 = c
'''
# TESTA_NO_SECTIONS and TESTB_NO_SECTIONS combined
TESTC_NO_SECTIONS = '''key1 = a
key2 = b
key3 = c
'''
TESTA_NO_DEFAULT_SECTION = '''key1 = a
key2 = b
[a]
key1 = not_a
[b]
key3 = not_c
'''
TESTB_NO_DEFAULT_SECTION = '''key3 = c
[b]
key2 = not_b
key3 = override
'''
# TESTA_NO_DEFAULT_SECTION and TESTB_NO_DEFAULT_SECTION combined
TESTC_NO_DEFAULT_SECTION = '''key1 = a
key2 = b
key3 = c
[a]
key1 = not_a
[b]
key3 = override
key2 = not_b
'''
class OverrideConfigParserTest(base.BaseTestCase):
def test_read_write(self):
for ini in [TESTA, TESTB, TESTC]:
for ini in [TESTA,
TESTB,
TESTC,
TESTA_NO_SECTIONS,
TESTB_NO_SECTIONS,
TESTC_NO_SECTIONS,
TESTA_NO_DEFAULT_SECTION,
TESTB_NO_DEFAULT_SECTION,
TESTC_NO_DEFAULT_SECTION]:
parser = merge_configs.OverrideConfigParser()
parser.parse(StringIO(ini))
output = StringIO()
@ -106,3 +163,21 @@ class OverrideConfigParserTest(base.BaseTestCase):
parser.write(output)
self.assertEqual(TESTC, output.getvalue())
output.close()
def test_merge_no_sections(self):
parser = merge_configs.OverrideConfigParser()
parser.parse(StringIO(TESTA_NO_SECTIONS))
parser.parse(StringIO(TESTB_NO_SECTIONS))
output = StringIO()
parser.write(output)
self.assertEqual(TESTC_NO_SECTIONS, output.getvalue())
output.close()
def test_merge_no_default_section(self):
parser = merge_configs.OverrideConfigParser()
parser.parse(StringIO(TESTA_NO_DEFAULT_SECTION))
parser.parse(StringIO(TESTB_NO_DEFAULT_SECTION))
output = StringIO()
parser.write(output)
self.assertEqual(TESTC_NO_DEFAULT_SECTION, output.getvalue())
output.close()