Search code examples
ansible

Checking the first digit in a number in ansible playbook


I have an ansible playbook that reads in a vars_file containing usernames and uids

users:
  - name: josh
    uid: 1201
  - name: peter
    uid: 1202
  - name: paul
    uid: 2101
  - name: ryan
    uid: 2102

I have two host groups in my inventory file, db and web. I want users to be created in db if their uid starts with a 1, and web if it starts with 2.

My playbook so far looks like this

---
- name: users playbook
  hosts: all
  become: yes

  vars_files:
    - vars/user_list.yml

  tasks:

  - name: test debug
    debug:
      msg: "{{ item.username }}, {{ item.uid }}"
    loop: "{{ users }}"
    when: '{{ item.uid[0] }} == 1'

But my when conditional throws the error

The error was: error while evaluating conditional ({{ item.uid[0] }} == 1)

Is there a better way of doing this for both conditionals?


Solution

  • Several problems.

    First, you are not comparing anything. In the expression '{{ item.uid[0] }} == 1' the last part (i.e. == 1) will be literally treated as a string and written as output. If used in a full jinja2 expression, the comparison must be inside the markers: {{ item.uid[0] == 1 }}

    Second, when clauses should not contain any jinja2 markers to expand variables. This is also the case for failed_when and changed_when. See the conditionals doc

    Lastly, getting the character with an index will only work if the input is a string and not an int. So you first need to make sure or that by casting it correctly with the string filter. The char you will then get will be itself a string. Comparing it to an integer will always return false. So you either have to write the comparison value as a string (i.e. '1') or cast the extracted char to an integer with the int filter.

    This is how I would fix your task:

      - name: test debug
        debug:
          msg: "{{ item.username }}, {{ item.uid }}"
        loop: "{{ users }}"
        when: (item.uid | string)[0] | int == 1