# Iterate host definitions into single file

**URL:** <https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089>\
**Category:** Ansible Project\
**Created:** [December 9, 2021, 7:19am UTC](https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089 "2021-12-09T07:19:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![chrisjx](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chrisjx/32/6922_2.png) [@chrisjx](https://forum.ansible.com/u/chrisjx)\
**Post date:** [December 9, 2021, 7:19am UTC](https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089/1 "2021-12-09T07:19:49Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Dick\_Visser](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Dick\_Visser](https://forum.ansible.com/u/Dick_Visser)\
**Post date:** [December 9, 2021, 7:59am UTC](https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089/2 "2021-12-09T07:59:33Z")

</div>

> 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?

---

<div class="post-metadata">

**Author:** ![racke](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/racke/32/4767_2.png) [@racke](https://forum.ansible.com/u/racke)\
**Post date:** [December 9, 2021, 8:02am UTC](https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089/3 "2021-12-09T08:02:38Z")

</div>

> 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

&nbsp;&nbsp;&nbsp;run\_once: yes  
&nbsp;&nbsp;&nbsp;delegate\_to: localhost

Regards  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Racke

---

<div class="post-metadata">

**Author:** ![chrisjx](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chrisjx/32/6922_2.png) [@chrisjx](https://forum.ansible.com/u/chrisjx)\
**Post date:** [December 9, 2021, 9:07am UTC](https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089/4 "2021-12-09T09:07:25Z")

</div>

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](http://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. 😉 I’m sure it will.

object Host “[myhost1.mine.me](http://myhost1.mine.me)” {  
import “generic-host”  
address = “192.68.0.1”  
vars.os = “Linux”  
}  
object Host “[myhost2.mine.me](http://myhost2.mine.me)” {  
import “generic-host”  
address = “192.68.0.2”  
vars.os = “Linux”  
}

Thank you.

---

<div class="post-metadata">

**Author:** ![racke](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/racke/32/4767_2.png) [@racke](https://forum.ansible.com/u/racke)\
**Post date:** [December 9, 2021, 9:13am UTC](https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089/5 "2021-12-09T09:13:15Z")

</div>

> 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

---

<div class="post-metadata">

**Author:** ![chrisjx](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chrisjx/32/6922_2.png) [@chrisjx](https://forum.ansible.com/u/chrisjx)\
**Post date:** [December 9, 2021, 10:36am UTC](https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089/6 "2021-12-09T10:36:24Z")

</div>

Racke,  
One glitch that I did not understand…

I must add:

host: all

instead of just

hosts: [icinga.example.com](http://icinga.example.com)

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

when: “{{inventory\_hostname == ‘[icinga.example.com](http://icinga.example.com)’}}”

to the other tasks. Small price to pay.

Thank you.

---

<div class="post-metadata">

**Author:** ![racke](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/racke/32/4767_2.png) [@racke](https://forum.ansible.com/u/racke)\
**Post date:** [December 9, 2021, 10:43am UTC](https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089/7 "2021-12-09T10:43:52Z")

</div>

> 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  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Racke

---

<div class="post-metadata">

**Author:** ![Chris\_Jefferies](https://avatars.discourse-cdn.com/v4/letter/c/df705f/32.png) [@Chris\_Jefferies](https://forum.ansible.com/u/Chris_Jefferies)\
**Post date:** [December 16, 2021, 8:40pm UTC](https://forum.ansible.com/t/iterate-host-definitions-into-single-file/36089/8 "2021-12-16T20:40:37Z")

</div>

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

Beautiful. Thanks.
