3
votes

I have the following ansible setup:

ansible_test/playbooks/roles/main/main.yml

- name: hello world
  hosts: all
  
  tasks:
  - name: hello!
    shell: echo "test"

  - name: display config
    debug:
      msg: "testvar is {{ hostvars['localhost']['testvar'] }}"

ansible_test/playbooks/inventory/hosts

[main]
localhost

[main:vars]
testvar=99

ansible-test/playbooks/inventory/group_vars/all/main.yml

testvar: 77

Now, when I modify the hosts file to the following:

[main]
localhost testvar=88

[main:vars]
testvar=99

I get an output of "testvar is 88". However, when I remove this, I get "testvar is 77" instead of the expected "testvar is 99".

When I add "testvar: 101" to a file: ansible_test/playbooks/inventory/host_vars/localhost.yml, I get an output of "testvar is 101".

I am running the command:

/usr/bin/ansible-playbook -i playbooks/inventory/hosts playbooks/roles/main/main.yml --connection=local -vvvv

Why is this? Shouldn't this host-group definition still take precedence over group_vars?

enter image description here

1
The only host in test_group is called test_var, which is also the name of the var your assign in your role and inventory for host_name belonging to different_group. This is all really confusing. But since I guess your are running your test against host_name, the result you describe looks rather coherent: when different_group exists, it takes value defined in its group vars, when not, the default value in your role. Can you please double check all this, retest after your fix the eventual typo and see if it fixes your issue ? Thanks. - Zeitounator
Yup sorry I am running against host_name and am trying to determine which value for test_var it will pick up in it’s hostvars. - mlz7
But your inventory is still declaring host_name in a single group, not two. - Zeitounator
[test_group]\ntest_var <= This is declaring a host called test_var (not host_name) in group test_group - Zeitounator
Ah ok fixed sorry. Didn’t notice. In my actual code I did not have this typo. - mlz7

1 Answers

3
votes

Looks to me like your example makes all the sense based on the documentation about variable precedence:

Ansible does apply variable precedence, and you might have a use for it. Here is the order of precedence from least to greatest (the last listed variables override all other variables):

  1. command line values (for example, -u my_user, these are not variables)
  2. role defaults (defined in role/defaults/main.yml) 1
  3. inventory file or script group vars 2
  4. inventory group_vars/all 3
  5. playbook group_vars/all 3
  6. inventory group_vars/* 3
  7. playbook group_vars/* 3
  8. inventory file or script host vars 2
  9. inventory host_vars/* 3
  10. playbook host_vars/* 3
  11. host facts / cached set_facts 4
  12. play vars
  13. play vars_prompt
  14. play vars_files
  15. role vars (defined in role/vars/main.yml)
  16. block vars (only for tasks in block)
  17. task vars (only for the task)
  18. include_vars
  19. set_facts / registered vars
  20. role (and include_role) params
  21. include params
  22. extra vars (for example, -e "user=my_user")(always win precedence)

Where you can see that:

  • inventory file or script group vars is 3
  • inventory group_vars/* is 4
  • inventory file or script host vars is 8
  • inventory host_vars/* is 9

So in you first trial, you have

  • inventory file or script group vars is 3 => 99
  • inventory group_vars/* is 4 => 77
  • inventory file or script host vars is 8 => 88

So, 88 wins.


Then you remove 88

  • inventory file or script group vars is 3 => 99
  • inventory group_vars/* is 4 => 77

So, 77 wins.


And then you add one:

  • inventory file or script group vars is 3 => 99
  • inventory group_vars/* is 4 => 77
  • inventory host_vars/* is 9 => 101

So 101 wins.