I'm struggling with a pattern pulling inventory vars in Ansible templates, please help. :)
I'm setting up a monitoring server, and I want to be able to automatically provision the servers using Ansible. I'm struggling with loops in the template to allow me to this.
My semi-working soluition so far is in the playbook that calls the template task I have:
monitoringserver.yml
vars: servers_to_monitor: - {cname: web1, ip_address: 192.168.33.111} - {cname: web2, ip_address: 192.168.33.112} - {cname: db1, ip_address: 192.168.33.211} - {cname: db2, ip_address: 192.168.33.212}
template.yml
all_hosts += [ {% for host in servers_to_monitor %} "{{ host.cname }}{{ host.ip }}|cmk-agent|prod|lan|tcp|wato|/" + FOLDER_PATH + "/", {% endfor %} ]
But this isn't ideal as I can't define different IP address for different servers to be monitoring. How have other people done this? I'm sure it must be trivial but my brain's struggling with the syntax.
Thanks
Alan
edit: To clarify the resulting template looks something like this:
all_hosts += [ "web1|cmk-agent|prod|lan|tcp|wato|/" + FOLDER_PATH + "/", "web2|cmk-agent|prod|lan|tcp|wato|/" + FOLDER_PATH + "/", "db1|cmk-agent|prod|lan|tcp|wato|/" + FOLDER_PATH + "/", "db2|cmk-agent|prod|lan|tcp|wato|/" + FOLDER_PATH + "/", ]
What I would like is the values web1/web2/db1/db2 to be different depending on whether I'm using a production inventory file or a development inventory file.
You can nest two looping tasks using include_tasks . However, by default Ansible sets the loop variable item for each loop. This means the inner, nested loop will overwrite the value of item from the outer loop. You can specify the name of the variable for each loop using loop_var with loop_control .
item is not a command, but a variable automatically created and populated by Ansible in tasks which use loops. In the following example: - debug: msg: "{{ item }}" with_items: - first - second. the task will be run twice: first time with the variable item set to first , the second time with second .
Looping over Filetrees. with_filetree recursively matches all files in a directory tree, enabling you to template a complete tree of files on a target system while retaining permissions and ownership.
Jinja2 being a templating language has no need for wide choice of loop types so we only get for loop. For loops start with {% for my_item in my_collection %} and end with {% endfor %} . This is very similar to how you'd loop over an iterable in Python.
Ideally you would be using different inventory files for production and staging, which would allow you to keep the same {{ inventory_hostname }}
value, but target different machines.
You can also loop through different groups...
hosts:
[web] web1 web2 [db] db1 db2
playbook:
- name: play that sets a group to loop over vars: servers_to_monitor: "{{ groups['db'] }}" tasks: - template: src: set-vars.j2 dest: set-vars.js
template:
all_hosts += [ {% for host in servers_to_monitor %} "{{ hostvars[host].inventory_hostname }}{{ hostvars[host].ansible_default_ipv4.address }}|cmk-agent|prod|lan|tcp|wato|/" + FOLDER_PATH + "/", {% endfor %} ]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With