27

An array is generated in Ansible from shell command output, it is similar to below:

foo: [value0, value1, value2, value3]

Now depending on output of the shell command, the number of elements of foo may vary.

I then generate a jinja2 template to show :

foo[0] will return value0
foo[1] will return value1
...

How would I determine how many elements are stored in foo?

2 Answers 2

46
Number_of_elements: "{{ foo|length }}"
1
  • For anyone who doesn't know, beware that storing it to a variable (using set_fact and jinja2 template) will implicitly convert it to a string. So the next time you want to use the variable, you will need to convert it to an integer first, for example when: "Number_of_elements | int >2". Up to the current version, you won't be able to store integers using set_fact, unless you hardcode the integer
    – Hzz
    Feb 15 at 8:30
1

Just to expand on Vladimir Botka's response, you really need to check to make sure your item is a list (or a dictionary) first! It's very easy to make a mistake around type checking, as this can be a very easy slip-up to make.

Just to prove this, here's a sample playbook:

---
- hosts: localhost
  gather_facts: false
  vars:
    a_string: abcd1234
    a_list: ['a', 'short', 'list']
    a_dict: {'a': 'dictionary', 'with': 'values'}
  tasks:
  - debug:
      msg: |
        [
          "a_string length: {{ a_string | length }}",
          "a_list length: {{ a_list | length }}",
          "a_dict length: {{ a_dict | length }}"
        ]

And the result:

PLAY [localhost] ******************************************************************************************************************************

TASK [debug] **********************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "a_string length: 8",
        "a_list length: 3",
        "a_dict length: 2"
    ]
}

PLAY RECAP ************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

So, how can we confirm that this is, in fact, a list before we want to check the number of elements?

Like this:

{% if my_value is string %}
  1
{% elif my_value is iterable %}
  {{ my_value | length }}
{% endif %}

We have to check if it's a string first as strings are also iterable, whereas dictionaries (mapping) and lists (sequences) are not strings. Integers and Floats don't have a "length" property, so perhaps you should check for that first too (using if my_value is number)?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .