18

I merged two lists from an Ansible inventory:

set_fact:
  fact1: "{{ groups['group1'] + groups[group2']|list }}

The output is:

fact1:
  - server01
  - server02
  - server03

With the above results, I need to append https:// to the front, and a port number to the back of each element. Then I need to convert it to a comma delimited list for a server config.

In this example I want: https://server01:8000,https://server02:8000,https://server03:8000.

I tried using a join:

set_fact:
  fact2: "{{ fact1|join(':8000,') }}"

which partly worked but it left the last server without a port.

How can I achieve my goal?

techraf
  • 64,883
  • 27
  • 193
  • 198
Adam S
  • 183
  • 1
  • 1
  • 5

3 Answers3

30

Solution

set_fact:
  fact2: "{{ fact1 | map('regex_replace', '(.*)', 'https://\\1:8000') | join(',') }}"

Explanation

  1. map filter applies a filter (regex_replace) to individual elements of the list;

  2. regex_replace filter (with the following regular expression) adds a prefix and suffix to a string;

    current_list | map('regex_replace', '(.*)', 'prefix\\1suffix')
    
  3. join filter converts the list to comma-delimited string in the output.


Alternative

Another possible solution (builds on what you already know) would be to use Jinja2 to directly for the target string:

set_fact:
  fact2: "{{ 'https://' + fact1|join(':8000,https://') + ':8000' }}"
techraf
  • 64,883
  • 27
  • 193
  • 198
  • 9
    Beware that on some Python versions, `(.*)`will match the whole string and an empty string at the end, which means it will make two replacements: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#regular-expression-filters. We should use `^(.*)$` instead. – Merwan Jan 17 '20 at 18:25
  • Excuse me, but shouldn't that be `\1` instead of `\\1` there? – Volodymyr Melnyk Oct 05 '22 at 21:24
5

Also you can use ternary filter:

set_fact:
  fact2: "{% for it in fact1 %}https://{{ it }}:8000{{ loop.last | ternary('', ',') }}{% endfor %}"
bav
  • 1,543
  • 13
  • 13
0

i have this list of inventory i want to do like this ['servers'] server01 server02 server03 server04 in this example I want: https://server01:8000;https://server02:8000],https://server03:8000;https://server04:8000]

ahmed
  • 39
  • 7