In Ansible. This might be a bit of a challenge. I have this variable:
nodes:
- name: fin
hosts: 2
- name: swe
hosts: 1
And from this I would like a fact like this:
fin:
- name: fin1
- name: fin2
swe:
- name: swe1
Is this possible?
There are multiple solutions. I'll give two which are the easiest and most legible and maintainable in my opinion.
This is my preferred one as using python to transform the data gives much more possibilities. I just crafted one which fulfills your above requirement. Meanwhile note it is not production ready as you should add input data validation and exception handling. But this will give you the global idea.
Create a filter_plugins/my_node_plugins.py
file adjacent to you playbook:
def transform_my_nodes(nodes):
transformed_nodes = {}
for node in nodes:
node_list = []
for node_number in range(1, node["hosts"] + 1):
node_list.append({"name": f"{node['name']}{node_number}"})
transformed_nodes[node["name"]] = node_list
return transformed_nodes
class FilterModule(object):
def filters(self):
return {
'transform_my_nodes': transform_my_nodes,
}
Then the following playbook:
- hosts: localhost
gather_facts: false
vars:
nodes:
- name: fin
hosts: 2
- name: swe
hosts: 1
tasks:
- name: Transform data with a custom filter
debug:
var: nodes | transform_my_nodes
gives:
$ ansible-playbook transform_with_filter.yml
PLAY [localhost] *********************************************************************************************************************************************************************************************************************
TASK [Transform data with a custom filter] *******************************************************************************************************************************************************************************************
ok: [localhost] => {
"nodes | transform_my_nodes": {
"fin": [
{
"name": "fin1"
},
{
"name": "fin2"
}
],
"swe": [
{
"name": "swe1"
}
]
}
}
PLAY RECAP ***************************************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Create a templates/transform_nodes.j2
file adjacent to your playbook:
{% for node in nodes %}
{{ node.name }}:
{% for node_number in range(1, node.hosts + 1) %}
- name: {{ node.name }}{{ node_number }}
{% endfor %}
{% endfor %}
Then the following playbook:
- hosts: localhost
gather_facts: false
vars:
nodes:
- name: fin
hosts: 2
- name: swe
hosts: 1
tasks:
- name: Transform data with a template
debug:
var: lookup('template', 'transform_nodes.j2') | from_yaml
gives:
$ ansible-playbook transform_with_template.yml
PLAY [localhost] *********************************************************************************************************************************************************************************************************************
TASK [Transform data with a template] ************************************************************************************************************************************************************************************************
ok: [localhost] => {
"lookup('template', 'transform_nodes.j2') | from_yaml": {
"fin": [
{
"name": "fin1"
},
{
"name": "fin2"
}
],
"swe": [
{
"name": "swe1"
}
]
}
}
PLAY RECAP ***************************************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0