'Ansible change all dict key values only by filters
I have an ansible dict like
ports:
webui: 7200
webadmin: 7209
core_api: 7201
stock_api: 7204
import_export: 7207
And i want to transform all keys in it, like
ports:
staging-webui: 7200
staging-webadmin: 7209
staging-core_api: 7201
staging-stock_api: 7204
staging-import_export: 7207
I do that in 'vars' section, so i can't use 'set_fact' with 'with_items' to iterate over dict. Is it possible to it only by filters?
I found working answer,
env: staging # comes from outside
regex_env: "\"key\": \"{{ env }}-\\1\""
app_upstreams: "{{ ports | dict2items | map('to_json') | map('regex_replace', '\"key\":\\s\"(.*)\"', lookup('vars', 'regex_env')) | map('from_json') }}"
but it looks really ugly, is there more good-looking solution?
Solution 1:[1]
For example, the playbook below
- hosts: localhost
vars:
env: staging_
ports:
webui: 7200
webadmin: 7209
core_api: 7201
stock_api: 7204
import_export: 7207
env_ports_keys: "{{ [env]|product(ports.keys()|list)|map('join') }}"
env_ports_vals: "{{ ports.values()|list }}"
env_ports: "{{ dict(env_ports_keys|zip(env_ports_vals)) }}"
tasks:
- debug:
var: env_ports
gives (abridged)
env_ports:
staging_core_api: 7201
staging_import_export: 7207
staging_stock_api: 7204
staging_webadmin: 7209
staging_webui: 7200
To simplify the code, you can create a custom filter
shell> cat filter_plugins/dict_utils.py
def prefix_key(d, prefix='prefix'):
temp = {}
for key in d.keys():
temp[prefix + key] = d[key]
return temp
class FilterModule(object):
''' utility filters for operating on dictionary '''
def filters(self):
return {
'prefix_key': prefix_key,
}
The playbook below gives the same result
- hosts: localhost
vars:
env: staging_
ports:
webui: 7200
webadmin: 7209
core_api: 7201
stock_api: 7204
import_export: 7207
env_ports: "{{ ports|prefix_key(prefix=env) }}"
tasks:
- debug:
var: env_ports
Solution 2:[2]
I was just trying to solve this issue for myself. I came up with a solution that does not require the use of a filter plugin or a jinja template. Just pure ansible playbook tasks. I did this on the newest version of Ansible, so I can not confirm it will work on older versions.
It works by creating a second dictionary that has the renamed keys and then overwriting the original dictionary with the renamed one. Here is a complete playbook you can run as a proof of concept.
---
- hosts: localhost
connection: local
vars:
prefix: staging
ports:
webui: 7200
webadmin: 7209
core_api: 7201
stock_api: 7204
import_export: 7207
renamed_ports: {}
tasks:
- name: set renamed ports
ansible.builtin.set_fact:
renamed_ports: "{{ renamed_ports | combine({ prefix + '-' + item.key: item.value }) }}"
with_dict: "{{ ports }}"
- name: rewrite original ports
ansible.builtin.set_fact:
ports: "{{ renamed_ports }}"
- name: erase renamed ports if you want to
ansible.builtin.set_fact:
renamed_ports:
- name: print ports
ansible.builtin.debug:
var: ports
...
Here is the output of the print ports task:
TASK [print ports] ****************************************************************************
ok: [localhost] => {
"ports": {
"staging-core_api": 7201,
"staging-import_export": 7207,
"staging-stock_api": 7204,
"staging-webadmin": 7209,
"staging-webui": 7200
}
}
Solution 3:[3]
You can achieve this using jinja2 template module and create a yml file with all the variables.
playbook -->
---
- hosts: localhost
vars:
ports:
webui: 7200
webadmin: 7209
core_api: 7201
stock_api: 7204
import_export: 7207
tasks:
- name: debug module
debug:
var: "{{ item }}"
with_items:
- ports
- name: template
template:
src: templates/template.yml
dest: templates/dest.yml
jinja2 template -->
ports:
{% for key, value in ports.iteritems() %}
staging-{{ key }}: {{ value }}
{% endfor %}
output -->
ports:
staging-core_api: 7201
staging-import_export: 7207
staging-stock_api: 7204
staging-webui: 7200
staging-webadmin: 7209
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Apreche |
Solution 3 | error404 |