conditionally running tasks

What’s the preferred way to conditionally configure something if the ‘how’ changes from os to os, and version to version ‘of’ any particular os ?

Here’s an example - setting up a serial console on a SysVinit system (example - debian 7.8):


  • hosts: all

gather_facts: yes

tasks:

  • name: set up serial console

replace:

dest: /etc/inittab

regexp: “^#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100$”

replace: “T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100”

notify:

  • telinit_q

handlers:

  • name: telinit_q

command: “/sbin/telinit q”

But that only works on debian-7 systems. I can limit it to debian-7 by inserting

when:
ansible_distribution == ‘Debian’ and ansible_distribution_version == ‘7’

But that doesn’t handle centos-5 which has a slightly different search/replace needed…or centos-7 which uses systemd, and so on.

I guess I’m struggling with how to have a set (tree?) of plays for task-ABC that are known good, but only using them when the os/version say to do it that way.

Is the preferred way to include .yml files based on distribution/version values discovered at runtime ? Examples ?

You could try to variablize the values of the module parameters into os-specific vars files and then do conditional include statements based on the os.

So like

`

You could try to variablize the values of the module parameters into os-specific vars files and then do conditional include statements based on the os.
Where you would have files named like debian-7.yml, etc. And within those files you would have serial_regex/replace defined along with any other vars.

Does that help?

Notionally yes, but ansible doesn’t seem to like variables in - include: statements.

Does ansible do ‘include’ before ‘gather_facts’ perhaps ???
If so, that would be a pretty major bug/misfeature to me…

Here’s an example that shows the problem.

  • hosts: all

gather_facts: yes

tasks:

  • debug: msg=“{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml”

  • include: “{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml”

Running that trivial playbook fails:

ERROR: file could not read: /tmp/{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml

But if you try to debug only (after commenting out the include: line) the fact collection works ok:

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.169]

TASK: [debug msg=“{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml”] ***
ok: [192.168.0.169] => {
“msg”: “Debian-7.8.yml”
}

PLAY RECAP ********************************************************************
192.168.0.169 : ok=2 changed=0 unreachable=0 failed=0

I tried similar things setting variables, custom facts, etc. to no avail. Seems like ansible includes first as it does its runs (???)

I haven't tested your example, but what I usually do is something like:

   tasks:
   - action: group_by key={{ ansible_distribution }}-{{ ansible_distribution_major }}

and have a a group_vars file for each group:

   group_vars/debian-7
   group_vars/redhat-6

This will automatically pull variables from the matching group_vars file.

In fact, in large/complex environments my inventory script has this kind of functionality included so that it has all the needed variables and groups available for every playbook and play from the very start.

Thanks, that helps a lot, I think I’ll go that route…

If you have time, see if you can get variable substitution to work in an include statement. It sure ‘seems’ to try to include the file before doing things defined above it (like grabbing the facts) which to me is a design flaw. If we wanted to have calculated filenames based on other things defined above it in the sequence, how is that possible currently ? How do we know (or control) the ordering of what ansible is doing ?

Lots of cool stuff here, just a bit undefined and perhaps buggy from what I’ve seen thus far, but I might just not be looking up the right buzzwords in their docs.

Hi Vince,

Jonathan’s approach is also valid. Just replace “include” with “include_vars” and it will work.

The group_by approach is pretty neat as it doesn’t produce the pesky “skipping” entries in the run output.

A useful read on precedence: http://docs.ansible.com/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

Cheers,

Dan.