Warning:
The information here applies to ansible version 2.4.3. This problem
identified here seems to have been fixed in version 2.5.0 and tags on
included tasks work
how you would expect. The behaviour of tags has changed between 2.4.3 and
2.5.0 - See
part-2 for the updated
version.
Once your ansible configuration gets decently complicated, you might well
require multiple roles for different components, and a full run-through of the
playbook might take several minutes. It is therefore useful to be able to run
just a few tasks at once. …Usually repeatedly until you fix the bugs.
For example, today I was troubleshooting a problem with a configuration for
wordpress. The main playbook included roles for collectd and logstash and
the wordpress role itself called in further roles mysql and apache. The whole thing took a
couple of minutes to run, even on subsequent runs after the packages have been
installed.
The error was in a single template in the wordpress role similar to this;
But that template isn’t processed until after about a minute when running the
full playbook, because the main.yml tasks file was called by a role
which was in turn called from the original playbook. So for debugging when you
have to run this repeatedly, this can be a tiresome wait.
According to the ansible documentation, tags would be useful in this situation;
Tags:
If you have a large playbook it may become useful to be able to run a specific
part of the configuration without running the whole playbook.
Both plays and tasks support a “tags:” attribute for this reason.
You can ONLY
filter tasks based on tags from the command line with –tags or –skip-tags.
Adding “tags:” in any part of a play (including roles) adds those tags to the
contained tasks.
The obvious thing to do is to add a tag to that task, and run ansible-playbook
with the tag as an argument.
and then run it like so;
However, I found that the tagged task didn’t run;
Turning back to the documentation, it seems that this is because of the
following caveat;
The above information does not apply to include_tasks or other dynamic
includes, as the attributes applied to an include, only affect the include
itself.
To test this, I added another task that definitely shouldn’t run, and tried
importing the role with the import_role module instead;
and running this, you can see the tagged task runs correctly, and the other
doesn’t
so great!, we just use import_role and not include_role and everything is
good, right?
… Actually…
The reason for using include_role and include_tasks is that the imported
versions are done statically in advance of variable processing. Which means you
can’t do something like this with import_role;
It gives you an error like this;
So how about tagging the include_role…
Ah, well here things go wrong…
It’s running all the tasks under the include regardless of their tag… It’s
seems that contrary to the documentation,
the include_role and include_tasks modules are copying the tag to the
children.
After a bit of head scratching, I found this that someone had noticed this
problem and raised an issue on github.
So with a little modification, a patch to ignore tags in include modules;
when applied to the file lib/ansible/playbook/block.py it allows running of
specific tags on dynamic includes, like so;
will correctly run the dynamically included tasks/roles;
This rather hacky patch also works for calling include_tasks inside an
include_role like this;
will correctly run the dynamically included tasks/roles;
So now you can run just a single tagged task inside a nested set of includes
without waiting for all the other tasks to run…