Passing Results Between Tasks Across Different Hosts in Ansible Playbooks
In an Ansible playbook, you may find yourself needing to pass a variable from one task (on one host) to another on a different host. Here’s how this can be achieved effectively and securely using several methods outlined below:
Option 1: Delegate Fact with delegate_to
Utilize the combination of setting facts directly onto localhost, which will survive an inventory reload if required during your task execution flow:
- name: Get filename on host1.
hosts: host1
tasks:
- command: # Find a file with this finder and register the output as `filename`.
register: result_file
- set_fact:
global_filename: "{{result_file.stdout}}"
delegate_to: localhost
delegate_facts: True
Now you can use that variable on host2 like so, assuming your playbook is structured correctly to allow for this flow of variables across different hosts:
- name: Use the filename from Host1.
hosts: host2
tasks:
- command: # Using {{global_filename}} here in a task on Host2's inventory, after delegation has taken place above.
delegate_to: localhost
Option 2: Use add_host
with Ansible Grouping Mechanism
This option involves creating an additional group of hosts (group
) and adding the host along with its required variable using a task on Host1, like so (please note this method introduces complexity):
- name: Get filename from command.
hosts: localhost # Using 'localhost' as your initial source for setting facts before moving to another group of targets is not typical practice and should be used with caution regarding maintainability complexities, but here it goes nonetheless:
tasks:
- add_host:
hostname: "{{item.stdout | b64decode}}" # Assuming `result_file` contains only one line for filename encoded in base64 (for simplicity)
group: mygroup
with_items: [command(output from previous command)]
Now, you can use this variable on the newly added host within your tasks under the same inventory defined by mygroup
:
- name: Use filename to perform a task.
hosts: mygroup # Targets that were grouped using add_host from above step
tasks:
- command: Your desired operation with {{item}}.hostname as the variable for your specific purpose on these newly included targets in 'mygroup'.
Best Practice Option 3: Delegate Within The Same Playbook’s Flow
To minimize complexity and ensure idempotency, delegate tasks directly within their current flow of execution. Here is how you would modify the task to use this method without resorting to third-party modules or complex configurations (this approach avoid issues related with inventory reloads):
- name: Get filename from command on Host1 and reuse it in a subsequent playbook action directly after its registration.
hosts: host2 # Ensure that the next task is defined within this same flow of execution, which means you won't use `delegate_to`.
tasks:
- name: Perform an operation on filename as if it was registered for Host1 and now available here directly.
command: Your desired action using {{filename}}.stdout or any other relevant variable to get the task done efficiently without crossing host boundaries unnecessarily, which is often not recommended unless there's a strong rationale behind such need due to added complexity in playbook maintainability for example
Remember that this pattern of flow within one inventory and avoiding unnecessary cross-host dependencies helps keep your Ansible scripts manageable while also respecting idempotency principles.