Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 634
tenpn Avatar asked Mar 09 '17 14:03

tenpn


People also ask

What is the main advantage purpose of using Jinja2 templates within Ansible?

Ansible uses Jinja2 templating to enable dynamic expressions and access to variables and facts. You can use templating with the template module.

What is Jinja2 templating in Ansible?

Jinja2 templates are simple template files that store variables that can change from time to time. When Playbooks are executed, these variables get replaced by actual values defined in Ansible Playbooks. This way, templating offers an efficient and flexible solution to create or alter configuration file with ease.

What is pipe in Jinja2?

Jinja2 filter is something we use to transform data held in variables. We apply filters by placing pipe symbol | after the variable followed by name of the filter. Filters can change the look and format of the source data, or even generate new data derived from the input values.


1 Answers

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 %}
like image 169
SztupY Avatar answered Oct 16 '22 05:10

SztupY