medisamm
medisamm

Reputation: 331

Filter data using JSON query in Ansible to extract data from an ansible_fact

I have created this playbook to extract all mount points starting with any element in the variable whitelist matching the type= ext2, ext3, ext4.

The problem is that I can get all mount_points but I am not able to filter the result with the variables.

- hosts: all
  gather_facts: True
  become: True
  vars:
     whitelist:
         - /boot
         - /home
         - /opt
         - /var
         - /bin
         - /usr

  tasks:
  - name: extract mount_points 
    set_fact:
      mount_point: "{{ansible_facts.mounts | selectattr('fstype', 'in', ['ext2', 'ext3', 'ext4']) | map(attribute='mount') | list }}"

  - debug:
      var: mount_point
    vars:
      query: "[?starts_with(mount, whitelist)].mount"

When I execute the playbook I get this

ok: [ansible@controller] => {
    "mount_point": [
        "/", 
        "/boot", 
        "/tmp", 
        "/home", 
        "/var", 
        "/var/opt", 
        "/var/tmp", 
        "/var/log", 
        "/var/log/audit", 
        "/opt", 
    ]
}

/tmp is included which means that query: "[?starts_with(mount, whitelist)].mount" was skipped and I don't know how to achieve the playbook goal.

Upvotes: 2

Views: 1232

Answers (2)

medisamm
medisamm

Reputation: 331

While testing i used a filter expression within the json_query string which achieved the same goal for me Query String with Dynamic Variable . In this example the filter expression is used with a built-in function, ?starts_with. This function provides a boolean result, based on a match with a search string, on any element within the fstype and mount_point using a dynamic variable {{whitelist}}.

- name: find mount_points
  debug:
    msg: "{{ ansible_mounts | to_json | from_json | json_query(mount_point) }}"
  vars:
      mount_point: " @[?starts_with(fstype, 'ext')] | @[?starts_with(mount, '{{item}}')].mount"
  loop: "{{whitelist}}"

this is the output

ok: [ansible@ansible1] => (item=/var) => {
    "msg": [
        "/var", 
        "/var/opt", 
        "/var/tmp", 
        "/var/log", 
        "/var/log/audit"
}
ok: [ansible@ansible1] => (item=/usr) => {
    "msg": []
}
ok: [ansible@ansible1] => (item=/home) => {
    "msg": [
        "/home"
>>>

Upvotes: 0

Zeitounator
Zeitounator

Reputation: 44615

You don't really need a json query here IMO. An easy way is to filter the list with match and construct a regex containing all possible prefixes:

- name: show my filtered mountpoints:
  vars:
    start_regex: "{{ whitelist | map('regex_escape') | join('|') }}"
  degug:
    msg: "{{ {{ansible_facts.mounts | selectattr('fstype', 'in', ['ext2', 'ext3', 'ext4'])
          | map(attribute='mount') | select('match', start_regex) | list }}"
   

Upvotes: 3

Related Questions