task includes with facts

750 views
Skip to first unread message

Oliver Heinz

unread,
Jun 12, 2014, 9:22:29 AM6/12/14
to ansible...@googlegroups.com
Hi all,

I cannot use facts for include variables. I think it's because the yaml syntax checker fails (as they don't exits at that time):

My test play:
---
- hosts: localhost
  gather_facts: true
  tasks:
  - include: "{{ansible_distribution}}{{ansible_distribution_major_version}}.yml"

$ansible-playbook -i hosts -l localhost -C playbooks/test.yml 
ERROR: file could not read: /home/heinzoliver/ansible/branches/heinzoliver/playbooks/{{ansible_distribution}}{{ansible_distribution_major_version}}.yml

=> it should be /home/heinzoliver/ansible/branches/heinzoliver/playbooks/Debian7.yml

My goal is to put the tasks that differ between the distiributions in seperate task files to avoid having lot's of when-clauses or completely seperated roles for things that are 90% the same and differ 10% between dists/dist-versions.
Is there any chance that the facts can be gathered before doing the rest of the syntax checking? Is it possible to disable the checks? Or am I'm on the wrong track at all?

TIA,
Oliver






Serge van Ginderachter

unread,
Jun 12, 2014, 9:29:40 AM6/12/14
to ansible...@googlegroups.com
This is  not possible, as the parsing of the playbooks happens before anything else. 

The best practice here is to use conditionals on and variables within specific tasks.


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/31ff684a-330a-4c05-99ba-d49c73a0b8af%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Oliver Heinz

unread,
Jun 12, 2014, 9:42:26 AM6/12/14
to ansible...@googlegroups.com
Using lt's of conditionals get's pretty messy - IMHO it would be nicer if it could be handled in seperate files.

I would love if  syntax checks  were a bit more relaxed here:  If variables in an include statement cannot be replaced just print a warning instead of raising an error.

Serge van Ginderachter

unread,
Jun 12, 2014, 10:02:37 AM6/12/14
to ansible...@googlegroups.com

On 12 June 2014 15:42, Oliver Heinz <oliver.h...@googlemail.com> wrote:
Using lt's of conditionals get's pretty messy - IMHO it would be nicer if it could be handled in seperate files.

​You can assign conditionals next to task includes or roles though.​

Oliver Heinz

unread,
Jun 12, 2014, 10:25:27 AM6/12/14
to ansible...@googlegroups.com
Thanks for pointing this out.

So 
  tasks:
  - include: "{{ansible_distribution}}{{ansible_distribution_major_version}}.yml"

would expand to

  tasks:
  - include: Debian6.yml
    when: ansible_distribution == Debian AND ansible_distribution_major_version == 6

  - include: Debian7.yml
    when: ansible_distribution == Debian AND ansible_distribution_major_version == 7

  - include: RedHat5.yml
    when: ansible_distribution == RedHat AND ansible_distribution_major_version == 5

  - include: RedHat6.yml
    when: ansible_distribution == RedHat AND ansible_distribution_major_version == 6
[...]


This is definitely better than putting everything into one file. But I'd still like it much more when the single include + fact var worked - this is the way that is recommended for working with config templates/files so it feels somewhat wrong that it does not work with task includes.


Am Donnerstag, 12. Juni 2014 15:29:40 UTC+2 schrieb Serge van Ginderachter:

Michael DeHaan

unread,
Jun 12, 2014, 10:37:12 PM6/12/14
to ansible...@googlegroups.com
You can use "group_by" to avoid repeated conditionals.

Select the hosts where something is true and apply roles/tasks to the dynamically created group.


Oliver Heinz

unread,
Jun 13, 2014, 4:58:32 AM6/13/14
to ansible...@googlegroups.com
Seperate roles for every flavor are exactly what I wan't to avoid. We usually have different roles for different ansible_os_families but sometimes this is not granular enough.

We have the power to make decisions based on facts at runtime
  action: template src=apache2.conf.j2-{{ ansible_lsb.codename }} dest={{ apache_ConfigBase }}/apache2.conf
to create smart roles that don't need repeated tasks with when statements  for every flavor

But there is no smart way to decide which tasks to run based on facts - just because the YAML syntax checker raises an error because a variable is not defined (yet) and thus a play that is perfectly valid at runtime is considered faulty :-( At least it would be great if that was configurable (fail/warn/ignore)

With the conditional includes we have a workaound for this shortcomming, so that we can reduce the conditionals to one per flavor. This is not great but sufficient - but as ansible is a great tool it is less than I expected ;-)

thanks,
Oliver

C. Morgan Hamill

unread,
Jun 13, 2014, 9:02:58 AM6/13/14
to ansible-project
Excerpts from Oliver Heinz's message of 2014-06-13 04:58:32 -0400:
> But there is no smart way to decide which tasks to run based on facts -
> just because the YAML syntax checker raises an error because a variable is
> not defined (yet) and thus a play that is perfectly valid at runtime is
> considered faulty :-( At least it would be great if that was configurable
> (fail/warn/ignore)

My understanding here, having run into use cases for the same ability,
is that Ansible has, as a conscious design goal, the principle that the
task list should be reconstructable by as valid YAML without any
run-time variable information. The idea being that one could parse
a playbook programmatically without resorting to re-implementing the
`ansible-playbook` script.

I *believe* this is part of the "infrastructure as data" idea that
Michael likes to mention sometimes.

As a Unix partisan of the most obnoxious sort, I *really* like this: it
reminds me of the "separate mechanism from policy" idea that's been
part of the Unix style for decades, now.

Just sharing, as I think it's pretty awesome and worth the slight
trade-off in functionality.
--
Morgan Hamill

Michael DeHaan

unread,
Jun 13, 2014, 1:58:19 PM6/13/14
to ansible...@googlegroups.com
"But there is no smart way to decide which tasks to run based on facts - just because the YAML syntax checker raises an error because a variable is not defined (yet)"

when: foo is defined 

it's a thing





--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.

Oliver Heinz

unread,
Jun 13, 2014, 3:15:48 PM6/13/14
to ansible...@googlegroups.com
Am Freitag, 13. Juni 2014 19:58:19 UTC+2 schrieb Michael DeHaan:
"But there is no smart way to decide which tasks to run based on facts - just because the YAML syntax checker raises an error because a variable is not defined (yet)"
when: foo is defined 


When the variables used for the include have reasonable defaults the parser will not fail.So I defined some foo ;-)
I defined  those variables in role/defaults, because they have to loose in priotity to facts. But sadly defaults are not used when the syntax checker runs. If I rename the defaults dir to vars  they are used and the syntax checker is satisfied [but for precedence reasons I obviously need defaults]
=>  is this difference in behavior for role vars and defaults on purpose?











it's a thing

Michael DeHaan

unread,
Jun 13, 2014, 4:49:33 PM6/13/14
to ansible...@googlegroups.com
I'm not sure what you mean when you say "syntax checker".

Can you show the ansible command line you are running and also the output you are receiving?


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.

Oliver Heinz

unread,
Jun 13, 2014, 5:18:53 PM6/13/14
to ansible...@googlegroups.com


Am Freitag, 13. Juni 2014 22:49:33 UTC+2 schrieb Michael DeHaan:
I'm not sure what you mean when you say "syntax checker".

Syntax checker is probably the wrong term, but before the play starts executing tasks all referenced yaml documents (roles, includes) seem to get parsed and if there is a syntax error in one of them you get an error message (or sometimes a helpful hint).

 

Can you show the ansible command line you are running and also the output you are receiving?




playbooks/roles/test/
├── tasks
│   ├── Debian7.yml
│   └── main.yml
└── vars
    └── main.yml


$ cat playbooks/roles/test/tasks/main.yml 
---
- include: "{{ansible_distribution}}{{ansible_distribution_major_version}}.yml"

$ cat playbooks/roles/test/defaults/main.yml 
---
ansible_distribution: Debian
ansible_distribution_major_version: 7


$ sudo ansible-playbook -i hosts -l localhost playbooks/test.yml 
ERROR: file could not read: /home/heinzoliver/ansible/branches/heinzoliver/playbooks/roles/test/tasks/{{ansible_distribution}}{{ansible_distribution_major_version}}.yml


Using vars instead of defaults works - but as I want them overwridden by facts I need defaults.

$ mv playbooks/roles/test/defaults/ playbooks/roles/test/vars
$ sudo ansible-playbook -i hosts -l localhost playbooks/test.yml 

PLAY [localhost] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [localhost]

PLAY RECAP ******************************************************************** 
localhost                  : ok=1    changed=0    unreachable=0    failed=0   


Debian7.yml is just empty so this output is correct.

TIA,
Oliver

Oliver Heinz

unread,
Jun 13, 2014, 5:21:51 PM6/13/14
to ansible...@googlegroups.com
Sorry 

$ tree -L 2 playbooks/roles/test/
playbooks/roles/test/
├── defaults
│   └── main.yml
└── tasks
    ├── Debian7.yml
    └── main.yml


is the correct one before the move command.


Reply all
Reply to author
Forward
0 new messages