Home > Net >  How to trim last character when using ansible jinja2 loop
How to trim last character when using ansible jinja2 loop

Time:07-25

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"

CodePudding user response:

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
  • Related