Figuring out playbook_vars_root

405 views
Skip to first unread message

Jean Helou

unread,
Feb 28, 2018, 4:10:09 AM2/28/18
to Ansible Project
I am trying to understand what playbook_vars_root does in Ansible 2.4.3, I have the feeling that it is totally ignored 

According to the documentation : 

>   This sets which playbook dirs will be used as a root to process vars plugins, which includes finding host_vars/group_vars The top option follows the traditional behaviour of using the top playbook in the chain to find the root directory. The bottom option follows the 2.4.0 behaviour of using the current playbook to find the root directory. The all option examines from the first parent to the current playbook.  

Despite my efforts, I can't seem to get anything else than the "bottom" behaviour. 

I have the following tree

─ ansible.cfg
├── group_vars
│   └── foo
│       └── vars.yml
├── host_vars
│   └── localhost.yml
├── inventories
│   └── site.lst
├── main.yml
└── playbooks
    └── sub.yml

ansible.cfg

[defaults]
playbook_vars_root = top

site.lst contains the following 

[foo]
localhost ansible_connection=local

group_vars/foo/vars.yml

---
_group_vars_msg: "host var message"

host_vars/localhost.yml

---
_host_vars_msg: "host var message"

main.yml

---
- hosts: foo
  tasks:
    - debug: msg="main | {{ _group_vars_msg }}"
    - debug: msg="main | {{ _host_vars_msg }}"

- import_playbook: "playbooks/sub.yml"

playbooks/sub.yml

---
- hosts: foo
  tasks:
    - debug: msg="sub | {{ _group_vars_msg }}"
    - debug: msg="sub | {{ _host_vars_msg }}"

Running the following command: 

ansible-playbook -i inventories/site.lst main.yml 

yields 


PLAY [foo] ***********************************************************************************************************************************************************************************************************************************

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

TASK [debug] *********************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "main | group var message"
}

TASK [debug] *********************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "main | host var message"
}

PLAY [foo] ***********************************************************************************************************************************************************************************************************************************

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

TASK [debug] *********************************************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: '_group_vars_msg' is undefined\n\nThe error appears to have been in '/home/ansible/playbooks/sub.yml': line 4, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n    - debug: msg=\"sub | {{ _group_vars_msg }}\"\n      ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes.  Always quote template expression brackets when they\nstart a value. For instance:\n\n    with_items:\n      - {{ foo }}\n\nShould be written as:\n\n    with_items:\n      - \"{{ foo }}\"\n\nexception type: <class 'ansible.errors.AnsibleUndefinedVariable'>\nexception: '_group_vars_msg' is undefined"}
to retry, use: --limit @/home/ansible/main.retry

PLAY RECAP ***********************************************************************************************************************************************************************************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=1


The imported playbook fails to resolve the variables. can someone explain in more details why my main.yml is not considered to be the "top" playbook in this case or is importing playbooks not what is meant by "chain" in the documentation ? 

> The top option follows the traditional behaviour of using the top playbook in the chain to find the root directory

I have of course tried to set the playbook_vars_root to all too to no avail.

I understand that I can move/link/whatever my group_vars and host_vars to inventories or playbooks, but the behaviour doesn't seem consistent with the documentation and I don't understand why. if playbook_vars_root is useless/unsupported it would be nice to remove it from the documentation or at least make it clear that it doesn't do anything.

Thank you,
Jean

Jean Helou

unread,
Feb 28, 2018, 4:53:06 AM2/28/18
to Ansible Project
Looking further into this I find conflicting information (maybe I understand it all wrong)

In https://github.com/ansible/ansible/issues/33177#issuecomment-356976272 ("when including playbook, group_vars of original playbook are ignored") @sivel says : 

We have discussed this in the Core Team Meeting on Jan 11, 2018.

After looking at the code previous to 2.4, and discussing what our expectations are, we have decided that the previous behavior was a bug, and we will not be adding functionality to mimic the pre 2.4 behavior.

but in https://github.com/ansible/ansible/issues/29008#issuecomment-330558987 ("import_playbook from child directory break var scope") @bcoca says :

The fix we are planning does 2 things:

  • keep a 'stack' of playbook paths, starting with the initial playbook and ending with the 'current' one
  • group/host_vars processing should got through each path in order

So 'initial playbook' and the 'current playbook' adjacent group/host_vars will all be read (as well as any intermediate ones). This is still a change from previous behaviour but we believe this is the 'most' correct way of dealing with the variables.

in https://github.com/ansible/ansible/issues/32936#issuecomment-352700117 ("Host variables adjacent to master playbook are unavailable to included tasks") @lufik also mentions

The PLAYBOOK_VARS_ROOT config doesn't change anything (it's only task related not playbook related). Shortly >=2.4.0 breaks the backward compatibility for including playbooks (maybe the caption of this issue should be changed also).

the code does seem to be in agreement (https://github.com/ansible/ansible/blob/stable-2.4/lib/ansible/vars/manager.py#L246) though I am not familiar with the code base but I fail to see the differences between all 3 issues ... they all seem to have a structure similar to what I used in my experimentation.




Reply all
Reply to author
Forward
0 new messages