Condition judgment and error handling in ansible playbook (fail module failed_when changed_when keyword)

I. Fail module
When writing a shell script, there are may have such demand, when the script to a certain stage, it is necessary to determine a condition, if the condition is established, then immediately stop scripts run, implement this requirement in a shell script is very simple, need only in conditions can call “exit” command to terminate the script when running, so when writing the playbook, if have similar requirements, what should we do?
In order to interrupt the execution of the playBook as we wish, it is also very simple. We only need one module to do this, and this module is the “Fail” module.
We know that when executing playBook, if any of the tasks in PlayBook fail, PlayBook will stop running unless the task is set “ignore_errors: true”. In the task, “ignore_errors: In the case of “true”, the playbook will terminate automatically after the failure of the task execution, while the Fail module is inherently a module for” failed execution “. When the Fail module executes, the Playbook will consider that a task has failed, so as to terminate the operation and achieve the interrupt effect we want. Let’s take a look at a small example:

[root@server4 ~]# vim block8.yml
[root@server4 ~]# cat block8.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - debug:
      msg: "1"
  - debug:
      msg: "2"
  - fail:
  - debug:
      msg: "3"
  - debug:
      msg: "4"

, as shown in the example above cases on the playbook altogether four debug task, after the second debug task, we call the fail module, then let us have a run on the playbook, execute the following after the output information

can be seen from the above, the current two debug module and output the corresponding information, the playbook is announced, after the debug module has not been called, has realized the interrupt script running effect, when performing the fail module, The default output of the FAIL module is’ Failed as requested from Task ‘, and we can customize the error message through the MSG parameter of the FAIL module, as shown below

[root@server4 ~]# vim block9.yml
[root@server4 ~]# cat block5.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - debug:
      msg: "1"
  - fail:
      msg: "Interrupt running playbook"
  - debug:
      msg: "2"


of course, the sample is only for the use of the preliminary introduction to fail the module, we usually don’t want to interrupt the playbook for no reason, often need to determine certain conditions, if the condition is met, then interrupt the script, so usually fail module combined with the when using, for example, if before the module after the execution of the standard output information contain the string “error”, argues that interrupts the script was established, the condition of fail immediately call module, in order to end the playbook, the sample is as follows:

[root@server4 ~]# vim fail1.yml 
[root@server4 ~]# cat fail1.yml 
---
- hosts: testB
  remote_user: root
  tasks: 
  - shell: echo '---error'
    register: return_value
  - fail: 
      msg: 'running fail'
    when: "'error' in return_value.stdout"
  - debug:
      msg: 'I never execute, Because the playbook has stopped'


in the above example, we use the shell output module deliberately a contains’ error ‘string of text, and the shell after module performs the return value of the register to the variable’ return_value ‘, in the later call fail module, and the fail module adds the judgment condition, the corresponding conditions for “. “error” in return_value stdout “, said the conditions shell module after the execution of tagging output information if the string contains “error”, Condition was established, among them, the ‘in’ use of key words and the use of the python ‘in’ is the same, you can use the ‘in’ keyword to judge whether there is a string in another string, can also be used to determine whether a particular value exists in the list, because the shell standard output information does contain the error string, so the fail module corresponding conditions was established, the final call fail module, the playbook terminates.
Note, however, that when using “in” or “not in” for conditional judgments, the entire condition needs to be enclosed in quotation marks, and the string to be judged needs to be enclosed in quotation marks, so the following syntax is correct when using “in” or “not in” for conditional judgments:

when: ' "successful" not in return_value.stdout '
when: " 'successful' not in return_value.stdout "

The failed_when keyword
‘failed_when ‘is used to set the execution status of the corresponding task to failure when the corresponding condition is true. This may not be easy to understand. Let’s start with a small example.

[root@server4 ~]# vim fail2.yml 
[root@server4 ~]# cat fail2.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - debug:
      msg: "I execute normally"
  - shell: "echo 'This is a string for testing error'"
    register: return_value
    failed_when: ' "error" in return_value.stdout'
  - debug:
      msg: "I never execute,Because the playbook has stopped"

In the above example, there are three tasks. The first task outputs “I execute NORMALLY” through the debug module, and the second task calls the shell module, echoing the sentence ‘This is a string for testing error’, and registers the return value into the variable ‘return_value’. The keyword ‘failed_when’ is aligned with the shell keyword, indicating that the corresponding condition is for the shell module. ‘failed_when’ corresponding conditions is’ “error” in return_value stdout, ‘says “error” string if exists in shell module after the execution of the standard output, the established conditions, when the condition after the establishment, execution of the shell module status will be set to fail, due to shell module execution status is set to fail, so the device will stop running, so the final debug module will not be implemented, so, also carried on the playbook, The effects are as follows:

failed_when ‘role is, when the’ failed_when ‘keyword matching conditions,’ failed_when ‘will set the corresponding task execution status, for failure to stop the operation of the playbook, but need to be aware of,’ failed_when ‘although task execution status will be set to fail, but does not represent the task really failed, as the above example, in the case of shell module is carried out completely normal, just after the execution, ‘failed_when’ set the execution state of the shell module to failure. Therefore, ‘failed_when’ does not affect the execution process of the shell module, but only affects the final execution state of the shell module when the condition is established in order to stop the running of playbook.
3. The changed_when keyword
The ‘failed_when’ keyword is used to set the execution status of the corresponding task to failure if the condition is true
The ‘changed_when’ keyword is used to set the execution state of the corresponding task to changed when the condition is true
Let’s look directly at a small example:

[root@server4 ~]# vim changed.yml
[root@server4 ~]# cat changed.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - debug:
      msg: "test message"
    changed_when: 2 > 1

We know that the debug module can only be in the “OK” state for normal execution. In the above example, we use the ‘changed_when’ keyword to define the post-execution state of the debug module as “changed”. You can try to execute the playBook as shown in the above example.

this paper summed up the use of the handlers before, we know that only a task made actual operation (after the execution status is changed), will truly the execution of the corresponding handlers, and in some cases, if you want to after the tasks performed by the return value of the task to determine the final execution status of changed, you can use ‘changed_when’ keywords, so that, when conditions can perform the corresponding handlers, in fact, In addition to being able to set the execution state of a task to “changed” if the condition is true, ‘changed_when ‘also enables the corresponding task to never be changed. Here’s an example:

[root@server4 ~]# vim changed2.yml
[root@server4 ~]# cat changed2.yml 
---
- hosts: testB
  remote_user: root
  tasks:
  - shell: "ls /opt"
    changed_when: false


plus changed_when: false keyword:
can see that changed_when: false keyword can make the corresponding task never be changed state.

Read More: