From 87d10b9b78e1992598d1de064f32b4c5f64fbdf2 Mon Sep 17 00:00:00 2001 From: Xaroth Date: Thu, 15 Nov 2018 16:01:29 +0100 Subject: [PATCH] Include dependency role names in `role_names`. (#46483) * -Change: Include dependency role names in `role_names`. -Add: `play_role_names` magic variable to include only explicitly named roles (formerly `role_names`). -Add: `dependent_role_names` magic variable to include all dependency names for all roles. * -Change: use the ansible_ prefix for new magic variables. -Change: keep `role_names` as a deprecated variable, using the old functionality. * -Add: changelog fragment for the role_names rework. * -Add: Tests for the role_names (and ansible_*role_names) special variables * -Fix: resolve erroneous documentation snippet that was introduced after rebasing. * -Fix: explicitly sort to ensure list comparison works in test. --- .../fragments/46483-role_names-change.yaml | 11 +++++++++ .../special_variables.rst | 13 ++++++++++- lib/ansible/vars/hostvars.py | 3 +++ lib/ansible/vars/manager.py | 18 ++++++++++++++- .../targets/special_vars/tasks/main.yml | 23 ++++++++++++++++++- 5 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/46483-role_names-change.yaml diff --git a/changelogs/fragments/46483-role_names-change.yaml b/changelogs/fragments/46483-role_names-change.yaml new file mode 100644 index 00000000000..e022df3cca0 --- /dev/null +++ b/changelogs/fragments/46483-role_names-change.yaml @@ -0,0 +1,11 @@ +minor_changes: + - magic variables - added a new ``ansible_role_names`` magic variable to include the names of roles being applied to + the host both directly and indirectly (via dependencies). + - magic variabels - added a new ``ansible_play_role_names`` magic variable to mimic the old functionality of + ``role_names``. This variable only lists the names of roles being applied to the host directly, and does not + include those added via dependencies + - magic variables - added a new ``ansible_dependent_role_names`` magic variable to contain the names of roles + applied to the host indirectly, via dependencies. +deprecated_features: + - magic variables - documented the deprecation of the ``role_names`` magic variable in favor of either + ``ansible_role_names`` (including dependency role names) or ``ansible_play_role_names`` (excluding dependencies). diff --git a/docs/docsite/rst/reference_appendices/special_variables.rst b/docs/docsite/rst/reference_appendices/special_variables.rst index 3d729e35eff..e67ad3bda75 100644 --- a/docs/docsite/rst/reference_appendices/special_variables.rst +++ b/docs/docsite/rst/reference_appendices/special_variables.rst @@ -10,6 +10,9 @@ These variables are directly not settable by the user, Ansible will always overr ansible_check_mode Boolean that indicates if we are in check mode or not +ansible_dependent_role_names + The names of the roles currently imported into the current play as dependencies of other plays + ansible_diff_mode Boolean that indicates if we are in diff mode or not @@ -31,9 +34,17 @@ ansible_play_hosts ansible_play_hosts_all List of all the hosts that were targeted by the play +ansible_play_role_names + The names of the roles currently imported into the current play. This list does **not** contain the role names that are + implicitly included via dependencies. + ansible_playbook_python The path to the python interpreter being used by Ansible on the controller +ansible_role_names + The names of the roles currently imported into the current play, or roles referenced as dependencies of the roles + imported into the current play. + ansible_run_tags Contents of the ``--tags`` CLI option, which specifies which tags will be included for the current run. @@ -86,7 +97,7 @@ role_name: The name of the currently executed role role_names - The names of the rules currently imported into the current play. + Deprecated, the same as ansible_play_role_names role_path The path to the dir of the currently running role diff --git a/lib/ansible/vars/hostvars.py b/lib/ansible/vars/hostvars.py index 77589602b8e..8a7516bc723 100644 --- a/lib/ansible/vars/hostvars.py +++ b/lib/ansible/vars/hostvars.py @@ -28,6 +28,9 @@ from ansible.template import Templar STATIC_VARS = [ 'ansible_version', 'ansible_play_hosts', + 'ansible_dependent_role_names', + 'ansible_play_role_names', + 'ansible_role_names', 'inventory_hostname', 'inventory_hostname_short', 'inventory_file', diff --git a/lib/ansible/vars/manager.py b/lib/ansible/vars/manager.py index a783076a3bc..ec5d581ef50 100644 --- a/lib/ansible/vars/manager.py +++ b/lib/ansible/vars/manager.py @@ -451,7 +451,23 @@ class VariableManager: variables['ansible_playbook_python'] = sys.executable if play: - variables['role_names'] = [r._role_name for r in play.roles] + # This is a list of all role names of all dependencies for all roles for this play + dependency_role_names = list(set([d._role_name for r in play.roles for d in r.get_all_dependencies()])) + # This is a list of all role names of all roles for this play + play_role_names = [r._role_name for r in play.roles] + + # ansible_role_names includes all role names, dependent or directly referenced by the play + variables['ansible_role_names'] = list(set(dependency_role_names + play_role_names)) + # ansible_play_role_names includes the names of all roles directly referenced by this play + # roles that are implicitly referenced via dependencies are not listed. + variables['ansible_play_role_names'] = play_role_names + # ansible_dependent_role_names includes the names of all roles that are referenced via dependencies + # dependencies that are also explicitly named as roles are included in this list + variables['ansible_dependent_role_names'] = dependency_role_names + + # DEPRECATED: role_names should be deprecated in favor of ansible_role_names or ansible_play_role_names + variables['role_names'] = variables['ansible_play_role_names'] + variables['ansible_play_name'] = play.get_name() if task: diff --git a/test/integration/targets/special_vars/tasks/main.yml b/test/integration/targets/special_vars/tasks/main.yml index 653bf7b9055..ab5c318d73e 100644 --- a/test/integration/targets/special_vars/tasks/main.yml +++ b/test/integration/targets/special_vars/tasks/main.yml @@ -23,7 +23,7 @@ include_vars: "{{output_dir}}/special_vars.yaml" -- name: veriy all test vars are defined +- name: verify all test vars are defined assert: that: - 'item in hostvars[inventory_hostname].keys()' @@ -35,3 +35,24 @@ - test_template_fullpath - test_template_run_date - test_ansible_managed + +- name: ensure that role_name exists in role_names, ansible_play_role_names, ansible_role_names, and not in ansible_dependent_role_names + assert: + that: + - "role_name in role_names" + - "role_name in ansible_play_role_names" + - "role_name in ansible_role_names" + - "role_name not in ansible_dependent_role_names" + +- name: ensure that our dependency (prepare_tests) exists in ansible_role_names and ansible_dependent_role_names, but not in role_names or ansible_play_role_names + assert: + that: + - "'prepare_tests' in ansible_role_names" + - "'prepare_tests' in ansible_dependent_role_names" + - "'prepare_tests' not in role_names" + - "'prepare_tests' not in ansible_play_role_names" + +- name: ensure that ansible_role_names is the sum of ansible_play_role_names and ansible_dependent_role_names + assert: + that: + - "(ansible_play_role_names + ansible_dependent_role_names)|unique|sort|list == ansible_role_names|sort|list"