Chris Tonkinson
Chris Tonkinson

Reputation: 14459

Jinja conditional clause dependent on data type

I'm using SaltStack to manage BIND9 zone files. Previously I have used pillar data like this:

zones:
  example.com:
    a:
      www1: 1.2.3.4
      www2: 1.2.3.5

along with a jinja templated file (indented just for readability) like this:

{% if info.a is defined %}
  {% for host, defn in info.a.items() %}
    {{ host }}  IN  A  {{ defn }}
  {% endfor %}
{% endif %}

where info is a context variable (the dict at zones.example.com).

Now, I need to be able to define multiple IPs per A record. In the previous example, suppose I wanted to round-robin the subdomain www:

zones:
  example.com:
    a:
      www1: 1.2.3.4
      www2: 1.2.3.5
      www:
        - 1.2.3.4
        - 1.2.3.5

That requires - in the Jinja template - to know the difference between defn being a scalar value (representing a single IP address) or a list (representing a collection of IP addresses). Something like:

    {% for host, defn in info.a.items() %}
      {% if DEFN_IS_A_LIST_OBJECT %}
        {% for ip in defn %}
          {{ host }} IN A {{ ip }}
        {% endfor %}
      {% else %}
        {{ host }} IN A {{ defn }}
      {% endif %}
    {% endfor %}

From this thread I tried if isinstance(defn, list) but I get:

Unable to manage file: Jinja variable 'isinstance' is undefined

I also tried if len(defn) but realized length() will respond Truthy to strings as well as lists. It is also reported as an error though:

Unable to manage file: Jinja variable 'len' is undefined

How can I distinguish between a list and a string in Jinja?

Upvotes: 1

Views: 802

Answers (1)

r-m-n
r-m-n

Reputation: 15090

If the value can only be a string or a list, you can just check that this is not a string with builtin test

{% if defn is not string %}
    {% for ip in defn %}
        {{ host }} IN A {{ ip }}
    {% endfor %}
{% else %}

Upvotes: 2

Related Questions