Updated April 14, 2023
Introduction to Ansible run_once
The following article provides an outline for Ansible run_once. In Ansible, we always tend to work on remote target nodes, for which we write plays and tasks. This is common understanding that anything written in a play or task will be executed on all remoted target hosts unless specified otherwise. But many times you get a situation where you need to run a task only once on a specific machine to generate some data or do some modification, in between of a playbook or in middle of two tasks in a play. In such cases, we need feature parameters like local_action, delegate_to, run_once. run_once, which is used to run a task only one time for the group of hosts mentioned in playbook.
What is Ansible run_once?
Ansible is designed to work in multiple tier environments. It is very useful where running tasks on a host on behalf of another is the requirement. For such requirements where we need one tasks to run only once on a batch of hosts and we will be running that from Ansible controller node, we have feature parameter named run_once. When we have this parameter mentioned in a task, that task will run only once on first host it finds despite the host batch. This is useful in scenarios like Patching on environment where you will send one-time email notification to all system users before starting.
How does Ansible run_once work?
Ansible run_once parameter is used with a task, which you want to run once on first host. When used, this forces the Ansible controller to attempt execution on first host in the current hosts batch, then the result can be applied to the other remaining hosts in current batch. Its best use is with delegate_to parameter, which enables us to run a task on delegated host once and the continue the rest of tasks on remaining hosts.
Given below is the syntax, which shows how it can be used in a playbook.
---
# ...
tasks:
# ...
- shell: some_command run_once: true
# ...
Examples of Ansible run_once
Given below are the examples of Ansible run_once:
Here we will see Ansible parameter run_once, which you might have to use in day to day operations. We will first see our lab, we used for testing purpose. Here we have an Ansible control server named ansible-controller and two remotes hosts named host-one and host-two. We will create playbooks and run Ansible commands on ansible-controller node and see the results on remote hosts.
Example #1
In this example, we have created a playbook with contents like below, here we are trying to download a tarball file from internet to Ansible control node. As this download is needed only once, so we will use run_once in this task. Also as this is to be done on local machine only, we need to mention delegate_to and pass localhost to it.
Then we will unarchive this tarball to remote machines, which will be done separately on both the hosts:
Code:
---
- hosts: all
gather_facts:
no tasks:
- name: Here we download a file from internet to controller node only once using run_once
get_url:
url: http://download.videolan.org/pub/videolan/vlma/0.2.0/vlma-0.2.0-bin.tar.gz
dest: /tmp/
run_once: true
delegate_to:
localhost
- name: Here we unarchive the downloaded file on remote machines.
unarchive:
src: /tmp/vlma-0.2.0-bin.tar.gz
dest: /tmp/
On running this playbook like below with some verbosity, to get some detailed output:
ansible-playbook ansible_run_once_downlaod_copy.yaml -v
We get output like below, where we can see that the tarball was first downloaded to localhost, as we used delegate_to, then using unarchive module, we unarchived this tarball to both remote target machines.
Output:
Example #2
In this example, we have created a playbook with contents like below, here we are trying to achieve that when we fetch IPv4 details from all hosts without using run_once, then we will get different details from each host. But if we use run_once, then the IPv4 details fetched from first host in host batch will be stored and shown another host’s output as well.
Code:
---
-hosts: all
gather_facts:
no tasks:
-name: here we are fetching facts about IPv4 from all setup:
filter: ansible_default_ipv4 register: remote_ipv4
-debug:
var: remote_ipv4
When running this playbook, we have output like below, in which we can see that output is different from different hosts:
ansible-playbook ansible_run_once.yaml
Output:
Now update the playbook like below, where we have mentioned run_once in the task.
Code:
---
-hosts: all
gather_facts:
no tasks:
-name: here we are fetching facts about IPv4 from all setup:
filter:
ansible_default_ipv4
register: remote_ipv4
run_once: true
-debug:
var: remote_ipv4
Now after running it, in output we can see that the data fetched from first host is also shown in the output of second host.
ansible-playbook ansible_run_once.yaml
Output:
Example #3
In this example, we have created a playbook with contents like below, here we are trying to achieve that when we are updating a package on remote machines, a mail should be sent to a email account, with a mail body and subject, so that that mail owner is notified of the changes. Also note use of run_once, which make the sending mail to execute only once.
Code:
---
-hosts:
all
tasks:
-name: Send summary mail local_action:
module: mail
subject: "Summary
Mail" to:
root@localhost
body: we are installing or updating the httpd
run_once: True
-name: Update the remote
machines. yum:
name:
httpd
state:
latest
Executing the playbook using below command:
ansible-playbook ansible_local_action_mail_update.yaml
Output:
Here we can see that when playbook ran, it did try to upgrade httpd package on remote target nodes and the mailing task where local_action is mentioned was performed on local machine viz. the Ansible controller node. Also it was performed only once, as we have used run_once.
We can check that if the mail was created and sent, to check that we have mailx utility.
Using this we can read mail like below.
mailx
Output:
Conclusion
As we saw, using local_action is a bit tricky, but while using it, you do not need to use condition for running a task once like where one action is required to be run once and depending on that all other hosts need to do other actions.
Recommended Articles
This is a guide to Ansible run_once. Here we discuss what is ansible run_once? how does ansible run_once work? and examples respectively. You may also have a look at the following articles to learn more –