Hello everyone, I need some help with using variables in jinja templates.
Disclaimer: I am pretty new to ansible, so feel free to tell me that I understood something wrong.
What I’m trying to do
I try to use a variable inside a variable, that gets called from a jinja template
I have my network ranges defined in the global vars
networks:
lclsrv:
ipv4: 10.10.10.0/24
ext:
ipv4: 1234.123.123.12/x
Then I createt a role called “iptables”, with which I would like to manage all iptables on all hosts. In its defaults, there are (obviously) the default_iptable_rules
defined.
Besides them, there are host specific iptables, which are also defined in the defaults, like this e.g:
host1_rules:
- "-A INPUT -p tcp --dport 80 -j ACCEPT"
- "-A INPUT -p tcp --dport 443 -j ACCEPT"
In some of the host specific rules I have to define a network range from the global vars, like:
host2_rules:
- "-A INPUT -p tcp -s {{ networks['ext']['ipv4'] }} --dport 6000 -j ACCEPT"
In the template I try to insert these host specific rules like this:
{% for rule in vars[inventory_hostname + '_rules'] %}
{{rule}}
{% endfor %}
I think I understood, that this “structure” is not the recommended ansible way. Until now we got all host specific iptables organized in there host files, which is probably the clean way of doing this (?) But with lots of hosts this got very messy, so I want to manage them in one single file, to have them all together.
What I get
The for loop itself works as expected, but the variables won’t get processed. The resulting /etc/iptables/rules.v4
for host2 will look exactly like this:
-A INPUT -p tcp -s {{ networks['ext']['ipv4'] }} --dport 6000 -j ACCEPT
So the template get the element from the host specific variable as a string but won’t interpret the variable inside of this string.
I looked at suggestions to use the lookup function, but this also did not work. When I replaced the variable inside of the rule-string with the lookup, the lookup-functiongot printed out, just like the variable in “{{}}”.
I am struggling with this sinc last monday and I would appreciate any help! Tanks!
I try some tests based on your description, and I think I got a solution. Try to use host_vars
This is a playbook:
--- - name: Test for lemmy hosts: your_hosts vars: networks: ext: ipv4: "127.0.0.1" tasks: - name: Use template ansible.builtin.template: src: test.j2 dest: "/etc/iptables/rules.v4" owner: root group: root mode: "0644"
This is a template file
test.j2
:{% for rule in rules %} {{ rule }} {% endfor %}
This is a
host2.yml
file in ahost_vars
directory:--- rules: - "-A INPUT -p tcp -s {{ networks['ext']['ipv4'] }} --dport 6000 -j ACCEPT"
For another hosts you can create separate host files with variable
rules
.