Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: September 24, 2024
When refactoring, debugging, or making any adjustment to large playbooks, we sometimes have to run only a few tasks or even one task only. Thankfully, we can do this in a couple of ways, including using tags and when.
In this tutorial, we’ll describe a few ways to run only one task in Ansible playbook.
ansible-playbook‘s –step option allows us to interactively accept, deny, or skip the execution of tasks, while –start-at-task makes the playbook start at a particular task. When combined together, we can use both options to run only one task in an Ansible playbook.
Our playbook for this illustration will contain two tasks – one that displays the time and one that installs curl:
- name: Display Time and Install Curl
hosts: localhost
become: yes
tasks:
- name: Display Current Time
command: date
- name: Install curl
apt:
name: curl
state: present
In this example, we’re only going to execute the task that installs curl:
$ ansible-playbook playbook.yml --start-at-task='Install curl' --step
By default, Ansible executes a Gathering Facts task. So, when we run the command above, we’ll get a –step prompt to allow or prevent the Gathering Facts task:
$ ansible-playbook playbook.yml --start-at-task='Install curl' --step
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match
'all'
PLAY [Display Time and Install Curl] ***********************************************************************************
Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue:
Whether we allow or prevent the Gathering Facts task, we’ll get the prompt for the Install curl task right after it:
$ ansible-playbook playbook.yml --start-at-task='Install curl' --step
...truncated...
PLAY [Display Time and Install Curl] ***********************************************************************************
Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue: y
Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue: *************************************************************
TASK [Gathering Facts] *************************************************************************************************
ok: [localhost]
Perform task: TASK: Install curl (N)o/(y)es/(c)ontinue:
Of course, once we allow the execution of the Install curl task, we won’t get anymore –step prompts because the Install curl task is the last task in the playbook:
$ ansible-playbook playbook.yml --start-at-task='Install curl' --step
...truncated...
Perform task: TASK: Install curl (N)o/(y)es/(c)ontinue: y
Perform task: TASK: Install curl (N)o/(y)es/(c)ontinue: ****************************************************************
TASK [Install curl] ****************************************************************************************************
changed: [localhost]
PLAY RECAP *************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
However, if there had been another task after Install curl, we would have gotten a prompt. But since we only want to run Install curl, we simply would’ve denied the execution of the subsequent tasks. Of course, that could get tedious if we have many tasks after our target task.
If we want to execute the Install curl task without having to respond to a prompt for the Gathering Facts task, we need to add gather_facts: false to our play configuration:
- name: Display Time and Install Curl
hosts: localhost
become: yes
gather_facts: false
...truncated...
Now, when we execute the command, we won’t get a prompt for Gathering Facts. The playbook goes right to the Install curl task:
$ ansible-playbook playbook.yml --start-at-task='Install curl' --step
...truncated...
PLAY [Display Time and Install Curl] ***********************************************************************************
Perform task: TASK: Install curl (N)o/(y)es/(c)ontinue:
To run only one task in an Ansible playbook using tags, we’ll add the tags keyword to the task and pass a value to it. We’ll work with the same playbook from the previous section, adding a tag to the Display Current Time task:
- name: Display Time and Install Curl
hosts: localhost
become: yes
tasks:
- name: Display Current Time
command: date
tags: date_only
...truncated...
Now, we’ll execute the Display Current Time task only by passing its tag’s value to ansible-playbook‘s –tags option:
$ ansible-playbook playbook.yml --tags "date_only" -v
...truncated...
PLAY [Display Time and Install Curl] ***********************************************************************************
TASK [Display Current Time] ********************************************************************************************
changed: [localhost] => {"changed": true, "cmd": ["date"], "delta": "0:00:00.003507", "end": "2024-09-17 16:39:25.494453", "msg": "", "rc": 0, "start": "2024-09-17 16:39:25.490946", "stderr": "", "stderr_lines": [], "stdout": "Tue 17 Sep 2024 04:39:25 PM UTC", "stdout_lines": ["Tue 17 Sep 2024 04:39:25 PM UTC"]}
PLAY RECAP *************************************************************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
As expected, the playbook executed only the date task. We added the -v option, so we can see the output of the command.
We can configure our playbook to execute only one task when a when condition is met. In this illustration, we’ll execute the date task using a when condition based on a variable.
First, we’ll add when conditions to both tasks:
- name: Display Time and Install Curl
hosts: localhost
become: yes
tasks:
- name: Display Current Time
command: date
when: run_date
- name: Install curl
apt:
name: curl
state: present
when: not run_date
The playbook above will run the Display Current Time task when the run_date variable resolves as True. However, if run_date is False, it’ll run the Install curl task. To show this, we’ll pass a value to the run_date variable using ansible-playbook’s –extra-vars option:
$ ansible-playbook playbook.yml --extra-vars '{run_date: True}'
...truncated...
TASK [Display Current Time] ********************************************************************************************
changed: [localhost]
TASK [Install curl] ****************************************************************************************************
skipping: [localhost]
PLAY RECAP *************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
As expected, the playbook executes the date task but skips the curl task. If we flip things and make run_date False, the curl task will run while the date task won’t:
$ ansible-playbook playbook.yml -e '{run_date: False}'
...truncated...
TASK [Display Current Time] ********************************************************************************************
skipping: [localhost]
TASK [Install curl] ****************************************************************************************************
ok: [localhost]
PLAY RECAP *************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
This method of running only one task may not be the best for large playbooks, as we’d have to specify a nullifying when condition for the non-target tasks. However, if we want to alternate between running and skipping two tasks or group of tasks, this would be a viable approach.
In this article, we discussed how to execute only one task using –start-at-task and –step options, the tags keyword, and when conditionals. Of all three options, the tags keyword is the most straightforward, as it requires fewer steps to configure and is more precise.