Ansible - negate Filter

14.3k Views Asked by At

I find some files with the find ansible module

- find:
    paths: "/"
    patterns: ["*.service"]
    file_type: file
    hidden: True
    recurse: yes
  register: find_results
  when: ansible_service_mgr == "systemd"

Now I want to check modify the Permissions on some of the files:

- file:
    path: "{{ item.path }}"
    owner: root
    group: root
    mode: 0644
  with_items:
    - "{{ find_results.files }}"
  when:
    - item.path | match("/sys/devices/power/events/*")
    - ansible_service_mgr == "systemd"

The Problem is that I don't want a match. I want everything that don't match that path?

How can I negate the match filter? (!, not, etc.)?

3

There are 3 best solutions below

0
On

I'd recommend to rewrite your task as follows:

- file:
    path: "{{ item.path }}"
    owner: root
    group: root
    mode: 0644
  with_items: "{{ [] if ansible_service_mgr != 'systemd' else find_results.files | rejectattr('path','match','/sys/devices/power/events/.*') | list }}"
  1. It uses rejectattr to reject (eliminate) all items from find_results.files that match /sys/devices/power/events/.* regexp. A kind of match negation you wanted.

  2. It makes a loop only with required items. Your task will make a loop with all found files and generate "skipped" message for each when statement miss.

  3. Also it feeds empty list [] to with_items when service managed is not systemd. Otherwise your task may either generate multiple skipped items for each find_results.files item, or fail altogether because previous task was skipped and has find_results.files undefined.

P.S. If you have many tasks that depend on systemd, you may want to separate them into different yaml fils and conditionally include it only on systemd machines – this will make code much cleaner without those multiple when: ansible_service_mgr == "systemd" statements.

0
On

can you try

when: ("/sys/devices/power/events/*" not in item.path "/sys/devices/power/events/")  and
      (ansible_service_mgr == "systemd")

But the second condition is useless because you already set the condition when getting the find_results

1
On

Thx for your help you can also do something like:

not (item.path | match("/sys/devices/power/events/*"))