diff --git a/changelogs/fragments/fix-displaying-delegate_to-ansible_host.yml b/changelogs/fragments/fix-displaying-delegate_to-ansible_host.yml new file mode 100644 index 00000000000..741b7379487 --- /dev/null +++ b/changelogs/fragments/fix-displaying-delegate_to-ansible_host.yml @@ -0,0 +1,3 @@ +bugfixes: + - callback plugins - fix displaying the rendered ``ansible_host`` variable with ``delegate_to`` (https://github.com/ansible/ansible/issues/84922). + - ssh connection - fix documented variables for the ``host`` option. Connection options can be configured with delegated variables in general. diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index 60c6b392cbc..fa328f396cf 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -19,7 +19,7 @@ from ansible.errors import ( AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleTaskError, AnsibleValueOmittedError, ) -from ansible.executor.task_result import _RawTaskResult +from ansible.executor.task_result import _RawTaskResult, _SUB_PRESERVE from ansible._internal._datatag import _utils from ansible.module_utils._internal import _messages from ansible.module_utils.datatag import native_type_name, deprecator_from_collection_name @@ -771,14 +771,18 @@ class TaskExecutor: # on the results side without having to do any further templating # also now add connection vars results when delegating if self._task.delegate_to: - result["_ansible_delegated_vars"] = {'ansible_delegated_host': self._task.delegate_to} - for k in plugin_vars: - result["_ansible_delegated_vars"][k] = cvars.get(k) + result["_ansible_delegated_vars"] = { + "ansible_delegated_host": self._task.delegate_to, + "ansible_connection": current_connection, + } # note: here for callbacks that rely on this info to display delegation - for requireshed in ('ansible_host', 'ansible_port', 'ansible_user', 'ansible_connection'): - if requireshed not in result["_ansible_delegated_vars"] and requireshed in cvars: - result["_ansible_delegated_vars"][requireshed] = cvars.get(requireshed) + for k in plugin_vars: + if k not in _SUB_PRESERVE["_ansible_delegated_vars"]: + continue + + for o in C.config.get_plugin_options_from_var("connection", current_connection, k): + result["_ansible_delegated_vars"][k] = self._connection.get_option(o) # and return display.debug("attempt loop complete, returning result") diff --git a/lib/ansible/plugins/connection/ssh.py b/lib/ansible/plugins/connection/ssh.py index 08ff188cf6c..a4f7fedcd1c 100644 --- a/lib/ansible/plugins/connection/ssh.py +++ b/lib/ansible/plugins/connection/ssh.py @@ -34,8 +34,6 @@ DOCUMENTATION = """ - name: inventory_hostname - name: ansible_host - name: ansible_ssh_host - - name: delegated_vars['ansible_host'] - - name: delegated_vars['ansible_ssh_host'] host_key_checking: description: Determines if SSH should reject or not a connection after checking host keys. default: True diff --git a/test/integration/targets/delegate_to/delegate_vars_handling.yml b/test/integration/targets/delegate_to/delegate_vars_handling.yml index 13860a910c9..be3ed72ad6e 100644 --- a/test/integration/targets/delegate_to/delegate_vars_handling.yml +++ b/test/integration/targets/delegate_to/delegate_vars_handling.yml @@ -1,11 +1,3 @@ -- name: setup delegated host - hosts: localhost - gather_facts: false - tasks: - - add_host: - name: delegatetome - ansible_host: 127.0.0.4 - - name: ensure we dont use orig host vars if delegated one does not define them hosts: testhost gather_facts: false diff --git a/test/integration/targets/delegate_to/delegate_vars_inventory b/test/integration/targets/delegate_to/delegate_vars_inventory new file mode 100644 index 00000000000..7d32753e0bf --- /dev/null +++ b/test/integration/targets/delegate_to/delegate_vars_inventory @@ -0,0 +1,2 @@ +[all] +delegatetome ansible_host="{{ hostip }}" hostip="127.0.0.4" diff --git a/test/integration/targets/delegate_to/runme.sh b/test/integration/targets/delegate_to/runme.sh index ce5a607d25f..1fed90bfe17 100755 --- a/test/integration/targets/delegate_to/runme.sh +++ b/test/integration/targets/delegate_to/runme.sh @@ -57,7 +57,11 @@ ansible-playbook delegate_facts_block.yml -i inventory -v "$@" ansible-playbook test_delegate_to_loop_caching.yml -i inventory -v "$@" # ensure we are using correct settings when delegating -ANSIBLE_TIMEOUT=3 ansible-playbook delegate_vars_handling.yml -i inventory -v "$@" +ANSIBLE_TIMEOUT=3 ansible-playbook delegate_vars_handling.yml -i inventory -i delegate_vars_inventory -v | tee out +if grep '{{ hostip }}' out; then + echo 'Callback displayed the ansible_host template instead of the rendered value.' + exit 1 +fi ansible-playbook has_hostvars.yml -i inventory -v "$@" diff --git a/test/units/plugins/connection/test_ssh.py b/test/units/plugins/connection/test_ssh.py index e818d27ef86..12011afe5be 100644 --- a/test/units/plugins/connection/test_ssh.py +++ b/test/units/plugins/connection/test_ssh.py @@ -210,8 +210,8 @@ class TestConnectionBaseClass(unittest.TestCase): mock_ospe.return_value = True conn._build_command.return_value = 'some command to run' conn._bare_run.return_value = (0, '', '') - conn.host = "some_host" + conn.set_option("host", "some_host") conn.set_option('reconnection_retries', 9) conn.set_option('ssh_transfer_method', None) # default is smart @@ -261,8 +261,8 @@ class TestConnectionBaseClass(unittest.TestCase): conn._build_command.return_value = 'some command to run' conn._bare_run.return_value = (0, '', '') - conn.host = "some_host" + conn.set_option("host", "some_host") conn.set_option('reconnection_retries', 9) conn.set_option('ssh_transfer_method', None) # default is smart