regexansible

Ansible reject with search/regex


I try to manipulate the ouptut of following powershell command:

Get-CimInstance -ClassName Win32_UserProfile | Select-Object -ExpandProperty LocalPath

Which could look like this:

[
  "C:\\Users\\LocalUser",
  "C:\\Users\\LocalUser.001",
  "C:\\Users\\Admin",
  "C:\\Windows\\ServiceProfiles\\NetworkService",
  "C:\\Windows\\ServiceProfiles\\LocalService",
  "C:\\Windows\\system32\\config\\systemprofile"
]

My goal is to reject the profiles, like Admin and them under Windows path.

My approach so far looks like this:

- hosts: windows10
  gather_facts: false

  tasks:
    - name: Get a list of all user profiles
      ansible.windows.win_powershell:
        script: |
          Get-CimInstance -ClassName Win32_UserProfile |
          Select-Object -ExpandProperty LocalPath
      register: all_user_profiles
      changed_when: false

    - name: Filter profiles for deletion
      set_fact:
        profiles_to_delete: >-
          {{ all_user_profiles.output |
             reject('search', '\\\\Users\\\\(' + (keep_users | join("|")) + ')') |
             list }}
      vars:
        keep_users:
          - Admin
      

    - debug:
        var: profiles_to_delete

The Expected result from the last debug:

[
  "C:\\Users\\LocalUser",
  "C:\\Users\\LocalUser.001",
  "C:\\Windows\\ServiceProfiles\\NetworkService",
  "C:\\Windows\\ServiceProfiles\\LocalService",
  "C:\\Windows\\system32\\config\\systemprofile"
]

But instead it still includes the Admin line, from above.

I tested also the following based on @β.εηοιτ.βε gist from the comments:

- hosts: localhost
  gather_facts: false

  tasks:
    - name: Filter profiles for deletion
      set_fact:
        profiles_to_delete: >-
          {{ all_user_profiles.output |
             reject('search', '\\\\Users\\\\(' + (keep_users | join("|")) + ')') |
             list }}
      vars:
        keep_users:
          - Admin
        all_user_profiles:
          output:
            - C:\\Users\\LocalUser
            - C:\\Users\\LocalUser.001
            - C:\\Users\\Admin
            - C:\\Windows\\ServiceProfiles\\NetworkService
            - C:\\Windows\\ServiceProfiles\\LocalService
            - C:\\Windows\\system32\\config\\systemprofile

    - debug:
        var: profiles_to_delete

And here it works fine as expected.

So I compared the two lists and came to the conclusion, that the issue is originating from the difference, that the content of the shell output is quoted and the content of the hardcoded variable is not.

As soon as I update the hardcoded variable, I get the same unwanted result as my MWE creates:

all_user_profiles:
  output:
    - "C:\\Users\\LocalUser"
    - "C:\\Users\\LocalUser.001"
    - "C:\\Users\\Admin"
    - "C:\\Windows\\ServiceProfiles\\NetworkService"
    - "C:\\Windows\\ServiceProfiles\\LocalService"
    - "C:\\Windows\\system32\\config\\systemprofile"

So, why does the search not work if the values are quoted?


Solution

  • Since all_user_profile.output just seems to be list and you like to remove (reject) an item from that list, a minimal example playbook

    ---
    - hosts: localhost
      become: false
      gather_facts: false
    
      vars:
    
        all_user_profile:
          output: [
            "C:\\Users\\LocalUser",
            "C:\\Users\\LocalUser.001",
            "C:\\Users\\Admin",
            "C:\\Windows\\ServiceProfiles\\NetworkService",
            "C:\\Windows\\ServiceProfiles\\LocalService",
            "C:\\Windows\\system32\\config\\systemprofile"
          ]
    
      tasks:
    
        - name: Profiles to delete
          debug:
            msg: "{{ all_user_profile.output | reject('search', user) | list }}"
          vars:
            user: Admin
    

    will result into an output of

    TASK [Profiles to delete] *******************
    ok: [localhost] =>
      msg:
      - C:\Users\LocalUser
      - C:\Users\LocalUser.001
      - C:\Windows\ServiceProfiles\NetworkService
      - C:\Windows\ServiceProfiles\LocalService
      - C:\Windows\system32\config\systemprofile
    

    It is also possible to specify the path in more detail, see in example

        - name: Profiles to delete
          debug:
            msg: "{{ all_user_profile.output | reject('search', keep) | list }}"
          vars:
            keep: Users\\Admin