I've used includ_vars
for importing a file which includes some variables as follows:
my_vars:
- { name: "a", surname: "b", status: "c"}
- { name: "d", surname: "e", status: "f"}
- { name: "g", surname: "h", status: "i"}
I'm going to create a new dynamic list by my_vars
and use it in get_url
task:
- { url: "http://company.com/a/b/c.txt"}
- { url: "http://company.com/d/e/f.txt"}
- { url: "http://company.com/g/h/i.txt"}
- name: "include my_vars"
include_vars:
file: "../myvars.yml"
- name: "create new URL list"
set_fact:
new_list: "- {url: "http://"http://company.com/{{ my_vars.name }}/{{ my_vars.surname }}/{{ my_vars.status }}.txt
with_items: {{ my_vars }}
- name: "get desired url"
get_url:
url: {{ item.url }}
dest: /tmp/
loop: {{ new_list }}
But it doesn't work. How can I create this new iterative list by existing variables for using in other steps?
Join the values
my_vals: "{{ my_vars|json_query('[].[name, surname, status]')|
map('join', '/')|
list }}"
gives the list of the fragments
my_vals:
- a/b/c
- d/e/f
- g/h/i
Use the filter product to combine the fragments. Flatten and join the lists
my_urls: "{{ ['http://company.com/']|product(my_vals)|
product(['.txt'])|
map('flatten')|
map('join')|
list }}"
gives
my_urls:
- http://company.com/a/b/c.txt
- http://company.com/d/e/f.txt
- http://company.com/g/h/i.txt
Use the filter community.general.dict_kv if you need the list of the dictionaries
my_urls_dict: "{{ my_urls|map('community.general.dict_kv', 'url')|
list }}"
gives
my_urls_dict:
- {url: 'http://company.com/a/b/c.txt'}
- {url: 'http://company.com/d/e/f.txt'}
- {url: 'http://company.com/g/h/i.txt'}
Example of a complete playbook
- hosts: localhost
vars:
my_vars:
- {name: "a", surname: "b", status: "c"}
- {name: "d", surname: "e", status: "f"}
- {name: "g", surname: "h", status: "i"}
my_vals: "{{ my_vars|json_query('[].[name, surname, status]')|
map('join', '/')|
list }}"
my_urls: "{{ ['http://company.com/']|product(my_vals)|
product(['.txt'])|
map('flatten')|
map('join')|
list }}"
my_urls_dict: "{{ my_urls|map('community.general.dict_kv', 'url')|
list }}"
tasks:
- debug:
var: my_urls
- debug:
var: my_urls_dict
Q: "How can I create a loop on objects with status: 'f'
?"
A: Select the item. For example,
- debug:
var: item
loop: "{{ my_vars|selectattr('status', 'eq', 'f') }}"
gives
TASK [debug] ************************************************************
ok: [localhost] => (item={'name': 'd', 'surname': 'e', 'status': 'f'}) =>
ansible_loop_var: item
item:
name: d
status: f
surname: e
But this answer seems to be too obvious. You're probably asking how to select such an item when the url is created. There are many options:
my_urls_dict: "{{ my_urls|map('community.general.dict_kv', 'url')|
zip(my_vars)|
map('combine')|
list }}"
gives
my_urls_dict:
- {name: a, status: c, surname: b, url: 'http://company.com/a/b/c.txt'}
- {name: d, status: f, surname: e, url: 'http://company.com/d/e/f.txt'}
- {name: g, status: i, surname: h, url: 'http://company.com/g/h/i.txt'}
Then, the iteration is as trivial as before.
- debug:
var: item
loop: "{{ my_urls_dict|selectattr('status', 'eq', 'f') }}"
- debug:
var: item
with_together:
- "{{ my_vars }}"
- "{{ my_urls }}"
when: item.0.status == 'f'
- debug:
var: url
loop: "{{ my_vars|selectattr('status', 'eq', 'f') }}"
vars:
url: "http://company.com/{{ item.name }}/{{ item.surname }}/{{ item.status }}.txt"