1

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?

Community
  • 1
  • 1
Chris Tonkinson
  • 13,823
  • 14
  • 58
  • 90

1 Answers1

2

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 %}
r-m-n
  • 14,192
  • 4
  • 69
  • 68