From 62a353c085e10ed8d8713357421a06e00de551f4 Mon Sep 17 00:00:00 2001 From: Sloane Hertel <19572925+s-hertel@users.noreply.github.com> Date: Mon, 17 Apr 2023 10:22:03 -0400 Subject: fix using templated values for include/import role FA (#80320) (#80378) * fix using templated values for include/import role options 'public', 'allow_duplicates', and 'rolespec_validate' * pass templated values without changing the instance * Fix templating by setting always_post_validate to True and calling IncludeRole.post_validate() instead ci_complete * add changelog (cherry picked from commit 666188892ed0833e87803a3e80c58923e4cd6bca) --- .../fragments/fix-templating-private-role-FA.yml | 2 ++ lib/ansible/playbook/helpers.py | 1 + lib/ansible/playbook/included_file.py | 1 + lib/ansible/playbook/role_include.py | 6 ++--- .../role_with_argspec/meta/argument_specs.yml | 7 ++++++ .../roles/role_with_argspec/tasks/main.yml | 1 + test/integration/targets/include_import/runme.sh | 5 ++++ .../tasks/test_templating_IncludeRole_FA.yml | 28 ++++++++++++++++++++++ 8 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/fix-templating-private-role-FA.yml create mode 100644 test/integration/targets/include_import/roles/role_with_argspec/meta/argument_specs.yml create mode 100644 test/integration/targets/include_import/roles/role_with_argspec/tasks/main.yml create mode 100644 test/integration/targets/include_import/tasks/test_templating_IncludeRole_FA.yml diff --git a/changelogs/fragments/fix-templating-private-role-FA.yml b/changelogs/fragments/fix-templating-private-role-FA.yml new file mode 100644 index 0000000000..bef23f7873 --- /dev/null +++ b/changelogs/fragments/fix-templating-private-role-FA.yml @@ -0,0 +1,2 @@ +bugfixes: + - roles - Fix templating ``public``, ``allow_duplicates`` and ``rolespec_validate`` (https://github.com/ansible/ansible/issues/80304). diff --git a/lib/ansible/playbook/helpers.py b/lib/ansible/playbook/helpers.py index 38e32ef9a2..ff5042a751 100644 --- a/lib/ansible/playbook/helpers.py +++ b/lib/ansible/playbook/helpers.py @@ -308,6 +308,7 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h # template the role name now, if needed all_vars = variable_manager.get_vars(play=play, task=ir) templar = Templar(loader=loader, variables=all_vars) + ir.post_validate(templar=templar) ir._role_name = templar.template(ir._role_name) # uses compiled list from object diff --git a/lib/ansible/playbook/included_file.py b/lib/ansible/playbook/included_file.py index 409eaec795..b833077c95 100644 --- a/lib/ansible/playbook/included_file.py +++ b/lib/ansible/playbook/included_file.py @@ -187,6 +187,7 @@ class IncludedFile: role_name = templar.template(role_name) new_task = original_task.copy() + new_task.post_validate(templar=templar) new_task._role_name = role_name for from_arg in new_task.FROM_ARGS: if from_arg in include_args: diff --git a/lib/ansible/playbook/role_include.py b/lib/ansible/playbook/role_include.py index fb49ec4082..75d26fb811 100644 --- a/lib/ansible/playbook/role_include.py +++ b/lib/ansible/playbook/role_include.py @@ -52,9 +52,9 @@ class IncludeRole(TaskInclude): # ATTRIBUTES # private as this is a 'module options' vs a task property - allow_duplicates = NonInheritableFieldAttribute(isa='bool', default=True, private=True) - public = NonInheritableFieldAttribute(isa='bool', default=False, private=True) - rolespec_validate = NonInheritableFieldAttribute(isa='bool', default=True) + allow_duplicates = NonInheritableFieldAttribute(isa='bool', default=True, private=True, always_post_validate=True) + public = NonInheritableFieldAttribute(isa='bool', default=False, private=True, always_post_validate=True) + rolespec_validate = NonInheritableFieldAttribute(isa='bool', default=True, private=True, always_post_validate=True) def __init__(self, block=None, role=None, task_include=None): diff --git a/test/integration/targets/include_import/roles/role_with_argspec/meta/argument_specs.yml b/test/integration/targets/include_import/roles/role_with_argspec/meta/argument_specs.yml new file mode 100644 index 0000000000..e6d200c165 --- /dev/null +++ b/test/integration/targets/include_import/roles/role_with_argspec/meta/argument_specs.yml @@ -0,0 +1,7 @@ +argument_specs: + main: + short_description: The main entry point for dup_allowed_role + options: + optional_int: + type: int + description: An integer value diff --git a/test/integration/targets/include_import/roles/role_with_argspec/tasks/main.yml b/test/integration/targets/include_import/roles/role_with_argspec/tasks/main.yml new file mode 100644 index 0000000000..23f52ef574 --- /dev/null +++ b/test/integration/targets/include_import/roles/role_with_argspec/tasks/main.yml @@ -0,0 +1 @@ +- debug: msg='Running role_with_argspec' diff --git a/test/integration/targets/include_import/runme.sh b/test/integration/targets/include_import/runme.sh index d384a12e14..078f080b0d 100755 --- a/test/integration/targets/include_import/runme.sh +++ b/test/integration/targets/include_import/runme.sh @@ -121,6 +121,11 @@ ansible-playbook valid_include_keywords/playbook.yml "$@" ansible-playbook tasks/test_allow_single_role_dup.yml 2>&1 | tee test_allow_single_role_dup.out test "$(grep -c 'ok=3' test_allow_single_role_dup.out)" = 1 +# test templating public, allow_duplicates, and rolespec_validate +ansible-playbook tasks/test_templating_IncludeRole_FA.yml 2>&1 | tee IncludeRole_FA_template.out +test "$(grep -c 'ok=4' IncludeRole_FA_template.out)" = 1 +test "$(grep -c 'failed=0' IncludeRole_FA_template.out)" = 1 + # https://github.com/ansible/ansible/issues/66764 ANSIBLE_HOST_PATTERN_MISMATCH=error ansible-playbook empty_group_warning/playbook.yml diff --git a/test/integration/targets/include_import/tasks/test_templating_IncludeRole_FA.yml b/test/integration/targets/include_import/tasks/test_templating_IncludeRole_FA.yml new file mode 100644 index 0000000000..cb67a9bb15 --- /dev/null +++ b/test/integration/targets/include_import/tasks/test_templating_IncludeRole_FA.yml @@ -0,0 +1,28 @@ +--- +- name: test templating allow_duplicates, public, and rolespec_validate + hosts: localhost + gather_facts: false + tasks: + - name: prevent duplicate roles with a templated value + block: + - import_role: + name: dup_allowed_role + allow_duplicates: "{{ False | bool }}" + - import_role: + name: dup_allowed_role + allow_duplicates: "{{ False | bool }}" + + - name: prevent leaky vars with a templated value + include_role: + name: role1 + public: "{{ False | bool }}" + - assert: + that: + - where_am_i_defined is undefined + + - name: skip role argspec validation with a templated value + include_role: + name: role_with_argspec + rolespec_validate: "{{ False | bool }}" + vars: + optional_int: wrong_type -- cgit v1.2.1