Task execution control in Ansible

1. Loop

Loop iteration task

1. Simple loop

loop: ##Assignment list
 - value1
 - value2
 -...
{<!-- -->{item}} ##Iteration variable name

#Example#
---
- name: create file
  hosts: 172.25.0.254
  tasks:
    - name: file module
      file:
        name: /mnt/{<!-- -->{item}}
        state: present
      loop:
        - westos_file1
        - westos_file2


2. Circular hash or dictionary list

---
- name: create file
  hosts: 172.25.0.254
  tasks:
    - name: file module
      service:
        name: "{<!-- -->{ item.name}}"
        state: "{<!-- -->{ item.state }}"
      loop:
        - name: httpd
          state: started
        - name: vsftpd
          state: stopped

2. Conditions

when:
  - Condition 1
  - Condition 2
#Conditional judgment#
= value == "string",value == number
< value < number
> value > number
<= value <= number
>= value >= number
!= value != number
is defined value value is defined variable exists
is not defined value is not defined The variable does not exist
in value is in value variable is
not in value is not in value variable is not
bool variable is true value value is true
bool variable false not value value is false
                       value in value2 value is in the value2 list
#Multiple conditions combination#
when:
 Condition 1 and Condition 2
  - Condition 1
  - Condition 2
when:
 Condition 1 or Condition 2
when: >
 Condition 1
 or
 Condition 2


true and false

3. Trigger

notify: The trigger triggers handlers when encountering changes.
handlers: Actions executed after the trigger is fired
#Example#
---
- name: create virtualhost for web server
  hosts: 172.25.0.254
  vars_files:
    ./vhost_list.yml
  tasks:
    - name: create document
      file:
        path: "{<!-- -->{web2.document}}"
        state: directory
    - name: create vhost.conf
      copy:
        dest: /etc/httpd/conf.d/vhost.conf
        content:
          "<VirtualHost *:{<!-- -->{web1.port}}>\\
\tServerName {<!-- -->{web1.name}}\\
\tDocumentRoot
{<!-- -->{web1.document}}\\
\tCustomLog logs/{<!-- -->{web1.name}}.log combined\\
</VirtualHost>\\
\ \
<VirtualHost *:
{<!-- -->{web2.port}}>\\
\tServerName {<!-- -->{web2.name}}\\
\tDocumentRoot {<!-- -->{ web2.document}}\\
\tCustomLog logs/
{<!-- -->{web2.name}}.log combined\\
</VirtualHost>"
      notify: notify
        restart apache
  handlers:
    - name: restart apache
      service:
        name: httpd
        state: restarted


4. Handle failed tasks

1.ignore_errors

#effect:
Play will terminate when it encounters a task failure
ignore_errors: yes will ignore task failures and allow the following tasks to continue running

#Example#
- name: check file play
  hosts: all
  tasks:
    - name: check file
      shell:
        test -e /mnt/file
      ignore_errors: yes
      register: check_state

    - name: show message
      debug:
        msg: hello world

2.force_handlers

#effect:
#When the task fails and the play is terminated, the trigger process will also be called.

#example
---
- name: apache change port
  hosts: 172.25.0.254
  force_handlers: yes
  vars:
    http_port: 80
  tasks:
    - name: configure apache conf file
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        regexp: "^Listen"
        line: "Listen {<!-- -->{ http_port }}"
      notify: restart apache
      
    - name: install error
      dnf:
        name: westos
        state: latest
  handlers:
    - name: restart apache
      service:
        name: httpd
        state: restarted
        enabled: yes

3.changed_when

#effect:
#Control when a task reports that it has made changes; force changes: true, force no changes: false

---
- name: apache change port
  hosts: 172.25.0.254
  force_handlers: yes
  vars:
    http_port: 8080
  tasks:
    - name: configure apache conf file
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        regexp: "^Listen"
        line: "Listen {<!-- -->{ http_port }}"
      changed_when: true
      notify: restart apache
  handlers:
    - name: restart apache
      service:
        name: httpd
        state: restarted
        enabled: yes

4.failed_when

#Force the task to fail when the conditions are met
#Force a play to fail

---
- name: test
  hosts: 172.25.0.254
  tasks:
    - name: shell
      shell: echo hello
      register: westos
      failed_when: "'hello' in westos.stdout"

5.block

block: ##Define the tasks to be run
rescue: ##Define the task to be run when a failed task appears in the block sentence
             ##block runs successfully, then rescue does not run.
always: ##Define the task that will eventually run independently

5. Practice

The requirements for creating playbook ~/westos.yml are as follows:
Create a device named /dev/vdb1 with a size of 1500M
If /dev/vdb does not exist please enter:
 /dev/vdb is not present
If the size of /dev/vdb is less than 1.5G, please output:
 /dev/vdb is less then 1.5G
And create 800M size /dev/vdb1
This device is mounted on /westos
- name: test fdisk
  hosts: all
  tasks:
    - name: check sdb
      debug:
        msg: /dev/sdb is not present
      when: ansible_facts['devices']['sdb'] is not defined

    - name: create /dev/sdb1
      block:
        - name: check size
          parted:
            device: /dev/sdb
            number: 1
            state: present
            part_end: 1.5GiB
          when: ansible_facts['devices']['sdb'] is defined
        - name: show size is not enough 1.5G
          debug:
            msg: /dev/sdb is not enough 1.5G
      rescue:
        - name: create /dev/sdb1
          parted:
            device: /dev/sdb
            number: 1
            state: present
            part_end: 800MiB
          notify: notify
            - set filesystem
            - mount /dev/sdb1
          when: ansible_facts['devices']['sdb'] is defined
      always:
        - name: create mount point
          file:
            path: /westos
            state: directory

  handlers:
    - name: set filesystem
      filesystem:
        fstype: ext4
        dev: /dev/sdb1
    - name: mount /dev/sdb1
      mount:
        path: /westos/
        src: /dev/sdb1
        fstype: ext4
        state: mounted