From 46137127a238d8e4b86a648cfda972a90f22b729 Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Tue, 9 Apr 2024 14:57:26 -0400 Subject: [PATCH] ansible-config: ensure we get templated default (#82974) AKA all defaults rendered --- changelogs/fragments/config_init_fix.yml | 2 ++ lib/ansible/cli/config.py | 8 +++++--- lib/ansible/config/manager.py | 24 +++++++++++++----------- test/integration/targets/config/runme.sh | 3 +++ 4 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 changelogs/fragments/config_init_fix.yml diff --git a/changelogs/fragments/config_init_fix.yml b/changelogs/fragments/config_init_fix.yml new file mode 100644 index 00000000000..f3b402dbdd4 --- /dev/null +++ b/changelogs/fragments/config_init_fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - ansible-config will now properly template defaults before dumping them. diff --git a/lib/ansible/cli/config.py b/lib/ansible/cli/config.py index e7457c18f43..e7f240c80d4 100755 --- a/lib/ansible/cli/config.py +++ b/lib/ansible/cli/config.py @@ -269,7 +269,7 @@ class ConfigCLI(CLI): if not settings[setting].get('description'): continue - default = settings[setting].get('default', '') + default = self.config.template_default(settings[setting].get('default', ''), get_constants()) if subkey == 'env': stype = settings[setting].get('type', '') if stype == 'boolean': @@ -351,7 +351,7 @@ class ConfigCLI(CLI): if entry['key'] not in seen[entry['section']]: seen[entry['section']].append(entry['key']) - default = opt.get('default', '') + default = self.config.template_default(opt.get('default', ''), get_constants()) if opt.get('type', '') == 'list' and not isinstance(default, string_types): # python lists are not valid ini ones default = ', '.join(default) @@ -413,14 +413,16 @@ class ConfigCLI(CLI): if context.CLIARGS['format'] == 'display': if isinstance(config[setting], Setting): # proceed normally + value = config[setting].value if config[setting].origin == 'default': color = 'green' + value = self.config.template_default(value, get_constants()) elif config[setting].origin == 'REQUIRED': # should include '_terms', '_input', etc color = 'red' else: color = 'yellow' - msg = "%s(%s) = %s" % (setting, config[setting].origin, config[setting].value) + msg = "%s(%s) = %s" % (setting, config[setting].origin, value) else: color = 'green' msg = "%s(%s) = %s" % (setting, 'default', config[setting].get('default')) diff --git a/lib/ansible/config/manager.py b/lib/ansible/config/manager.py index aaa8e545c0f..b8dada4ba4a 100644 --- a/lib/ansible/config/manager.py +++ b/lib/ansible/config/manager.py @@ -302,6 +302,17 @@ class ConfigManager(object): # ensure we always have config def entry self._base_defs['CONFIG_FILE'] = {'default': None, 'type': 'path'} + def template_default(self, value, variables): + if isinstance(value, string_types) and (value.startswith('{{') and value.endswith('}}')) and variables is not None: + # template default values if possible + # NOTE: cannot use is_template due to circular dep + try: + t = NativeEnvironment().from_string(value) + value = t.render(variables) + except Exception: + pass # not templatable + return value + def _read_config_yaml_file(self, yml_file): # TODO: handle relative paths as relative to the directory containing the current playbook instead of CWD # Currently this is only used with absolute paths to the `ansible/config` directory @@ -555,18 +566,9 @@ class ConfigManager(object): to_native(_get_entry(plugin_type, plugin_name, config))) else: origin = 'default' - value = defs[config].get('default') - if isinstance(value, string_types) and (value.startswith('{{') and value.endswith('}}')) and variables is not None: - # template default values if possible - # NOTE: cannot use is_template due to circular dep - try: - t = NativeEnvironment().from_string(value) - value = t.render(variables) - except Exception: - pass # not templatable - - # ensure correct type, can raise exceptions on mismatched types + value = self.template_default(defs[config].get('default'), variables) try: + # ensure correct type, can raise exceptions on mismatched types value = ensure_type(value, defs[config].get('type'), origin=origin, origin_ftype=origin_ftype) except ValueError as e: if origin.startswith('env:') and value == '': diff --git a/test/integration/targets/config/runme.sh b/test/integration/targets/config/runme.sh index 3e67b5e0888..b7a5244233d 100755 --- a/test/integration/targets/config/runme.sh +++ b/test/integration/targets/config/runme.sh @@ -40,3 +40,6 @@ do ANSIBLE_LOOKUP_PLUGINS=./ ansible-config init types -t lookup -f "${format}" > "files/types.new.${format}" diff -u "files/types.${format}" "files/types.new.${format}" done + +# ensure we don't show default templates, but templated defaults +[ "$(ansible-config init |grep '={{' -c )" -eq 0 ]