I have a list of dicts:
vars:
sites:
- name: "Tampa"
site_number: 0
- name: "Miami"
site_number: 1
- name: "Daytona"
site_number: 2
I want to add an entry to every dict in this list, but multiply it by a value. I have tried the following:
- set_fact:
sites: >-
{{
sites | map('combine', {
'site_subnet': '172.16.0.' + (item.site_number*8)|string + '/29',
'test1': item.site_number
}) | list
}}
loop: "{{ sites }}"
- debug: var=sites
Now, the resultant output shows that sites[n].test1
is always 2, and of course, the site_subnet
is always 172.16.0.16/29. What is the malfunction with my code?
Ansible is generally not a great tool for modifying data structures. You can get what you want by creating a new variable, like this:
- hosts: localhost
gather_facts: false
vars:
sites:
- name: "Tampa"
site_number: 0
- name: "Miami"
site_number: 1
- name: "Daytona"
site_number: 2
tasks:
- set_fact:
new_sites: >-
{{
new_sites + [item | combine({
'site_subnet': '172.16.0.' ~ (item.site_number*8) ~ '/29',
'test1': item.site_number
})]
}}
loop: "{{ sites }}"
vars:
new_sites: []
- debug:
var: new_sites
This results in the following output (which is what I think you want):
TASK [debug] *************************************************************************************************************************************************************
ok: [localhost] => {
"new_sites": [
{
"name": "Tampa",
"site_number": 0,
"site_subnet": "172.16.0.0/29",
"test1": 0
},
{
"name": "Miami",
"site_number": 1,
"site_subnet": "172.16.0.8/29",
"test1": 1
},
{
"name": "Daytona",
"site_number": 2,
"site_subnet": "172.16.0.16/29",
"test1": 2
}
]
}
For any sort of complex logic, I always find it more managable to use a custom filter instead. I would drop the following into filter_plugins/filters.py
:
def filter_update_sites(sites):
return [
site | {
"site_subnet": f"172.16.0.{site['site_number']*8}/29"
}
for site in sites
]
class FilterModule:
def filters(self):
return {
"update_sites": filter_update_sites,
}
And then write the playbook like this:
- hosts: localhost
gather_facts: false
vars:
sites:
- name: "Tampa"
site_number: 0
- name: "Miami"
site_number: 1
- name: "Daytona"
site_number: 2
tasks:
- set_fact:
new_sites: "{{ sites | update_sites }}"
- debug:
var: new_sites
Which produces:
TASK [debug] *************************************************************************************************************************************************************
ok: [localhost] => {
"new_sites": [
{
"name": "Tampa",
"site_number": 0,
"site_subnet": "172.16.0.0/29"
},
{
"name": "Miami",
"site_number": 1,
"site_subnet": "172.16.0.8/29"
},
{
"name": "Daytona",
"site_number": 2,
"site_subnet": "172.16.0.16/29"
}
]
}