include: "{{ ansible_os_family }}.yml" not working

Was going over different posts on how to handle different OS within a role.

In this thread: https://groups.google.com/forum/#!searchin/ansible-project/group_by$20role|sort:relevance|spell:false/ansible-project/OPCESPvMppg/5ueNHQf_oSAJ

I see:

You can do things like

  • include: “{{ ansible_os_family }}.yml”

Yet when I tried in a role I got:
ERROR: file could not read: /roles/postgres/tasks/{{ ansible_os_family }}.yml

If I hard code it like:

  • include: Ubuntu.yml

it works.

The calling playbook has
gather_facts: True

Any suggestions?

ansible 1.9 (devel 3b80f63e22) last updated 2014/12/06 23:08:13 (GMT +000)
lib/ansible/modules/core: (detached HEAD b766390ae2) last updated 2014/12/06 23:08:14 (GMT +000)
lib/ansible/modules/extras: (detached HEAD 19e688b017) last updated 2014/12/06 23:08:16 (GMT +000)
v2/ansible/modules/core: (detached HEAD cb69744bce) last updated 2014/12/06 23:08:17 (GMT +000)
v2/ansible/modules/extras: (detached HEAD 8a4f07eecd) last updated 2014/12/06 23:08:19 (GMT +000)
configured module search path = /ansible/library:/usr/share/ansible/

Hi Francisco

The {{ ansible_os_family }} fact is usually set to the parent (or other ancestor) distribution. For Ubuntu it will be set to “Debian”. You might want to use {{ ansible_distribution }} instead (or rename your included file to Debian.yml - given that there is typically little to no difference between them for most operations).

Regards
Tom

Tom,
Thanks for the suggestion. That did not seem to help. It is as if the variable is not expanding.

ERROR: file could not read: /roles/postgres/tasks/{{ ansible_distribution }}.yml

Tried:
ansible_os_family

ansible_distribution

id

Made copy of the file as Ubuntu.yml and Debian.yml… in case any option worked.

For now, until I can figure the include out, going with this:

`

  • name: Handle install for Ubuntu
    include: Ubuntu.yml
    when: ansible_distribution == “Ubuntu”
    `

That did not even produce output… which was what I was hoping for… so if I can’t figure out the include this would work.

Will very likely still want to figure it out; specially if I use include_vars so likely will revisit this.

All the Galaxy roles I saw did Ubuntu or Centos. Want to do one for Ubuntu and FreeBSD… and later (as low priority) throw in Centos.

I use Ansible for my clients so I like the idea of something I can use for most of my clients vs using one role per OS. Looked at existing roles in galaxy and they were not quite what I needed. Plus figure would be a good exercise for a first role for Galaxy.

Hi Francisco

I tried this with v1.8.2 and it failed as your attempt, apparently not expanding the variable. I thought this would have worked in previous releases, but I could be wrong.

- include: "{{ ansible_distribution }}.yml"

In such a case, I sometimes do conditional includes within roles if I really have to.

- include: MacOSX.yml
  when: ansible_distribution == 'MacOSX'

This has the side effect of showing the tasks therein as ‘skipped’ when the conditional doesn’t match. So I keep them to a minimum and my roles platform-specific. My preference is for small (thin) roles and verbose playbooks, it makes for easier refactoring and reuse. In your playbooks, you can use dynamic groups to apply platform oriented roles, as detailed here: http://docs.ansible.com/playbooks_best_practices.html#operating-system-and-distribution-variance

Regards
Tom

I tried this with v1.8.2 and it failed as your attempt, apparently not expanding the variable. I thought this would have worked in previous releases, but I could be wrong.

- include: "{{ ansible_distribution }}.yml" 

Thanks Tom. Will dig a little more into the documentation. Perhaps there has been a change and old examples found on the web refer to a configuration/syntax no longer supported.

It looks like you are trying to dynamically include a task file. I am pretty sure that is not possible. You can only dynamically include vars files.

I have always seen includes coupled with when statements when you need to conditionally include a task file. If you want to run multiple sets of task at the same time you can do some tricky things with async tasks.

It looks like you are trying to dynamically include a task file. I am pretty sure that is not possible. You can only dynamically include vars files.

Thanks Tom.

I thought it was possible from reading the URL I posted at the beginning of this thread.
I particular I saw this:

Michael DeHaan
Most all ansible modules already abstract out OS details.
Package managers we want you to know - not only do package names change, but the way you interact with those packages change - think of how different Apache is between Ubuntu and CentOS for instance.

You can do things like

  • include: “{{ ansible_os_family }}.yml”

And you can also do things like use “include_vars” with similar tricks where you want to maintain differences.

In most cases you’ll only differ by variables except having a few tasks with “when” statements on them keying off the OS - which will also minimize task duplication.

I got the impression from that post that it was possible to dynamically include a task file.

FWIW, we have the following at the top of all of our tasks/main.yml:

include the distro-specific stuff

  • include: debian.yml
    when: ansible_distribution == ‘Debian’ or ansible_distribution == ‘Ubuntu’

  • include: rhel.yml
    when: ansible_distribution == ‘CentOS’ or ansible_distribution == ‘Red Hat Enterprise Linux’

And then do “distro specific” stuff in those files.

Anything that can be done across both distro types is set out as tasks after the above includes.

Cheers,

Matt

If I may ask a related question, I’m using include / when for my tasks, but I noticed that when I do the same for handlers ( include / when ), it gets called only on first match. If 1st match is not matching my ansible_distribution from tasks, I have a problem.

For instance in my task for OpenBSD.yml I have notify handler “restart pf”. I have handler “restart pf” with the same name in FreeBSD.yml and OpenBSD.yml, both included from handlers/main.yml. First one evaluated is FreeBSD.yml, that one gets “skipped” and 2nd handler with the same name in OpenBSD.yml is never called.

Just want to make sure, if this is feature or bug. If I rename hander so they don’t have identical names, it works as expected.

handlers are play level so if you define conflicting handlers in roles
one of them gets overwritten.