# override non-defaults role variables

**URL:** <https://forum.ansible.com/t/override-non-defaults-role-variables/17356>\
**Category:** Ansible Project\
**Created:** [January 22, 2015, 4:46pm UTC](https://forum.ansible.com/t/override-non-defaults-role-variables/17356 "2015-01-22T16:46:30Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Antoine\_Jacoutot](https://avatars.discourse-cdn.com/v4/letter/a/977dab/32.png) [@Antoine\_Jacoutot](https://forum.ansible.com/u/Antoine_Jacoutot)\
**Post date:** [January 22, 2015, 4:46pm UTC](https://forum.ansible.com/t/override-non-defaults-role-variables/17356/1 "2015-01-22T16:46:30Z")

</div>

Hi.

After a lot of reading about variable inheritance in ansible, there’s still something I cannot properly grasp…  
I hope some folks in here could enlighten me 🙂

So. I have a “foobar” role with some default variables set under defaults/main.yml.  
So far, so good.  
But I would like some of these default variables to be for e.g. OS-dependant.  
I can easily achieve that using vars or with\_first\_found along with ansible\_os\_family.  
But if I do that, then I am not able to override these variables using group\_vars (/etc/ansible/group\_vars/mygroup (like I am able to override the variables set in defaults/main.yml). I do not want to have to pass variables directly in the inventory file.

I am sure I am missing something stupid…

Thanks in advance.

---

<div class="post-metadata">

**Author:** ![James\_Martin1](https://avatars.discourse-cdn.com/v4/letter/j/0ea827/32.png) [@James\_Martin1](https://forum.ansible.com/u/James_Martin1)\
**Post date:** [January 22, 2015, 6:59pm UTC](https://forum.ansible.com/t/override-non-defaults-role-variables/17356/2 "2015-01-22T18:59:18Z")

</div>

Antoine,

Let’s say for example you have your foobar role, and

`#defaults/main.yml foobar_port: 42`

And let’s say you have an inventory group called “foobar” which is a list of all your foobar hosts.

By using the group\_by module ([http://docs.ansible.com/group\_by\_module.html](http://docs.ansible.com/group_by_module.html)) in a previous play, you can dynamic create a group based on the OS (or any other fact)

`  
Enter code here…

- group\_by: key=machine\_{{ ansible\_distribution }}  
`

You would also have a

`#group_vars/machine_Ubuntu foobar_port: 43`

and a

`#group_vars/machine_CentOS foobar_port: 44`

That would render the 43 or 44, overriding the default role value and be dependent on the OS.

- James

---

<div class="post-metadata">

**Author:** ![Antoine\_Jacoutot](https://avatars.discourse-cdn.com/v4/letter/a/977dab/32.png) [@Antoine\_Jacoutot](https://forum.ansible.com/u/Antoine_Jacoutot)\
**Post date:** [January 23, 2015, 9:59am UTC](https://forum.ansible.com/t/override-non-defaults-role-variables/17356/3 "2015-01-23T09:59:39Z")

</div>

Hi James and thanks for the quick answer.

I already tried what you proposed but my issue is that the role ended not being self-contained.  
i.e. I had to put the default os values under /etc/ansible/group\_vars/machine\_\* instead of within the role hierarchy.

Or is there a way that I missed?  
Thanks.

---

<div class="post-metadata">

**Author:** ![Tomasz\_Kontusz](https://avatars.discourse-cdn.com/v4/letter/t/bc79bd/32.png) [@Tomasz\_Kontusz](https://forum.ansible.com/u/Tomasz_Kontusz)\
**Post date:** [January 23, 2015, 10:42am UTC](https://forum.ansible.com/t/override-non-defaults-role-variables/17356/4 "2015-01-23T10:42:11Z")

</div>

There is another way: you can put "foo: ‘{{ default\_foo }}’ in defaults, and only set default\_foo in the per-OS variables

Antoine Jacoutot [ajacoutot@bsdfrog.org](mailto:ajacoutot@bsdfrog.org) napisał:

---

<div class="post-metadata">

**Author:** ![Antoine\_Jacoutot](https://avatars.discourse-cdn.com/v4/letter/a/977dab/32.png) [@Antoine\_Jacoutot](https://forum.ansible.com/u/Antoine_Jacoutot)\
**Post date:** [January 23, 2015, 1:13pm UTC](https://forum.ansible.com/t/override-non-defaults-role-variables/17356/5 "2015-01-23T13:13:45Z")

</div>

Ok, It took me a little while to understand what you meant with "only set default\_foo in the per-OS variables"  
but I think I got it. Thanks Tomasz, that's clever 🙂

For the record, this is what I ended up with and it seems to work fine (I can override one or more vars using the inventory hierarchy under /etc/ansible):  
(of course I have to duplicate all vars from defaults.yml into the OS-specific vars files, not just the ones that need overriding, but I can leave with that)

# tasks/main.yml  
- name: OS-specific vars  
&nbsp;&nbsp;include\_vars: "{{ item }}"  
&nbsp;&nbsp;with\_first\_found:  
&nbsp;&nbsp;&nbsp;- "defaults\_{{ ansible\_distribution }}.yml"  
&nbsp;&nbsp;&nbsp;- "defaults\_{{ ansible\_os\_family }}.yml"  
&nbsp;&nbsp;&nbsp;- "defaults.yml"

# defaults/main.yml  
foobar: '{{ def\_foobar }}'

# vars/defaults.yml  
def\_foobar: blahblah

# vars/defaults\_CentOS.yml  
def\_foobar: blahblah-for-centos

# var/defaults\_Debian.yml  
def\_foobar: blahblah-for-debian-family

Thank you again Tomasz.  
Unless someone has a better idea...
