Search code examples
pythonstringansibleslice

ansible get the last character of a fact


I would like to have the last character of a fact. My playbook looks like this:

- name: sf
  set_fact:
    root_dev: "{{ ansible_mounts|json_query('[?mount == `/`].device') }}"

- name: e
  debug:
    msg: "{{ root_dev[:-1] }}"

The problem is the output in this case always:

"msg": []

or if I use the playbook without semicolon:

  debug:
    msg: "{{ root_dev[-1] }}"

then the whole partition will be the output:

"msg": "/dev/sda1"

I also can't quote the whole root_dev because it is a fact and I would like to get the last character of it's value. The split filter also not working in this case, because the device can be /dev/sda or /dev/mapper/root_part_0 and so. What would be the best option in this case?


Solution

  • Explanation of the problem:

    You have to understand how the slicing works. Given the lists l1 and l2 for testing

      l1: [a]
      l2: [a, b, c]
    

    The index [-1] gives you the last item (which is also the first item)

      l1[-1]: a
    

    The slice [:-1] gives you all items but the last one. The result is an empty list because there is only one item

    l1[:-1]: []
    

    Test it by slicing l2

     l2[:-1]: [a, b]
    

    Solution:

    The value of root_dev is a list

      root_dev: "{{ ansible_mounts | json_query('[?mount == `/`].device') }}"
    

    In your case

      root_dev: ['/dev/sda1']
    

    To get the number of the partition, index the first item in the list and the last character in the item

      root_dev[0][-1]: 1
    

    • Example of a complete playbook for testing
    - hosts: localhost
    
      vars:
    
        root_dev: "{{ ansible_mounts | json_query('[?mount == `/`].device') }}"
    
      tasks:
    
        - setup:
            gather_subset: mounts
        # - debug:
        #     var: ansible_mounts
    
        - debug:
            var: root_dev
        - debug:
            var: root_dev[0][-1]
    

    • The above solution works for a single-digit partitions only. Use regex_replace to cover also multiple-digit options
      part_no: "{{ root_dev.0 | regex_replace('^(.+?)(\\d*)$', '\\2') }}"