From 86d9a533e80c06a3b53067f60b72f9c998713b4a Mon Sep 17 00:00:00 2001
From: Will Szumski <will@stackhpc.com>
Date: Fri, 3 Nov 2023 17:42:49 +0000
Subject: [PATCH] Fallback to templating when only one source exists

This is a backwards compatability improvement, since it was previously
permitted to have a config file that templated to invalid yaml/ini.

Change-Id: I53a0894cc64e83c7342a82ad987b7e5a4696ece2
Closes-Bug: #2042690
---
 .../action_plugins/kolla_custom_config_info.py | 18 ++++++++++++++++--
 ...nly-one-source-exists-5eb19c0f6b8820d5.yaml |  7 +++++++
 2 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 releasenotes/notes/fallback-to-templating-when-only-one-source-exists-5eb19c0f6b8820d5.yaml

diff --git a/ansible/roles/kolla-openstack/action_plugins/kolla_custom_config_info.py b/ansible/roles/kolla-openstack/action_plugins/kolla_custom_config_info.py
index f5ad1542..b58b679e 100644
--- a/ansible/roles/kolla-openstack/action_plugins/kolla_custom_config_info.py
+++ b/ansible/roles/kolla-openstack/action_plugins/kolla_custom_config_info.py
@@ -77,13 +77,27 @@ class ConfigCollector(object):
         result = set(self.files_in_destination) - ignored
         return list(result)
 
-    def _find_matching_rule(self, relative_path):
+    def _find_matching_rule(self, relative_path, sources):
         # First match wins
         for rule in self.rules:
             if not rule.get('enabled', True):
                 continue
             glob_ = rule["glob"]
             if glob.globmatch(relative_path, glob_, flags=glob.GLOBSTAR):
+                requires_merge = (rule["strategy"] in
+                    ["merge_configs", "merge_yaml"])
+                # Fallback to templating when there is only one source. This
+                # allows you to have config files that template to invalid
+                # yaml/ini. This was allowed prior to config merging so
+                # improves backwards compatibility.
+                if requires_merge and len(sources) == 1:
+                    # The rule can be used again to match a different file
+                    # so don't modify in place.
+                    rule = rule.copy()
+                    rule["strategy"] = 'template'
+                    # Strip parameters as they may not be compatible with
+                    # template module.
+                    rule['params'] = {}
                 return rule
 
     def partition_into_actions(self):
@@ -114,7 +128,7 @@ class ConfigCollector(object):
             if not os.path.exists(dirname):
                 missing_directories.add(dirname)
 
-            rule = self._find_matching_rule(relative_path)
+            rule = self._find_matching_rule(relative_path, sources)
 
             if not rule:
                 continue
diff --git a/releasenotes/notes/fallback-to-templating-when-only-one-source-exists-5eb19c0f6b8820d5.yaml b/releasenotes/notes/fallback-to-templating-when-only-one-source-exists-5eb19c0f6b8820d5.yaml
new file mode 100644
index 00000000..6edcb55c
--- /dev/null
+++ b/releasenotes/notes/fallback-to-templating-when-only-one-source-exists-5eb19c0f6b8820d5.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+  - |
+    When merging kolla config, fallback to templating when only one source file
+    exists. This allows you to use config that templates to invalid yaml/ini as
+    long as there isn't an environment override. This improves backwards
+    compatability where it was permitted to use such constructs.
-- 
GitLab