Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to concatenate with a string each element of a list in ansible

Tags:

ansible

jinja2

I've got a list of string element in a ansible var. I'm looking how to append to each element of the list with a defined string.

Do you know how I can do? I didn't find a way to do so.

Input:

[ "a", "b", "c" ]

Output:

[ "a-Z", "b-Z", "c-Z" ]
like image 888
Raoul Debaze Avatar asked Jun 08 '19 16:06

Raoul Debaze


5 Answers

You can use join for this. Please see the code below:

playbook -->

---
- hosts: localhost
  vars:
    input: [ "a", "b", "c" ]
  tasks:
    - name: debug
      set_fact:
        output: "{{ output | default([]) + ['-'.join((item,'Z'))] }}"
      loop: "{{ input | list}}"

    - debug:
        var: output

output -->

PLAY [localhost] ********************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************
ok: [localhost]

TASK [debug] ************************************************************************************************************
ok: [localhost] => (item=a)
ok: [localhost] => (item=b)
ok: [localhost] => (item=c)

TASK [debug] ************************************************************************************************************
ok: [localhost] => {
    "output": [
        "a-Z",
        "b-Z",
        "c-Z"
    ]
}

PLAY RECAP **************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0
like image 146
error404 Avatar answered Jan 04 '23 00:01

error404


With simple filters

    shell> cat filter_plugins/string_filters.py
    def string_prefix(prefix, s):
        return prefix + s
    def string_postfix(postfix, s):
        return s + postfix
    class FilterModule(object):
        ''' Ansible filters. Python string operations.'''
        def filters(self):
            return {
                'string_prefix' : string_prefix,
                'string_postfix' : string_postfix
            }

the tasks below

    - set_fact:
        output: "{{ input|map('string_prefix', '-Z')|list }}"
    - debug:
        var: output

give

    "output": [
        "a-Z", 
        "b-Z", 
        "c-Z"
    ]

The same output gives the loop below

    - set_fact:
        output: "{{ output|default([]) + [item + '-Z'] }}"
      loop: "{{ input }}"
    - debug:
        var: output
like image 39
Vladimir Botka Avatar answered Jan 03 '23 23:01

Vladimir Botka


I really didn't like using the add-on filters or the loop. However, I stumbled across this blog post https://www.itix.fr/blog/ansible-add-prefix-suffix-to-list/ that used a different method that worked in Ansible 2.9.x.

- set_fact:
    output: "{{ list_to_suffix | product(['-Z']) | map('join') | list }}"
like image 23
Doug Avatar answered Jan 04 '23 00:01

Doug


Below is how both prefix and suffix can be done in one line

  - debug:
    var: result
  vars:
    prefix: foo1
    suffix: foo2
    a_list: [ "bar", "bat", "baz" ]
    result: "{{ [prefix] | product(a_list) | map('join') | list | product([suffix]) | map('join') | list }}"
like image 43
MNA Avatar answered Jan 04 '23 01:01

MNA


Yet another solution, for pre-fixing and post-fixing, without custom filters (which make a very elegant code, by the way):

- set_fact:
    input: ['a', 'b', 'c']
    suffix: '-Z'
    prefix: 'A-'

- debug:
    var: suffixed
  vars:
    suffixed: "{{ input | zip_longest([], fillvalue=suffix) | map('join') | list }}"

- debug:
    var: prefixed
  vars:
    prefixed: "{{ [] | zip_longest(input, fillvalue=prefix) | map('join') | list }}"
    "suffixed": [
        "a-Z",
        "b-Z",
        "c-Z"
    ]

    "prefixed": [
        "A-a",
        "A-b",
        "A-c"
    ]
like image 24
fabio Avatar answered Jan 04 '23 01:01

fabio