aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ansible/action_plugins/merge_configs.py7
-rw-r--r--ansible/action_plugins/merge_yaml.py7
-rw-r--r--tests/test_merge_config.py41
-rw-r--r--tests/test_merge_yaml.py32
4 files changed, 83 insertions, 4 deletions
diff --git a/ansible/action_plugins/merge_configs.py b/ansible/action_plugins/merge_configs.py
index 67a7da1cd..09dc1d04e 100644
--- a/ansible/action_plugins/merge_configs.py
+++ b/ansible/action_plugins/merge_configs.py
@@ -169,9 +169,12 @@ class ActionModule(action.ActionBase):
os.path.join(self._loader._basedir, 'templates'),
os.path.dirname(source),
]
- self._templar.environment.loader.searchpath = searchpath
+ templar = self._templar.copy_with_new_env(searchpath=searchpath)
- result = self._templar.template(template_data)
+ # lstrip_blocks avoids Jinja2 block tags (e.g. {% if %}) leaving
+ # behind leading whitespace that glues adjacent lines together.
+ result = templar.template(
+ template_data, overrides=dict(lstrip_blocks=True))
fakefile = StringIO(result)
config.parse(fakefile)
fakefile.close()
diff --git a/ansible/action_plugins/merge_yaml.py b/ansible/action_plugins/merge_yaml.py
index d2c15eb70..f3ba8597b 100644
--- a/ansible/action_plugins/merge_yaml.py
+++ b/ansible/action_plugins/merge_yaml.py
@@ -109,9 +109,12 @@ class ActionModule(action.ActionBase):
os.path.join(self._loader._basedir, 'templates'),
os.path.dirname(source),
]
- self._templar.environment.loader.searchpath = searchpath
+ templar = self._templar.copy_with_new_env(searchpath=searchpath)
- template_data = self._templar.template(template_data)
+ # lstrip_blocks avoids Jinja2 block tags (e.g. {% if %}) leaving
+ # behind leading whitespace that glues adjacent lines together.
+ template_data = templar.template(
+ template_data, overrides=dict(lstrip_blocks=True))
result = yaml.safe_load(template_data)
return result or {}
diff --git a/tests/test_merge_config.py b/tests/test_merge_config.py
index d64b2ae6b..de2c98281 100644
--- a/tests/test_merge_config.py
+++ b/tests/test_merge_config.py
@@ -15,8 +15,12 @@
from importlib.machinery import SourceFileLoader
import os
+import tempfile
from io import StringIO
+
+from ansible.parsing.dataloader import DataLoader
+from ansible.template import Templar
from oslotest import base
@@ -211,3 +215,40 @@ class OverrideConfigParserTest(base.BaseTestCase):
parser.write(output)
self.assertEqual(TESTC_NO_WHITESPACE, output.getvalue())
output.close()
+
+ def test_read_config_lstrip_blocks(self):
+ # An indented Jinja2 block tag on its own line must not leak its
+ # leading whitespace into the following line, or the line gets
+ # parsed as a continuation of the previous key's value instead of
+ # a new key.
+ content = (
+ "[DEFAULT]\n"
+ "key1 = value1\n"
+ " {% if true %}\n"
+ "key2 = value2\n"
+ " {% endif %}\n"
+ "key3 = value3\n"
+ )
+ with tempfile.TemporaryDirectory() as tmpdir:
+ source = os.path.join(tmpdir, 'source.conf')
+ with open(source, 'w') as f:
+ f.write(content)
+
+ loader = DataLoader()
+ loader.set_basedir(tmpdir)
+ action = object.__new__(merge_configs.ActionModule)
+ action._loader = loader
+ action._templar = Templar(loader=loader)
+
+ config = merge_configs.OverrideConfigParser()
+ action.read_config(source, config)
+
+ output = StringIO()
+ config.write(output)
+ self.assertEqual(
+ "[DEFAULT]\n"
+ "key1 = value1\n"
+ "key2 = value2\n"
+ "key3 = value3\n\n",
+ output.getvalue())
+ output.close()
diff --git a/tests/test_merge_yaml.py b/tests/test_merge_yaml.py
index d6b74ae77..35de91d2c 100644
--- a/tests/test_merge_yaml.py
+++ b/tests/test_merge_yaml.py
@@ -15,8 +15,11 @@
from importlib.machinery import SourceFileLoader
import os
+import tempfile
from ansible.errors import AnsibleModuleError
+from ansible.parsing.dataloader import DataLoader
+from ansible.template import Templar
from oslotest import base
PROJECT_DIR = os.path.abspath(os.path.join(os. path.dirname(__file__), '../'))
@@ -174,3 +177,32 @@ class MergeYamlConfigTest(base.BaseTestCase):
with self.assertRaisesRegex(AnsibleModuleError, "Failure merging key"):
merge_yaml.Utils.update_nested_conf(
initial_conf, extension, extend_lists=True)
+
+ def test_read_config_lstrip_blocks(self):
+ # An indented Jinja2 block tag on its own line must not leak its
+ # leading whitespace into the following line, or the resulting
+ # YAML indentation becomes inconsistent with its siblings.
+ content = (
+ "foo:\n"
+ " bar: baz\n"
+ " {% if true %}\n"
+ " extra: value\n"
+ " {% endif %}\n"
+ " qux: quux\n"
+ )
+ with tempfile.TemporaryDirectory() as tmpdir:
+ source = os.path.join(tmpdir, 'source.yml')
+ with open(source, 'w') as f:
+ f.write(content)
+
+ loader = DataLoader()
+ loader.set_basedir(tmpdir)
+ action = object.__new__(merge_yaml.ActionModule)
+ action._loader = loader
+ action._templar = Templar(loader=loader)
+
+ result = action.read_config(source)
+
+ self.assertEqual(
+ {'foo': {'bar': 'baz', 'extra': 'value', 'qux': 'quux'}},
+ result)