Variable precedence and making roles work across distributions

The technique I usually use for making a role work cross-distro is to do two things:

For variables: Include a variables file named {{ ansible_os_family }}.yml (then stick ‘Debian.yml’ and ‘RedHat.yml’, etc. into the role’s vars folder.

For tasks: Add “when: ansible_os_family == ‘Distribution’” to the task (where ‘Distribution’ is Debian, RedHat, etc.).

This presents an issue; for normal variables that I want to let role users override easily, I put the variables in the roles ‘defaults/main.yml’ file. But for distribution-specific variables (for example, “java_packages” in my Java role), I have to put the distro-specific vars include files in the main ‘vars’ folder, so those variables have higher precedence than, say, group_vars.

I’ve bumped into this a few times, but could usually find other ways of getting the variable I want to take hold. For some users, it’s not possible, thus I have bugs like: Openjdk-7 cannot be installed.

What are some possible fixes/other ways to do this?

I could set up a variable for each distro (like “java_redhat_packages” and “java_debian_packages”, but in some roles, where 5-10 of these would be needed, I fear maintainability and simplicity would be sacrificed for variable overridability…

How about this solution?

In defaults/main.yml:

java_distribution_packages:
Debian: [ ‘openjdk-7’, ‘java-stuff’ ]
RefHat: [ ‘java-runtime-7’, ‘other-stuff’ ]

And then, in tasks/main.yml:

  • {{ ansible_pkg_mgr }}: name={{ item }} state=latest
    witn_items: java_distribution_packages[ansible_os_family]

I think that should work fine and let you override java_distribution_packages in inventory.

Maciej

Never do this, ansible_pkg_mgr does not allow the with_items block to be grouped into a single yum/apt transaction, which results in much slower package installations.

I understand why it’s appealing, but really don’t … you’ll also find that the yum and apt modules have different options you may want to use from time to time anyway.

Will this work ok if I use apt: module directly instead? For different package lists in Debian and Ubuntu, for example.

You can achieve pretty much the same thing by using group_by or conditional includes along with the variable structure you’ve defined, without loosing the benefits Michael mentioned.

It should work fine with the apt or yum (or other package modules).

group_by is awesome.

  • hosts: webservers
    group_by: key=webservers_{{ ansible_os_family }}

  • hosts: webservers_RedHat
    roles: