override non-defaults role variables

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 :slight_smile:

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.

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) 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

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.

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 napisał:

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 :slight_smile:

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
  include_vars: "{{ item }}"
  with_first_found:
   - "defaults_{{ ansible_distribution }}.yml"
   - "defaults_{{ ansible_os_family }}.yml"
   - "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...