Suspected ansible bug include_playbook --> include_role where role has a tag

I am pretty sure this is a bug but as per the recommendations when raising a bug, ask the community first!

I have a playbook X that runs an include_playbook: Y
This include_playbook: Y code is inside a block: rescue: pair
Inside this playbook Y is an include_role
main.yml in the role has a single command with a tags: statement
Execute X and it runs the rescue: code and it shows no errors.

No debug output is shown from X prior to the entry to the block or within the block itself, only within the rescue. It ‘smells’ to me like the code importation/compilation had an issue.

Removing the tag: reference from the role fixed the immediate jump to rescue: and the required code was executed.

Running:
Ansible AWX 22.4.1.dev0+g6b381aa79e.d20230821
ansible [core 2.15.5]
config file = None
configured module search path = [‘/root/.ansible/plugins/modules’, ‘/usr/share/ansible/plugins/modules’]
ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.9.17 (main, Aug 9 2023, 00:00:00) [GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] (/usr/bin/python3)
jinja version = 3.1.2
libyaml = True

FYI: running playbook Y in isolation runs without issue.

The tag: definition is as little weird insofar as the tag name is formed in part from a variable:

tags: “{{ some_var }}_firewall”

but this might be a red herring

The difference between include_* (dynamic) and import_* (static) should be noted, but could you provide minimal reproducible playbooks/roles to help me to understand your situation?

2 Likes

Thank you for the response. The problem is that the tag name is itself a variable.

Two playbooks and a role:

import_playbook_B.yml

---
- hosts: localhost
  gather_facts: false
  vars:

  tasks:

  - block:
      - debug:
          msg: "import_playbook_B.yml: including tasks C"
  
      - include_tasks: include_playbook_C.yml
  
      - debug:
          msg: "import_playbook_B.yml: back from including tasks C"
  
    rescue:
      - debug:
          msg: "import_playbook_B.yml: rescue fired"
      - meta: end_play

include_playbook_C.yml

---
    - debug:
        msg: "include_playbook_C.yml: importing role"
    
    - import_role: 
          name: ians_testing
    
    - debug:
        msg: "include_playbook_C.yml: back from importing role"

Role: ians_testing tasks/main.yml contains:

- debug:
    msg: "This is the role"
  tags: "{{ random_var }}_tag_name"

ians_testing vars/main.yml contains:

random_var: banana

Using our old AWX/ansible instance (AWX 15.0.1 and Ansible 2.9.14) we see:

/usr/lib/python3.6/site-packages/ansible/parsing/vault/__init__.py:44: CryptographyDeprecationWarning: Python 3.6 is no longer supported by the Python core team. Therefore, support for it is deprecated in cryptography and will be removed in a future release.
  from cryptography.exceptions import InvalidSignature
/var/lib/awx/venv/ansible/lib/python3.6/site-packages/paramiko/transport.py:219: CryptographyDeprecationWarning: Blowfish has been deprecated
  "class": algorithms.Blowfish,

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

TASK [debug] *******************************************************************
Monday 30 October 2023  14:07:26 +0000 (0:00:00.019)       0:00:00.019 ******** 
ok: [localhost] => {
    "msg": "import_playbook_B.yml: including tasks C"
}

TASK [include_tasks] ***********************************************************
Monday 30 October 2023  14:07:26 +0000 (0:00:00.024)       0:00:00.044 ******** 
included: /tmp/awx_659235_i1yov0iu/project/include_playbook_C.yml for localhost

TASK [debug] *******************************************************************
Monday 30 October 2023  14:07:26 +0000 (0:00:00.334)       0:00:00.378 ******** 
ok: [localhost] => {
    "msg": "include_playbook_C.yml: importing role"
}

TASK [ians_testing : debug] ****************************************************
Monday 30 October 2023  14:07:26 +0000 (0:00:00.027)       0:00:00.405 ******** 
ok: [localhost] => {
    "msg": "This is the role"
}

TASK [debug] *******************************************************************
Monday 30 October 2023  14:07:26 +0000 (0:00:00.023)       0:00:00.429 ******** 
ok: [localhost] => {
    "msg": "include_playbook_C.yml: back from importing role"
}

TASK [debug] *******************************************************************
Monday 30 October 2023  14:07:26 +0000 (0:00:00.022)       0:00:00.451 ******** 
ok: [localhost] => {
    "msg": "import_playbook_B.yml: back from including tasks C"
}

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

Monday 30 October 2023  14:07:26 +0000 (0:00:00.021)       0:00:00.472 ******** 
=============================================================================== 
include_tasks ----------------------------------------------------------- 0.33s
debug ------------------------------------------------------------------- 0.03s
debug ------------------------------------------------------------------- 0.02s
ians_testing : debug ---------------------------------------------------- 0.02s
debug ------------------------------------------------------------------- 0.02s
debug ------------------------------------------------------------------- 0.02s

Using our new AWX/ansible instance (AWX 22.4.1.dev0+g6b381aa79e.d20230821 and Ansible 2.15.5) I see:

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

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "import_playbook_B.yml: including tasks C"
}

TASK [include_tasks] ***********************************************************
included: /runner/project/include_playbook_C.yml for localhost

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "import_playbook_B.yml: rescue fired"
}

TASK [meta] ********************************************************************

NO MORE HOSTS LEFT *************************************************************

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

If I import_role: straight from a playbook as opposed to from an imported playbook

---
- hosts: localhost
  gather_facts: false
  vars:

  tasks:

  - block:

      - import_role:
          name: ians_testing

      - debug:
          msg: "import_playbook_B.yml: including tasks C"
  
      - include_tasks: include_playbook_C.yml
  
      - debug:
          msg: "import_playbook_B.yml: back from including tasks C"
  
    rescue:
      - debug:
          msg: "import_playbook_B.yml: rescue fired"
      - meta: end_play

then I get the more meaningful message:

PLAY [localhost] ***************************************************************
ERROR! 'random_var' is undefined. 'random_var' is undefined

Interestingly in this instance the rescue does not fire.

I hope that this is enough information but reach out to me if you need more. Thanks for your time,
Ian

Taking your advice into consideration:
The difference between include_* (dynamic) and import_* (static) should be noted

If I “include_role” as opposed to “import_role” then I get a meaningful message:


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

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "import_playbook_B.yml: including tasks C"
}

TASK [include_tasks] ***********************************************************
included: /runner/project/include_playbook_C.yml for localhost

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "include_playbook_C.yml: importing role"
}

TASK [include_role : ians_testing] *********************************************
ERROR! 'random_var' is undefined. 'random_var' is undefined

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "import_playbook_B.yml: rescue fired"
}

TASK [meta] ********************************************************************

NO MORE HOSTS LEFT *************************************************************

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

Hi, thanks for clarifying your problem. I can confirm that the behavior you’ve faced is reproducible on my side.

There are some issues already reported for this behavior:

For 2.15, the fix was merged 5 days ago, and was already released as 2.15.6rc1 16 hours ago.

So I can also confirm installing ansible-core==2.15.6rc1 that includes this fix restores the behavior as same as 2.9.

$ pip install -U ansible-core~=2.15.6rc1
...

$ ansible --version
ansible [core 2.15.6rc1]
...

$ ansible-playbook import_playbook_B.yml 
...
TASK [ians_testing : debug] *************************************************************************
ok: [localhost] => {
    "msg": "This is the role"
}
...

As a temporary workaround for 2.15, switch import_role to include_role and add public: true attribute.

    - include_role: 
        name: ians_testing
        public: true

Hope this helps.

1 Like

Perfect, thanks again for your time working on this.

image001.jpg

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.