TJ Zimmerman
TJ Zimmerman

Reputation: 3484

Add new line to template for each item in a list

Given the following example list and Jinja template:

List:

list:
    - foo
    - bar

Jinja template:

{% for key in list %}
results:
      - "{{ key }}"
{% endfor %}

I am able to produce the following output:

results:
    - foo
results:
    - bar

How can I instead append a line, for each item in the list, to the template to produce this result?

results:
    - foo
    - bar

Is this possible with Ansible without using something like lineinfile? I am moreorless trying to replicate the Helm range filter which might look like this:

results:
    {{- range .Values.list }}
    - {{ . }}
    {{- end }}

The join filter appears to get me a little closer. For example:

results:
    - "{{ list | join('\n- ') }}"

Produces the following. But it is not syntactically correct yet:

results:
    - "foo
- bar"

Upvotes: 2

Views: 3799

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 68034

Given the list

list:
    - foo
    - bar

Q: "Produce this result!"

results:
    - foo
    - bar

A: There are more options:

  1. You can iterate the list
    - copy:
        dest: /tmp/test.yml
        content: |
          results:
          {% for key in list %}
              - {{ key }}
          {% endfor %}

gives

shell> cat /tmp/test.yml 
results:
    - foo
    - bar

You can put the template into a file

shell> cat templates/test.yml.j2
results:
{% for key in list %}
    - {{ key }}
{% endfor %}

Then, the template module gives the same result

    - template:
        dest: /tmp/test.yml
        src: test.yml.j2

  1. The next option is Ansible formatting filters and Jinja indent filter. The task below gives the same result
    - copy:
        dest: /tmp/test.yml
        content: |
          results:
              {{ list|to_nice_yaml|indent(4) }}
  1. You can use tab if you want to
    - copy:
        dest: /tmp/test.yml
        content: |
          results:
          {% for key in list %}
          {{ '{}- {}'.format(tab, key) }}
          {% endfor %}
      vars:
        tab: "{{ '\t' }}"

The tab spacing will depend on the pager

shell> cat /tmp/test.yml 
results:
    - foo
    - bar

Upvotes: 3

TJ Zimmerman
TJ Zimmerman

Reputation: 3484

It's ugly, but I got it using the join filter and some escape sequences. This:

results:
    - "{{ list | join('\"\n    - \"') }}"

Produces the following:

results:
    - "foo"
    - "bar"

Dismantling that for clarity for the future Googlers....

list | join('') - Retrieve the variablized list and "join" them using the following delimiter sequence, which effectively introduces list items in a roundabout way

\" - Add a " character to the end of the item

\n - Add a newline and tab in 4 spaces. See footnote for more info.

- \" - Add a new - " before adding each consecutive list item.

Not sure if it is possible to implement this without wrapping each templated list item in quotes or not. But that is syntactically correct so I will leave it.

Footnote: If you use \t instead of adding whitespace characters, Ansible will throw the following error:

MSG:

Error loading resource_definition: while scanning for the next token found character '\t' that cannot start any token

Upvotes: 0

Related Questions