Ansible can be configured for conditional task execution such
as the use of handlers and the when clause.
Handlers run when a task has changed something,
and they're executed after all tasks in a play.
Sometimes you want to skip a particular step on a particular host,
for example,
not to install a certain package if an operating system is a particular version.
This is where we can use the when clause. It allows you to run
tasks when specific conditions are true.
In this demo, we'll also look at blocks that can be used to implement if,
then, else, like statements.
At the end of the demo, we'll also look at loops.
Now let us look to run a playbook with a variable that
is highlighted in the vars section.
The variables that are supported distros,
and this is represented as a list value.
Then we have two packages.
We have the rhpackage and the ubupackage.
So the package names are different for the different flavors of Linux.
So with Ubuntu,
we're going to install the ubupackage when the Ansible distribution is Ubuntu.
So we used a when statement to check for a specific
string statement on the variable.
So when statement does something when the condition is true,
but does nothing when the condition is not true.
Now let us run the playbook,
and you can see that task one has skipped the Ubuntu host,
and task two has skipped the Rocky hosts,
as expected.
Next, we're going to examine the use of handlers,
which can be used for notification actions.
The items listed in a notify section are known as handlers.
Handlers are lists of tasks,
and they're not really any different from regular tasks.
If nothing notifies a handler,
it will not run regardless of how many tasks notify a handler.
So this playbook has a number of tasks,
and one of the tasks will have an intentional fail.
As a result of the failure, the handler will not run.
So once we run the playbook to demonstrate the failure,
you can see an error that it could not find access.
So you may be thinking that there could be a way just to force
this handler even if there is a failure,
and there is.
So to change this,
we need to enter force_handlers: yes just under the hosts section.
We could also use force_handlers: true.
Keep in mind that this is a Boolean,
so we can write Booleans in a number of different ways.
However, as you can see, the handler is still not being executed,
even though we have an explicit force statement.
The reason for this is that handler is not running, as nothing has changed.
A force handler allows you to start the handler if a task has failed,
but there needs to be a change for the handler to be triggered,
and we haven't changed anything.
Next, let's have a look at blocks.
Now a block is a logical group of tasks,
and they are used to control how tasks are executed.
Blocks allow for the logical grouping of tasks and have some error handling.
So most of what you apply to a single task can be applied at a block level,
which makes it much easier to set data or directives coming to tasks.
So in this example,
the play header starts by running on all hosts and Ansible group,
which is rocky1 and rocky2,
and then we have a number of tasks that are grouped by a block.
So below the block section, we have child elements that are tasks to run.
So here, we're just installing and running a service.
Then we have a when statement that applies to the entire block.
This when statement is looking for a fact of ansible_distribution of Rocky.
So let us run this playbook.
So keep in mind,
if we actually change this value to ubuntu and then we run the playbook again,
it will skip the block.
Next, let us have a quick look at loops.
So if you need to create several users such as Sarah,
James, and Matt, and Jimmy, we could have a single task with a loop.
Here we have the loop keyword.
So in the following example, I'm creating users with the use of a loop.
So we're using the user module to loop, and loop requires the keyword item,
and we represent that in a typical variable fashion,
and here we set the state to present.
So here you can see the loop argument also takes a variable.
So the user creation tasks will be used and have a
loop to iterate our variable lists.
We started this module discussing the inventory and how it
can be extended to include specific information about hosts
and groups with variables.
Variables can be defined in inventory, in separate files, and also directories.
The method you choose really does depend on the scalability you are looking for.
We then discussed variables in general and how and where they can be defined.
The inventory is just one place.
We also address conditional task execution with the
when clause and the use of handlers.
Finally, we looked at how Ansible deals with failures.
We had a number of demos including inventory variables,
playbook variables, and demos on conditionals,
handlers, and loops.