Ansible tags can be used to run only a subset of tasks/roles. This means that by default all tasks are executed and we can only prevent some tasks to execute.
Can we limit a task to be exectued only when "foo" tag is specified? Can we use current tags in when
section of a task?
Ansible 2.5 comes with special tags
never
andalways
. Tagnever
can be used exactly for this purpose. E.g:In this example, the task will only run when the
debug
(ornever
) tag is explicitly requested. [Reference on ansible docs]Although this is a roundabout solution, it works.
Inside the task list register a variable when normal execution runs. Then, add a when condition that checks that variable to the tagged task.
I don't have enough reputation to upvote or comment on the answer suggesting the use of command-line variables (
--extra-vars
), but I have this to add to it:You can prevent play failure in the absence of an
--extra-vars
definition by defining a default value in the playbook itself:Overriding via
--extra-vars
will still work because variables defined on the command line take precedence over all other definitions.The result is that the play runs without error when
thorough
is not changed totrue
on the command line.You can use Conditionals to protect against accidentally running tasks that would otherwise be executed if you don't specify a tag. The caveat to this method is that the play will error and fail if you do not define that extra variable.
Using the extra-vars argument you can trigger your conditional to be executed.
From ansible-playbook --help:
Example:
test.yaml:
A perhaps more idiomatic and elegant way is to add a
when
condition to the task, like such:This uses the magical variable
ansible_run_tags
which contains the list of tags supplied through the CLI argument--tags
(or synonymously-t
) and has the effect of running the above task if and only if the tagdebug
is given.It seems this magic variable has been introduced in ansible 2.5
Yes. Running ansible-playbook with the
--tags foo
flag will ensure that only tasks that are tagged withfoo
are executed. For example, assume we have a playbook called example.yml:running:
Will make sure only the yum task is executed.
So actually you don't really need to use tags in when section to conditionally execute a task. Notice that depending on the complexity of your playbooks/roles you might need to use a combination of --tags and --skip-tags to control which tasks are executed. For example, if an include tasks is tagged as 'foo' and some task inside the included playbook is tagged as 'bar' and you run
The internal task (tagged only as 'bar') will be executed. To avoid the execution of all internal tasks tagged as 'bar' you will have to execute the following command
Checking the 'tags' variable isn't working in Ansible 2.1.1.0. See below for the test. I have an other idea to execute task only when a tag is defined, working for both Ansible 1.9.X and 2.X.Y:
With that, when running the playbook without any tag, the 'foo' variable will be set to true then to false, so nothing is executed. If you add the 'bar' tag, only the first setting will be applied, so the 'foo' variable will be true, then your task will be executed. Enjoy!
And here's the test about the 'tags' variable in Ansible 2.1.1.0:
Here is the playbook:
And here is the output:
There is a special tag - "never", which will prevent a task from running unless a tag is specifically requested.
The
never
tag is the correct solution in general, but it won't work in one instance: tags are not supported onmeta
tasks until Ansible 2.11. In this case we have to fake tag support with awhen:
conditional and the magic variableansible_run_tags
.For example, here's a snippet that will list all hosts and end the play early when you say
--tags list-hosts
. It works with Ansible 2.8 and higher. This is useful if you generated hosts or groups at runtime withadd_host
orgroup_by
, since that happens too late for--list-hosts
.when clause can't evaluate the presence of tags. As a workaround, I use variables and tags together to run tasks specific to that tag/variable.
Ex: Imagine a playbook and inventory
With this approach, you use the tag to select only the tasks in uninstall.yml, but you also need to set 'uninstall_links' variable to something to enable it. So if you run the playbook without any parameters, it will, by default, run the install task. To uninstall, you can set the tag 'uninstall' to your playbook (or cmdline) and MUST set the variable. If you don't set the tag, it will run everything (install and uninstall) in that order, which is good to test the entire process.
How to run everything (it will install and uninstall):
$
ansible-playbook -i inventory site.yml -l dev -s -k -e "uninstall_links=true"
How to run only the 'uninstall' tag on dev group
$
ansible-playbook -i inventory site.yml -l dev -s -k -e "uninstall_links=true" -t uninstall
Therefore, variables and tags could also be in site.yml/inventory files, allowing you to commit into your SCM and record your intention.