In my variable file, I need to define a list variable whose items are of similar pattern, and also share some (redundant) info. Instead of manually type all those info, I would like to generate the list variable in a loop.
e.g., I have 100 hosts, with primary ip address 192.168.100.[1:100], and each host has an extra ip addresses 10.0.1.[1:100]. All primary IPs use the same gateway, say 192.168.100.254, and all extra IPs use another gateway, say 10.0.1.254.
In a task, I want to loop through all hosts, and for each host, it's primary ip, extra ip, and gateways are all needed. I want to use "with_items" in my task, so I want to have a list variable "IP_ADDRS", within which each item is a dict like below:
{ primary_ip: 192.168.100.x, primary_gw: 192.168.100.254, extra_ip: 10.0.1.x, extra_gw: 10.0.1.254}
Instead of define IP_ADDRS manually:
IP_ADDRS:
- { primary_ip: 192.168.100.1, primary_gw: 192.168.100.254, extra_ip: 10.0.1.1, extra_gw: 10.0.1.254}
- { primary_ip: 192.168.100.2, primary_gw: 192.168.100.254, extra_ip: 10.0.1.2, extra_gw: 10.0.1.254}
- ...
I want to generate the list variable "IP_ADDRS" somehow...
I tried jinja2 statements, something like below:
IP_ADDRS: >
"{% for idx in range(1, 101) %}
- { primary_ip: 192.168.100.{{ idx }}, primary_gw: 192.168.100.254, extra_ip: 10.0.1.{{ idx }}, extra_gw: 10.0.1.254 }
"{% endfor %}"
When I print IP_ADDRS using debug module, it does literally print all items in the list, BUT it seems Ansible is not treat this variable as a LIST, thus
with_items: {{ IP_ADDRS }}
does not work as I expected.
Is there any thing wrong with the jinja2 statement, or is there a way to achieve the same result?
Thanks a lot,
/bruin
You may define template of your object and use it in loops:
---
- hosts: localhost
gather_facts: no
vars:
ip_template:
primary_ip: "192.168.100.{{ item }}"
primary_gw: "192.168.100.254"
extra_ip: "10.0.1.{{ item }}"
extra_gw: "10.0.1.254"
tasks:
# execute single task, no need in list
- debug:
msg: "{{ ip_template }}"
with_sequence: "start=1 count=5"
# construct list
- set_fact:
ip_list: "{{ (ip_list | default([])) + [ip_template] }}"
with_sequence: "start=1 count=5"
- debug:
msg: "{{ ip_list }}"
If you still want to have ip_list
defined in your variables, you need to construct complex Jinja2 statement to generate list in JSON-format and not YAML, as you tried. Tiny example of such string with two objects inside: '[{"ip":"192.168.0.10","gw":"192.168.0.1"},{"ip":"192.168.0.20","gw":"192.168.0.1"}]'
If there are many complex variables needs to be generated by loops
, and if/else
. Sometimes, it would become nasty and less understandable when trying to generate them in tasks. Create variable files in jinja
template format might help.
For example, create the variable generated by jinja template:
# variable file
{% for idx in range(1, 101) %}
- primary_ip: 192.168.100.{{ idx }}
primary_gw: 192.168.100.254
extra_ip: 10.0.1.{{ idx }}
extra_gw: 10.0.1.254
{% endfor %}
Then read variable in tasks by template lookup plugin:
# playbook tasks
- name: Read variables
set_fact:
ip_list: "{{ lookup('template', 'path_to_file') | from_yaml }}"
And the result will be:
TASK [set_fact] *******************************************************************************************************************
Tuesday 06 February 2018 17:16:55 +0800 (0:00:00.110) 0:00:00.110 ******
Tuesday 06 February 2018 17:16:55 +0800 (0:00:00.108) 0:00:00.108 ******
ok: [localhost]
TASK [debug] **********************************************************************************************************************
Tuesday 06 February 2018 17:16:55 +0800 (0:00:00.137) 0:00:00.247 ******
Tuesday 06 February 2018 17:16:55 +0800 (0:00:00.137) 0:00:00.245 ******
ok: [localhost] => {
"ip_list": [
{
"extra_gw": "10.0.1.254",
"extra_ip": "10.0.1.1",
"primary_gw": "192.168.100.254",
"primary_ip": "192.168.100.1"
},
{
"extra_gw": "10.0.1.254",
"extra_ip": "10.0.1.2",
"primary_gw": "192.168.100.254",
"primary_ip": "192.168.100.2"
},
...........
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