Iterate host definitions into single file

I use ansible a lot for work and for my home lab. I love it.

I keep needing an approach that so far has stumped me, so asking here for advice.

I want to create a single file (an icinga2_hosts.conf) which has a separate collection of attributes from each host in my hosts inventory file. I would like to use jinja2 to template one instance and iterate through the hosts building the file in one go; not host by host in the usual ansible approach… although if a single file can be built by that method, I’m all ears.

I think I could duplicate the hosts section in the vars section and then iterate the yaml data for the single file with a loop.

I could actually create a file for each host and that would actually work in icinga2. But I want it in a single file for future readability and to avoid having to look in each host file for some anomaly.

I could give up on ansible for this and use python and jinja2 to pass the hosts inventory file to a jinja2 render function.

Is there a way to actually read the hosts inventory in traditional ansible style and iterate it into a single file using jinja2 as the template mechanism?

I’ve wanted to do this in other scenarios but abandoned those attempts.

Any tips and tricks appreciated.
Chris.

I use ansible a lot for work and for my home lab. I love it.

I keep needing an approach that so far has stumped me, so asking here for advice.

I want to create a single file (an icinga2_hosts.conf) which has a separate collection of attributes from each host in my hosts inventory file.

What do you mean by this?
Can you give an example?

I use ansible a lot for work and for my home lab. I love it.

I keep needing an approach that so far has stumped me, so asking here for advice.

I want to create a single file (an icinga2_hosts.conf) which has a separate collection of attributes from each host in my hosts inventory file. I would like to use jinja2 to template one instance and iterate through the hosts building the file in one go; not host by host in the usual ansible approach... although if a single file can be built by that method, I'm all ears.

You can iterate through your hosts with

{% for host in ansible_play_hosts %}
...
{% endfor %}

and use hostvars[host]['myattribute'] to access an attribute from you inventory.

To create the file, use template or copy with content parameter and add

   run_once: yes
   delegate_to: localhost

Regards
            Racke

Racke,
ansible_play_hosts - I did not know about this magic variable, as they call it. I’ll test but I assume that the attributes come with it.

Then you describe defining a task with:

run_once: yes
delegate_to: localhost

I see run_once in the documentation and they said it was like running only on the first host; which is fine because now I want to run using ansible_play_hosts which gets me all the hosts.

Then instead of using:
delegate_to: localhost

I think I can delegate to the server I am actually running against:
delegate_to: icinga.example.com

Or are you suggesting I delegate to localhost, then copy the resulting file?

dick,

I hope the above result explains what and how I would like to do. But to explain a bit… I want to end up with a file that has something like this content, below. I was trying to figure out a way to subvert the normal processing of an inventory host file and do it all into one file. Racke has show a way of doing this by using a “magic variable” that holds all of the host info I need and how to run it only once so I don’t get a bunch of repetitive files being generated. It’s beautiful… if it works. :wink: I’m sure it will.

object Host “myhost1.mine.me” {
import “generic-host”
address = “192.68.0.1”
vars.os = “Linux”
}
object Host “myhost2.mine.me” {
import “generic-host”
address = “192.68.0.2”
vars.os = “Linux”
}

Thank you.

Racke,
*ansible_play_hosts* - I did not know about this *magic* variable, as they call it. I'll test but I assume that the attributes come with it.

Then you describe defining a task with:

run_once: yes
delegate_to: localhost

I see run_once in the documentation and they said it was like running only on the first host; which is fine because now I want to run using *ansible_play_hosts* which gets me all the hosts.

Then instead of using:
delegate_to: localhost

I think I can delegate to the server I am actually running against:
delegate_to: icinga.example.com

Chris,

yes you can use icinga.example.com if that host is part of your inventory.

Racke

Racke,
One glitch that I did not understand…

I must add:

host: all

instead of just

hosts: icinga.example.com

… and run with all hosts defined in the playbook. I was only using icinga.example.com (the false name of my server). Now I must add:

when: “{{inventory_hostname == ‘icinga.example.com’}}”

to the other tasks. Small price to pay.

Thank you.

Racke,
One glitch that I did not understand...

I must add:

host: all

instead of just

hosts: icinga.example.com

... and run with all hosts defined in the playbook. I was only using icinga.example.com (the false name of my server). Now I must add:

when: "{{inventory_hostname == 'icinga.example.com'}}"

to the other tasks. Small price to pay.

Thank you.

Chris, you can still use "hosts: icinga.example.com" and iterate over the all group:

{% for host in groups['all'] %}
...
{% endfor %}

BTW: the when condition is automatically evaluated by Jinja, so drop the curly braces.

Regards
          Racke

Racke.
– {% for host in groups[‘all’] %}

Beautiful. Thanks.