3
votes

Ansible version: 2.0.0.2

I need to override role default variables through inventory host variables. As far as I understand reading Variable Precedence: Where Should I Put A Variable? in Ansible Docs, it is possible but maybe it could not be a best practice, but unfortunately it is necessary that some hosts tweak some default configuration parameters.

I'm going to reproduce the real case, so let's consider the following directory hierarchy:

├── debug.yml
├── host_vars
│   └── test.localdomain
├── inventory
│   └── debug
└── roles
    └── debug
        ├── tasks
        │   └── main.yml
        └── vars
            └── main.yml

debug.yml is our playbook file.

---
- name: debug
  hosts: debug
  roles:
    - debug

host_vars/test.localdomain contains the variables I want to take precedence over defaults.

---
foo:
  bar:
    - hey

inventory/debug is the inventory file we're going to use.

[debug]
test.localdomain

roles/debug/tasks/main.yml prints out foo.bar variable.

---
- debug: msg="{{foo.bar}}"

roles/debug/vars/main.yml contains default role variables.

---
foo:
  bar:
    - hello
    - world

At this point, I expect that during debug playbook run, the value of foo.bar is [ "hey" ], but evidently I'm wrong:

> ansible-playbook debug.yml -i inventory/debug

PLAY [debug] **********************************

TASK [setup] **********************************
ok: [test.localdomain]

TASK [debug : debug] **************************
ok: [test.localdomain] => {
    "msg": [
        "hello", 
        "world"
    ]
}

PLAY RECAP *************************************
test.localdomain : ok=2    changed=0    unreachable=0    failed=0   

Running debug module from ansible cli gives me the expected result, so I'm quite sure the host variables are evaluated correctly, but maybe for some reason they're not taking precedence over default role variables.

> ansible test.localdomain -i inventory/debug -m debug -a 'msg="{{foo.bar}}"'
test.localdomain | SUCCESS => {
    "msg": [
        "hey"
    ]
}

Where is my mistake?

1

1 Answers

11
votes

The problem is you're not using role default vars, but role vars. Have a look at the list from the docs again:

  • role defaults
  • inventory vars
  • inventory group_vars
  • inventory host_vars
  • playbook group_vars
  • playbook host_vars
  • host facts
  • registered vars
  • set_facts
  • play vars
  • play vars_prompt
  • play vars_files
  • role and include vars
  • block vars (only for tasks in block)
  • task vars (only for the task)
  • extra vars

role-vars have precedence over host-vars.

role defaults need to be stored in the directory defaults. So by just renaming your folder vars to defaults you should get your expected behavior.