ansible / ansible

Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain. Automate everything from code deployment to network configuration to cloud management, in a language that approaches plain English, using SSH, with no agents to install on remote systems. https://docs.ansible.com.
https://www.ansible.com/
GNU General Public License v3.0
62.49k stars 23.83k forks source link

Unexpected behavior with handlers in loops #83932

Closed pablos123 closed 3 weeks ago

pablos123 commented 3 weeks ago

Summary

When I try to notify certain handlers inside a loop I suspect I have an unintended behavior.

When I execute dynamic handlers inside a loop, if the item has not changed I expect that the notify is not send but it does when one or more of the items are true.

Issue Type

Bug Report

Component Name

handlers

Ansible Version

$ ansible --version
ansible [core 2.16.6]
  config file = /home/vagrant/ansible/ansible.cfg
  configured module search path = ['/home/vagrant/ansible/modules']
  ansible python module location = /home/vagrant/ansible/.venv/lib/python3.11/site-packages/ansible
  ansible collection location = /home/vagrant/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/vagrant/ansible/.venv/bin/ansible
  python version = 3.11.9 (main, Jul 22 2024, 17:20:21) [GCC 12.2.0] (/home/vagrant/ansible/.venv/bin/python)
  jinja version = 3.1.4
  libyaml = True

Configuration

# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
CONFIG_FILE() = None

OS / Environment

lsb_release -a

Distributor ID: Debian
Description:    Debian GNU/Linux 12 (bookworm)
Release:        12
Codename:       bookworm

uname -a

Linux $$$ 6.1.0-25-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.106-3 (2024-08-26) x86_64 GNU/Linux

Steps to Reproduce

---
- name: Testing Handlers...
  hosts: localhost
  tasks:
    - name: Testing handler bool False...
      ansible.builtin.debug:
        msg: Notifying Handler False
      when: false
      changed_when: true
      notify: Handler False

    - name: Testing handler bool True...
      ansible.builtin.debug:
        msg: Notifying Handler True
      when: true
      changed_when: true
      notify: Handler True

    - name: Testing handler bool loop with condition...
      ansible.builtin.debug:
        msg: Notifying Handler {{ item }} loop condition
      changed_when: item
      notify: Handler {{ item }} loop condition
      loop:
        - true
        - false
      when: item

    - name: Testing handler bool loop with no condition...
      ansible.builtin.debug:
        msg: Notifying Handler {{ item }} loop no condition
      changed_when: item
      notify: Handler {{ item }} loop no condition
      loop:
        - true
        - false

    - name: Testing handler bool loop with no condition...
      ansible.builtin.debug:
        msg: Notifying Handler {{ item }} loop no condition
      changed_when: item
      notify: Handler {{ item }} loop no condition
      loop:
        - true
        - false

    - name: Testing handler bool loop with no condition all false...
      ansible.builtin.debug:
        msg: Notifying Handler {{ item }} loop no condition all false
      changed_when: item
      notify: Handler {{ item }} loop no condition all false
      loop:
        - false
        - false

    - name: Testing handler bool loop with no condition multiple false...
      ansible.builtin.debug:
        msg: Notifying Handler {{ item }} loop no condition multiple false
      changed_when: item
      notify: Handler {{ item }} loop no condition multiple false
      loop:
        - true
        - false
        - 0

  handlers:
    - name: Handler False
      ansible.builtin.debug:
        msg: I have been notified

    - name: Handler True
      ansible.builtin.debug:
        msg: I have been notified

    - name: Handler False loop condition
      ansible.builtin.debug:
        msg: I have been notified

    - name: Handler True loop condition
      ansible.builtin.debug:
        msg: I have been notified

    - name: Handler True loop no condition
      ansible.builtin.debug:
        msg: I have been notified

    - name: Handler False loop no condition
      ansible.builtin.debug:
        msg: I have been notified

    - name: Handler False loop no condition all false
      ansible.builtin.debug:
        msg: I have been notified

    - name: Handler False loop no condition multiple false
      ansible.builtin.debug:
        msg: I have been notified

    - name: Handler True loop no condition multiple false
      ansible.builtin.debug:
        msg: I have been notified

    - name: Handler 0 loop no condition multiple false
      ansible.builtin.debug:
        msg: I have been notified

Expected Results

I expected the items inside the loops with no condition that returned OK to not notify the handlers but they do. Is this the expected result? If it is I'm not understanding properly. I read this documentation:

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html

That clearly states that Sometimes you want a task to run only when a change is made on a machine.

I left the other test cases because I think the behavior is the expected. Maybe is good for comparison. I expected the behavior to be something like the loop with condition task.

If all the items are OK then none of the handlers are notified, that's fine.

Actual Results

PLAY [Testing Handlers...] *******************************************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************************************
ok: [localhost]

TASK [Testing handler bool False...] *********************************************************************************************************************************************************
skipping: [localhost]

TASK [Testing handler bool True...] **********************************************************************************************************************************************************
changed: [localhost] => {
    "msg": "Notifying Handler True"
}

TASK [Testing handler bool loop with condition...] *******************************************************************************************************************************************
changed: [localhost] => (item=True) => {
    "msg": "Notifying Handler True loop condition"
}
skipping: [localhost] => (item=False)

TASK [Testing handler bool loop with no condition...] ****************************************************************************************************************************************
changed: [localhost] => (item=True) => {
    "msg": "Notifying Handler True loop no condition"
}
ok: [localhost] => (item=False) => {
    "msg": "Notifying Handler False loop no condition"
}

TASK [Testing handler bool loop with no condition...] ****************************************************************************************************************************************
changed: [localhost] => (item=True) => {
    "msg": "Notifying Handler True loop no condition"
}
ok: [localhost] => (item=False) => {
    "msg": "Notifying Handler False loop no condition"
}

TASK [Testing handler bool loop with no condition all false...] ******************************************************************************************************************************
ok: [localhost] => (item=False) => {
    "msg": "Notifying Handler False loop no condition all false"
}
ok: [localhost] => (item=False) => {
    "msg": "Notifying Handler False loop no condition all false"
}

TASK [Testing handler bool loop with no condition multiple false...] *************************************************************************************************************************
ok: [localhost] => (item=False) => {
    "msg": "Notifying Handler False loop no condition multiple false"
}
changed: [localhost] => (item=True) => {
    "msg": "Notifying Handler True loop no condition multiple false"
}
ok: [localhost] => (item=0) => {
    "msg": "Notifying Handler 0 loop no condition multiple false"
}
changed: [localhost] => (item=1) => {
    "msg": "Notifying Handler 1 loop no condition multiple false"
}

RUNNING HANDLER [Handler True] ***************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "I have been notified"
}

RUNNING HANDLER [Handler True loop condition] ************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "I have been notified"
}

RUNNING HANDLER [Handler True loop no condition] *********************************************************************************************************************************************
ok: [localhost] => {
    "msg": "I have been notified"
}

RUNNING HANDLER [Handler False loop no condition] ********************************************************************************************************************************************
ok: [localhost] => {
    "msg": "I have been notified"
}

RUNNING HANDLER [Handler False loop no condition multiple false] *****************************************************************************************************************************
ok: [localhost] => {
    "msg": "I have been notified"
}

RUNNING HANDLER [Handler True loop no condition multiple false] ******************************************************************************************************************************
ok: [localhost] => {
    "msg": "I have been notified"
}

RUNNING HANDLER [Handler 0 loop no condition multiple false] *********************************************************************************************************************************
ok: [localhost] => {
    "msg": "I have been notified"
}

RUNNING HANDLER [Handler 1 loop no condition multiple false] *********************************************************************************************************************************
ok: [localhost] => {
    "msg": "I have been notified"
}

PLAY RECAP ***********************************************************************************************************************************************************************************
localhost                  : ok=15   changed=5    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

Code of Conduct

ansibot commented 3 weeks ago

Files identified in the description:

None

If these files are incorrect, please update the component name section of the description or use the component bot command.

sivel commented 3 weeks ago

Duplicate of https://github.com/ansible/ansible/issues/77550