Floren
Floren

Reputation: 531

Execute Ansible reboot with handler only when required

I have the following file structure:

$ tree roles/os
roles/os
├── handlers
│   └── main.yaml
└── tasks
    └── main.yaml

tasks/main.yaml:

---
- name: Upgrade all packages
  ansible.builtin.apt:
    update_cache: true
    upgrade: dist

- name: Update bootloader firmware
  ansible.builtin.command: rpi-eeprom-update -ad
  changed_when: eeprom_update.stdout.find('updates pending') != -1
  notify: Perform reboot
  register: eeprom_update

- name: Check reboot status
  ansible.builtin.stat:
    path: /var/run/reboot-required
    get_checksum: false
  changed_when: reboot.stat.exists
  notify: Perform reboot
  register: reboot

handlers/main.yaml:

---
- name: Perform reboot
  ansible.builtin.reboot:
    post_reboot_delay: 30
  when: >
    eeprom_update.stdout.find('updates pending') != -1 or
    reboot.stat.exists

With the above configuration, a reboot is performed, only if a change occurs.

Is that the correct way to perform a conditional reboot with a handler?

Upvotes: 2

Views: 3144

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68034

You don't have to repeat the conditions in the handler. The conditions were used to notify the handler in the tasks.

  when: >
    eeprom_update.stdout.find('updates pending') != -1 or
    reboot.stat.exists

Remove the condition from the handler

- name: Perform reboot
  ansible.builtin.reboot:
    post_reboot_delay: 30

Notes:

  • In the handler, the syntax of the condition is wrong. The result of the expression is a string. Test it
    - name: Test the syntax of the condition
      block:
        - name: Wrong. The result of the expression is string.
          debug:
            msg: >
              eeprom_update.stdout.find('updates pending') != -1 or
              reboot.stat.exists
        - name: Correct. The result of the expression is boolean.
          debug:
            msg: "{{ eeprom_update.stdout.find('updates pending') != -1 or
                     reboot.stat.exists }}"

        - name: Do not use braces "{{ '{{' }}" in the conditions. Variables are
                expanded automatically in a condition.
          debug:
            msg: Correct. The result of the expression is boolean
          when: eeprom_update.stdout.find('updates pending') != -1 or
                reboot.stat.exists

gives

TASK [Wrong. The result of the expression is string.] ****************************************
ok: [localhost] => 
  msg: |-
    eeprom_update.stdout.find('updates pending') != -1 or reboot.stat.exists

TASK [Correct. The result of the expression is boolean.] *************************************
ok: [localhost] => 
  msg: true

TASK [Do not use braces "{{" in the conditions. Variables are expanded automatically in a condition.] ***
ok: [localhost] => 
  msg: Correct. The result of the expression is boolean
shell> tree .
.
├── ansible.cfg
├── hosts
└── pb.yml

0 directories, 3 files
shell> cat ansible.cfg 
[defaults]
gathering = explicit
inventory = $PWD/hosts
roles_path = $PWD/roles
remote_tmp = ~/.ansible/tmp
retry_files_enabled = false
stdout_callback = yaml
shell> cat hosts 
localhost

The reboot file exists

shell> ls -1 /tmp/reboot-required 
/tmp/reboot-required

The playbook

shell> cat pb.yml 
- hosts: localhost

  tasks:

    - name: Update bootloader firmware
      ansible.builtin.command: echo 'updates pending'
      register: eeprom_update
      changed_when: eeprom_update.stdout.find('updates pending') != -1
      notify: Perform reboot
    - debug:
        var: eeprom_update.stdout

    - name: Check reboot status
      ansible.builtin.stat:
        path: /tmp/reboot-required
        get_checksum: false
      register: reboot
      changed_when: reboot.stat.exists
      notify: Perform reboot
    - debug:
        var: reboot.stat.exists

    - name: Test the syntax of the condition
      block:
        - name: Wrong. The result of the expression is string.
          debug:
            msg: >
              eeprom_update.stdout.find('updates pending') != -1 or
              reboot.stat.exists
        - name: Correct. The result of the expression is boolean.
          debug:
            msg: "{{ eeprom_update.stdout.find('updates pending') != -1 or
                     reboot.stat.exists }}"

        - name: Do not use braces '{{' '}}' in the conditions. Variables are
                expanded automatically in a condition.
          debug:
            msg: Correct. The result of the expression is boolean
          when: eeprom_update.stdout.find('updates pending') != -1 or
                reboot.stat.exists
        
  handlers:

    - name: Perform reboot
      debug:
        msg: Perform reboot

gives

shell> ansible-playbook pb.yml 

PLAY [localhost] *****************************************************************************

TASK [Update bootloader firmware] ************************************************************
changed: [localhost]

TASK [debug] *********************************************************************************
ok: [localhost] => 
  eeprom_update.stdout: updates pending

TASK [Check reboot status] *******************************************************************
changed: [localhost]

TASK [debug] *********************************************************************************
ok: [localhost] => 
  reboot.stat.exists: true

TASK [Wrong. The result of the expression is string.] ****************************************
ok: [localhost] => 
  msg: |-
    eeprom_update.stdout.find('updates pending') != -1 or reboot.stat.exists

TASK [Correct. The result of the expression is boolean.] *************************************
ok: [localhost] => 
  msg: true

TASK [Do not use braces "{{" in the conditions. Variables are expanded automatically in a condition.] ***
ok: [localhost] => 
  msg: Correct. The result of the expression is boolean

RUNNING HANDLER [Perform reboot] *************************************************************
ok: [localhost] => 
  msg: Perform reboot

PLAY RECAP ***********************************************************************************
localhost: ok=8    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Upvotes: 2

Related Questions