tenpn
tenpn

Reputation: 4706

Complex string concatenation in jinja/ansible template

I have an ansible dict that looks like this:

servers:
  - name: foo
    port: 1000
  - name: bar
    port: 2000

I want an ansible/jinja2 template to ouput this:

result=pre-foo-1000,pre-bar-1000

So far I've got something like:

result={{ servers | json_query('[*].name') | join(',') }}

but that only outputs:

result=foo,bar

I've tried something like json_query('[*].name-[*].port') with no success - it gives errors about invalid - literal. I can't find a lot of docs on json_query but is there more I can do there? Or a better option to slide into the filter?

Upvotes: 9

Views: 9846

Answers (1)

SztupY
SztupY

Reputation: 10526

You could do a plain loop first, then collect the results:

- hosts: all
  connection: local
  vars:
    servers:
      - name: foo
        port: 1000
      - name: bar
        port: 2000
  tasks:
    - set_fact:
        result_item: '{{ item.name }}-{{ item.port }}'
      with_items:
        - '{{ servers }}'
      register: result_list

    - set_fact:
        result: '{{ result_list.results | map(attribute="ansible_facts.result_item") | join(",") }}'

    - debug:
        var: result

Alternatively try some inline jinja loops:

- hosts: all
  connection: local
  vars:
    servers:
      - name: foo
        port: 1000
      - name: bar
        port: 2000
  tasks:
    - set_fact:
        result: "{% for item in servers %}{{item.name}}-{{item.port}}{{ '' if loop.last else ',' }}{% endfor %}"

    - debug:
        var: result

This should also work from within a template file:

result={% for item in servers %}{{item.name}}-{{item.port}}{{ '' if loop.last else ',' }}{% endfor %}

Upvotes: 11

Related Questions