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.31k stars 23.8k forks source link

Role parameter: change in variable precedence #81474

Closed RomainMou closed 10 months ago

RomainMou commented 1 year ago

Summary

Hi ;

Since Ansible 8.0.0 (I think, I didn't check every ansible-core version), it seams that role parameters do not take precedence over already define facts.

According to the documentation, role (and include_role) params (line 20) should still take precedence over set_facts / registered vars (line 19). I also checked Ansible 8.x changelogs but I didn't see anything about that, except maybe this bug fix, I'm not sure what Also adjusted the precedence to act the same as inline params means and what are the expected impacts. But if this is a wanted new behavior, I feal like it should be details in major changes, not in the bug fix section.

Issue Type

Bug Report

Component Name

role

Ansible Version

ansible [core 2.15.2]
  config file = /home/courgette/Documents/Bimdata/dev/deployment/ansible.cfg
  configured module search path = ['/home/courgette/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/courgette/.virtualenvs/deploy/lib/python3.11/site-packages/ansible
  ansible collection location = /home/courgette/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/courgette/.virtualenvs/deploy/bin/ansible
  python version = 3.11.3 (main, Jun  5 2023, 09:32:32) [GCC 13.1.1 20230429] (/home/courgette/.virtualenvs/deploy/bin/python)
  jinja version = 3.1.2
  libyaml = True

Configuration

CONFIG_FILE() = /home/courgette/Documents/Bimdata/dev/deployment/ansible.cfg
DEFAULT_FILTER_PLUGIN_PATH(/home/courgette/Documents/Bimdata/dev/deployment/ansible.cfg) = ['/home/courgette/Documents/Bimdata/dev/deployment/ansible_plugins/filter_plugins']
DEFAULT_TIMEOUT(/home/courgette/Documents/Bimdata/dev/deployment/ansible.cfg) = 60
DEFAULT_VAULT_PASSWORD_FILE(/home/courgette/Documents/Bimdata/dev/deployment/ansible.cfg) = /home/courgette/Documents/Bimdata/dev/deployment/.get-vault-pass.sh
EDITOR(env: EDITOR) = vim
PAGER(env: PAGER) = less

CONNECTION:
==========

paramiko_ssh:
____________
timeout(/home/courgette/Documents/Bimdata/dev/deployment/ansible.cfg) = 60

ssh:
___
pipelining(/home/courgette/Documents/Bimdata/dev/deployment/ansible.cfg) = True
timeout(/home/courgette/Documents/Bimdata/dev/deployment/ansible.cfg) = 60

OS / Environment

Tested on Archlinux and also in python:3.11 docker container.

Steps to Reproduce

Create roles/test_set/tasks/main.yml with:

---
- name: "Set test fact."
  ansible.builtin.set_fact:
    test_set_one: "set by test_set"

Create roles/test_debug/tasks/main.yml with:

---
- name: "Debug the variable."
  ansible.builtin.debug:
    var: test_set_one

Create test.yml with:

---
- name: Test
  hosts: localhost
  gather_facts: false
  become: false
  roles:
    - test_set
    - test_debug
    - role: test_debug
      test_set_one: "Set as role parameter"

Run: ansible-playbook test.yml.

Expected Results

[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Test] *********************************************************************************************************************************************************************************************************

TASK [test_set : Set test fact.] ************************************************************************************************************************************************************************************
ok: [localhost]

TASK [test_debug : Debug the variable.] *****************************************************************************************************************************************************************************
ok: [localhost] => {
    "test_set_one": "set by test_set"
}

TASK [test_debug : Debug the variable.] *****************************************************************************************************************************************************************************
ok: [localhost] => {
    "test_set_one": "Set as role parameter"
}

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

This is a the result with ansible 7.x, here the corresponding version used to obtain it:

ansible [core 2.14.8]
  config file = /home/courgette/Documents/Bimdata/dev/deployment/ansible.cfg
  configured module search path = ['/home/courgette/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/courgette/.virtualenvs/deploy/lib/python3.11/site-packages/ansible
  ansible collection location = /home/courgette/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/courgette/.virtualenvs/deploy/bin/ansible
  python version = 3.11.3 (main, Jun  5 2023, 09:32:32) [GCC 13.1.1 20230429] (/home/courgette/.virtualenvs/deploy/bin/python)
  jinja version = 3.1.2
  libyaml = True

Actual Results

[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Test] *********************************************************************************************************************************************************************************************************

TASK [test_set : Set test fact.] ************************************************************************************************************************************************************************************
ok: [localhost]

TASK [test_debug : Debug the variable.] *****************************************************************************************************************************************************************************
ok: [localhost] => {
    "test_set_one": "set by test_set"
}

TASK [test_debug : Debug the variable.] *****************************************************************************************************************************************************************************
ok: [localhost] => {
    "test_set_one": "set by test_set"
}

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


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct
ansibot commented 1 year ago

Files identified in the description:

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

RomainMou commented 1 year ago

Also, if the fact is not already define, role parameter still works as expected:

---
- name: Test
  hosts: localhost
  gather_facts: false
  become: false
  roles:
    - role: test_debug
      test_set_one: "Set as role parameter"
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Test] *********************************************************************************************************************************************************************************************************

TASK [test_debug : Debug the variable.] *****************************************************************************************************************************************************************************
ok: [localhost] => {
    "test_set_one": "Set as role parameter"
}

PLAY RECAP **********************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
sivel commented 1 year ago

Bisected to 0b678d5036f64f95d50d73d3d27a523a2b264050

ekartsonakis commented 10 months ago

I could call this as a braking change. We rolled back to previous ansible version because of this bug. It can cause huge issues when working with multiple roles on production. Is there any roadmap for this?

bcoca commented 10 months ago

we don't do roadmap for bugs, but this is on my list to solve, I had to clear out a few other bugs with roles first, this quite high up the queue now.