Issue
My hosts configuration
[elasticsearch]
192.168.2.65 es_node_roles="master, data_hot, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform"
192.168.2.66 es_node_roles="master, data_hot, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform"
192.168.2.67 es_node_roles="master, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform"
192.168.2.77 es_node_roles="master, data_hot, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform"
My template:
aaaaa: '{% for i in elasticsearch_hosts_array %}{% if hostvars[i].es_node_roles | regex_search("data_hot") %}"{{i}}",{% endif %}{% endfor %}'
But the results is:
"192.168.2.65","192.168.2.66","192.168.2.77",
I want to get rid of the last comma, i.e.:
"192.168.2.65","192.168.2.66","192.168.2.77"
If I write it another way
{% for i in elasticsearch_hosts_array %}{% if loop.index0>0 %},{% endif %}{% if hostvars[i].es_node_roles | regex_search("data_hot") %}"{{i}}"{% endif %}{% endfor %}'
The results is:
"192.168.2.65","192.168.2.66",,"192.168.2.77"
Solution
If you want to use the Jinja template the playbook below
- hosts: all
vars:
a: |-
{% for i in ansible_play_hosts_all %}
{% if 'data_hot' in hostvars[i].es_node_roles %}
"{{ i }}"{%if not loop.last %},{% endif %}{% endif %}
{% endfor %}
tasks:
- debug:
var: a
run_once: true
gives
a: '"192.168.2.65","192.168.2.66","192.168.2.77"'
The next option is to create the list in a variable first. Use special variable ansible_play_hosts_all. When you run a playbook with - hosts: all
this variable will keep the list of all hosts
ansible_play_hosts_all: [192.168.2.65, 192.168.2.66, 192.168.2.67, 192.168.2.77]
Create a list of all instances of es_node_roles
nr_list: "{{ ansible_play_hosts_all|
map('extract', hostvars, 'es_node_roles')|
list }}"
gives
nr_list:
- master, data_hot, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform
- master, data_hot, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform
- master, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform
- master, data_hot, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform
Use this list and create a dictionary
nr_dict: "{{ dict(ansible_play_hosts_all|zip(nr_list)) }}"
gives
nr_dict:
192.168.2.65: master, data_hot, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform
192.168.2.66: master, data_hot, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform
192.168.2.67: master, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform
192.168.2.77: master, data_hot, data_content, data_warm, data_cold, data_frozen, ingest, ml, remote_cluster_client, transform
Now, you can use this dictionary and find hosts where the list contains data_hot
nodes_data_hot: "{{ nr_dict|dict2items|
selectattr('value', 'contains', 'data_hot')|
map(attribute='key')|
list }}"
gives
nodes_data_hot: [192.168.2.65, 192.168.2.66, 192.168.2.77]
Create a string with comma-separated items
a: "{{ nodes_data_hot|join(',') }}"
gives
a: 192.168.2.65,192.168.2.66,192.168.2.77
You can wrap the items with double-quotes
b: "{{ nodes_data_hot|map('regex_replace', b_regex, b_replace)|join(',') }}"
b_regex: '^(.*)$'
b_replace: '"\1"'
gives
b: '"192.168.2.65","192.168.2.66","192.168.2.77"'
Example of a complete playbook
- hosts: all
gather_facts: false
vars:
nr_list: "{{ ansible_play_hosts_all|
map('extract', hostvars, 'es_node_roles')|
list }}"
nr_dict: "{{ dict(ansible_play_hosts_all|zip(nr_list)) }}"
nodes_data_hot: "{{ nr_dict|dict2items|
selectattr('value', 'contains', 'data_hot')|
map(attribute='key')|
list }}"
a: "{{ nodes_data_hot|join(',') }}"
b: "{{ nodes_data_hot|map('regex_replace', b_regex, b_replace)|join(',') }}"
b_regex: '^(.*)$'
b_replace: '"\1"'
tasks:
- debug:
var: a
run_once: true
- debug:
var: b
run_once: true
Answered By - Vladimir Botka Answer Checked By - Marilyn (WPSolving Volunteer)