In our previous article we have seen how playbooks work and how tasks defined in the playbooks are executed. But in all these cases we see that Ansible executes the tasks in sequentially. Ansible also provides us conditionals in executing tasks bases on conditions.
For
example, let's say you have a playbook that will install Apache HTTPD Server on
the remote host. Now, the Apache HTTPD Server has a different package name for
a Debian-based operating system, and it's called apache2; for a
Red-Hat-based operating system, it's called httpd. But defining multiple
playbooks for different flavors of the *nix operating system is waste of time.
Ansible
allows us to identify system and execute certain command based on this. Ansible
provides conditional statements that help run a task only when a specified
condition is met.Ansible provide a WHEN condition
to execute tasks based on certain conditions. Lets see a basic example of usin
When condition
[root@vx111a
with-ansible]# cat with.yml
---
-
hosts: dev
tasks:
- name: install httpd Package
yum: name=httpd state=latest
sudo: yes
when: ansible_os_family ==
"Redhat"
- name: install apache2 package
apt: name=apache2 state=latest
sudo: yes
when: ansible_os_family ==
"Debian"
The
above playbook is basic example of using the when condition. This is similar to
if-else loop in the programming
syntax. In the above playbook, we first check what the anisble_os_family is.
Once we get the details we will then install the necessary Apache packages
based on that.
In
case if that is Redhat we will go with the HTTPD or apache2 if that is Debain.
Note – Every time Ansible runs a playbook it collects
certain details about the remote machine called Facts. This can be disabled
when we add the gather_facts: false in our playbook. This gathers all the necessary details about
the remote system including variables, memory and all necessary configurations
that are set for the remote machine
The second task in the playbook will install the
latest apache2 package if the ansible_os_family is Debian.
If the when condition doesn't match a task,
then it will simply skip that task and move forward.
Lets
run the playbook
[root@vx111a
with-ansible]# ansible-playbook with.yml
PLAY
[dev] ********************************************************************
GATHERING
FACTS ***************************************************************
ok:
[172.16.202.96]
ok:
[172.16.202.97]
TASK:
[install httpd Package] *************************************************
skipping:
[172.16.202.96]
skipping:
[172.16.202.97]
TASK:
[install apache2 package] ***********************************************
skipping:
[172.16.202.96]
changed:
[172.16.202.97]
PLAY
RECAP ********************************************************************
172.16.202.96 : ok=1 changed=0
unreachable=0 failed=0
172.16.202.97 : ok=2 changed=1
unreachable=0 failed=0
In
the above case, the IP (172.16.202.97) is a Debain machine and the other one
was a Centos machine.
Ansible
allows a variable to register to task that we run on the remote machine. Lets
see another example of using the with Condition along with register
[root@vx111a
with-ansible]# cat with1.yml
---
-
hosts: dev
tasks:
- name: Check for File
command: /usr/bin/cat /tmp/hai
register: cat_response
ignore_errors: yes
- name: Stop Futher if File is Not
available
fail: msg="File is Not available,
Please Create the File First"
when: cat_response.rc == 2
In
the above playbook we have defined a command to run on the remote machine. The
command is to “cat /tmp/hai”. We will make sure to capture the output in the
variable cat_response using the register module.
Ignore_errors – in some conditions when we run a playbook it may
fail due to missing variables or packages or any other reason. What if we want
to continue the playbook even though certain tasks defined were failed? . We
can use the ignore_errors: yes Condition
duing this case. The above condition only governs the return value of failure
of the particular task, so if you have an undefined variable used, it will
still raise an error that users will need to address. Neither will this prevent
failures on connection nor must execution issues, the task be able to run and
return a value of ‘failed’.
Now
if you check the above playbook we have defined a task to check the Contents of
the file /tmp/hai. If the file is not available the task fails and then we have
set the ignore_error to yes which will ignore the errors and continue the
playbook execution.
Every
task that is run will be having a stdout
and stderr. Besides these there will
some other details too like return code (rc) of the command, command itself,
start and end time of the command being executed etc.
-
name: Stop Futher if File is Not available
fail: msg="File is Not available,
Please Create the File First"
when: cat_response.rc == 2
In
the above playbook we are checking the return code of the task executed and
saved in the cat_response variable. We then used the when condition to make
sure that the rc command is equal to 2 , then use the fail module to generate a
failure message
Note
- Apart from ==, Ansible also supports
the >, <, <=, >=, and != operators
with the when condition.
Now
lets run the playbooks as,
[root@vx111a
with-ansible]# ansible-playbook
with1.yml
PLAY
[dev] ********************************************************************
GATHERING
FACTS ***************************************************************
ok:
[172.16.202.96]
ok:
[172.16.202.97]
TASK:
[Check for File] ********************************************************
failed:
[172.16.202.97] => {"cmd": "/usr/bin/cat /tmp/hai",
"failed": true, "rc": 2}
msg:
[Errno 2] No such file or directory
...ignoring
failed:
[172.16.202.96] => {"cmd": "/usr/bin/cat /tmp/hai",
"failed": true, "rc": 2}
msg:
[Errno 2] No such file or directory
...ignoring
TASK:
[Stop Futher if File is Not available] **********************************
failed:
[172.16.202.96] => {"failed": true}
msg:
File is Not available, Please Create the File First
failed:
[172.16.202.97] => {"failed": true}
msg:
File is Not available, Please Create the File First
FATAL:
all hosts have already failed -- aborting
PLAY
RECAP ********************************************************************
to retry, use: --limit
@/root/with1.retry
172.16.202.96 : ok=2 changed=0
unreachable=0 failed=1
172.16.202.97 : ok=2 changed=0
unreachable=0 failed=1
We
can see fail message output when the playbook is ran. We can also see that
though the task failed the execution continued and displayed messages
accordingly.
I
hope I have given clear examples of using the with Condition in Ansbile.
No comments :
Post a Comment