with_items: groups[]

Hi,

Assuming ansible-1.3 from pip, python 2.7.3 from wheezy.

Using something like:

  • include: something.yml
    with_items: groups[‘all’]

I have some error about with_items requiring a list.

Meanwhile, the further works:

  • name: toto
    file: src=client.j2 dest=/etc/munin/objects/{{ item }}.conf […]
    with_items: groups[‘all’]

Not sure if we could call that a bug. Whatever.
Now for what’s really bugging me tonight: I’m trying to configure my munin workers, so all hosts addressed during current ansible run gets defined/updated.

Using this:

  • name: ensure hosts from current run gets munin-monitored
    template: src=/etc/ansible/roles/munin/templates/client.j2 dest=/etc/munin/objects/{{ item }}.conf owner=root group={{ gid_zero }} mode=0644
    with_items: groups[‘all’]

when: hostvars[{{ item }}][‘ansible_default_ipv4’][‘address’] is defined

It seems that my when clause never evaluates to true, even iterating on local host.

Commenting out the when, template fails resolving ‘ansible_default_ipv4’:

fatal: [munin.example.com] => {‘msg’: “One or more undefined variables: ‘dict object’ has no attribute ‘ansible_default_ipv4’”, ‘failed’: True}
fatal: [munin.example.com] => {‘msg’: ‘One or more items failed.’, ‘failed’: True, ‘changed’: False, ‘results’: [{‘msg’: “One or more undefined variables: ‘dict object’ has no attribute ‘ansible_default_ipv4’”, ‘failed’: True}]}

with some template like:
[{{ item }}]

address {{ hostvars[item][‘ansible_default_ipv4’][‘address’] }}
use_node_name yes

I was looking at www.ansibleworks.com/docs/playbook2.html#id7
The last sample (host in groups[‘app_servers’]) looks pretty much like my failing template. Except I’m looping from the playbook.

Have I missed something?

Thanks,

Regards.

Could you open a github ticket for the first issue? It does seem like it’s inconsistent behavior for sure.

For the second issue, did you run the gather_facts step before this? If you’re trying to iterate over other hosts facts but have not yet connected to them, the data will not be there. We have an open feature request to create a lookaside cache to help overcome this situation.

Just to be sure it’s not some other issue, you can verify that the ansible_default_ipv4 structure is being filled by running “ansible -m setup ” and look through the JSON it returns. It is possible that it’s not being picked up correctly by the setup module but most likely it’s what I have described above.

Thanks!

Hi,

I had the same kind of looping through hostvars question …

  • name: ensure hosts from current run gets munin-monitored
    template: src=/etc/ansible/roles/munin/templates/client.j2 dest=/etc/munin/objects/{{ item }}.conf owner=root group={{ gid_zero }} mode=0644
    with_items: groups[‘all’]

when: hostvars[{{ item }}][‘ansible_default_ipv4’][‘address’] is defined

you should try using {{ hostvars[item][‘ansible_default_ipv4’][‘address’] }}

hope this help.

Fred

include cannot be used with host or group vars, not sure if this applies to groups themselves also.

Could you open a github ticket for the first issue? It does seem like it's inconsistent behavior for sure.

I did.
This is expected.
https://github.com/ansible/ansible/issues/4171
Sure, why not.

For the second issue, did you run the gather_facts step before this? If you're trying to iterate over other hosts facts but have not yet connected to them, the data will not be there. We have an open feature request to create a lookaside cache to help overcome this situation.

I haven't disabled gather_facts. These variables are available from local scope.

Investigating, I modified my template to look like this:

[{{ item }}]
{% if hostvars[item]['ansible_default_ipv4'] is defined %}
{% if hostvars[item]['ansible_default_ipv4']['address'] is defined %}
     address {{ hostvars[item]['ansible_default_ipv4']['address'] }}
{% else %}
{% for stuff in hostvars[item]['ansible_default_ipv4'] %}
{{ stuff }}
{% endfor %}
{% endif %}
{% else %}
{% for stuff in hostvars[item] %}
{{ stuff }}
{% endfor %}
{% endif %}
     use_node_name yes

Having the task:
- name: ensure hosts from current run gets munin-monitored
   template: src=/x/munin/templates/client.j2 dest=/etc/munin/objects/{{ item }}.
   with_items: groups['all']
   when: hostvars[{{ item }}] is defined #always evaluates to true

The templates are correctly evaluated:
muninone:~# cat /etc/munin/objects/muninone.example.com.conf
[muninone.example.com]
     address 10.42.242.205
     use_node_name yes
muninone:~# cat /etc/munin/objects/munintoo.example.com.conf
[munintoo.example.com]
     address 10.42.242.220
     use_node_name yes

So I can indeed reach hostvars[{{ item }}]['ansible_default_ipv4'] from my template.

Now if I change my task to:
- name: ensure hosts from current run gets munin-monitored
   template: src=/x/munin/templates/client.j2 dest=/etc/munin/objects/{{ item }}.
   with_items: groups['all']
   when: hostvars[{{ item }}]['ansible_default_ipv4'] is defined

muninone and munintoo iteration get skipped.

ansible:~/playbooks# ansible-playbook -i production centos.yml -l muninservices

PLAY [centos]

Well, seems not.
Maybe was it possible with 1.2.2? I noticed some syntax changes, either in templates en when: clauses, since 1.3.

ansible:~/playbooks# ansible-playbook -i production centos.yml -l muninservices
ERROR: Syntax Error while loading YAML script, /x/munin/tasks/server/suckit.yml
Note: The error may actually appear before this position: line 5, column 20

   with_items: groups['all']
   when: {{ hostvars[item]['ansible_default_ipv4'] }} is defined

Using either:
   when: {{ hostvars[item]['ansible_default_ipv4'] }}
Or:
   when: {{ hostvars[item]['ansible_default_ipv4'] }} is defined

You should quote it, try:

with_item: groups[‘all’]
when: “{{ hostvars[item][‘ansible_default_ipv4’] }}”

Fred

Still failing:

- name: ensure hosts from current run gets munin-monitored
   template: src=/x/munin/templates/client.j2 dest=/etc/munin/objects/{{ item }}.conf ...
   with_items: groups['all']
   when: "{{ hostvars[item]['ansible_default_ipv4'] }}"

TASK: [ensure hosts from current run gets munin-monitored]

You’re making template usage a bit too complicated, really, and this results in your problem.

when: “{{ hostvars[item][‘ansible_default_ipv4’] }}” is defined

Can be written as

when: hostvars[item][‘ansible_default_ipv4’] is defined