Search code examples
ansiblejinja2

jinja template adds extra line when if condition is not satisfied


A for loop in my jinja template is like this

{% for m in grp %}
abc {{ m.length }}
      pqr
      xyz
{% if m.flag is defined and m.flag == "f" %}
      yes f {% endif %}    
{% for r in uv %}
      abcdef
{% endfor %}

{% endfor %} 

Now the problem is in some members of grp don't have the flag variable. Wherever flag is present, the option true line is getting added properly. But when if condition is not satisfied, it just adds one blank line. These 4 or 5 lines are supposed to be without extra blank lines otherwise the generated config file gets marked as invalid. Can anyone please help me with this?


Solution

  • Q: A blank line is added if the condition is not satisfied.

    A: See Whitespace Control. Quoting:

    If you add a minus sign (-) to the start or end of a block (e.g. a For tag), a comment, or a variable expression, the whitespaces before or after that block will be removed.

    The template below does what you want

    {% if m.flag is defined and m.flag == "f" %}
        yes f
    {% endif -%}
    

    For example, given the data

        grp:
          - {length: 1, flag: x}
          - {length: 2}
          - {length: 3, flag: f}
          - {length: 4, flag: f}
    
    • The simplified template from your question
        {% for m in grp %}
            {{ m.length }}
            xyz
        {% if m.flag is defined and m.flag == "f" %}
            yes f {% endif %}    
        {% endfor %}
    

    adds the blank lines

            1
            xyz
      
            2
            xyz
      
            3
            xyz
            yes f
            4
            xyz
            yes f
    
    • If you use the minus sign
        {% for m in grp %}
            {{ m.length }}
            xyz
        {% if m.flag is defined and m.flag == "f" %}
            yes f
        {% endif -%}    
        {% endfor %}
    

    there are no blank lines

            1
            xyz
            2
            xyz
            3
            xyz
            yes f
            4
            xyz
            yes f
    
    • The condition can be simplified. The template below gives the same result
        {% for m in grp %}
            {{ m.length }}
            xyz
        {% if m.flag|default('') == "f" %}
            yes f
        {% endif -%}    
        {% endfor %}
    

    Example of a complete playbook for testing

    - hosts: localhost
    
      vars:
    
        grp:
          - {length: 1, flag: x}
          - {length: 2}
          - {length: 3, flag: f}
          - {length: 4, flag: f}
    
      tasks:
    
        - debug:
            msg: |
              {% for m in grp %}
                  {{ m.length }}
                  xyz
              {% if m.flag is defined and m.flag == "f" %}
                  yes f {% endif %}    
              {% endfor %}
          tags: t1
    
        - debug:
            msg: |
              {% for m in grp %}
                  {{ m.length }}
                  xyz
              {% if m.flag is defined and m.flag == "f" %}
                  yes f
              {% endif -%}    
              {% endfor %}
          tags: t2
    
        - debug:
            msg: |
              {% for m in grp %}
                  {{ m.length }}
                  xyz
              {% if m.flag|d('') == "f" %}
                  yes f
              {% endif -%}    
              {% endfor %}
          tags: t3