Search code examples
ansiblejinja2template-engine

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?


Solution

  • 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 %}