1

I'm writing a playbook to install 'oh my fish' for all local fish user.

I want trigger the install for local fish user (default shell set to /usr/bin/fish)

And ONLY if 'omf' is not installed in their home (check the presence ~/.local/share/omf directory)

Here what I produced

- name: Read local user database
  getent:
    database: passwd

- name: List local user of fish
  set_fact:
    fish_users: "{{ getent_passwd | dict2items | json_query('[? contains(value, `/usr/bin/fish`)].key') }}"

- name: Check if omf install for fish users
  stat:
    path: "/home/{{ item }}/.local/share/omf"
  loop: "{{ fish_users }}"
  register: omf_user_status

- name: Install omf when absent of fish user home
  block:
  - name: Get last omf repos
    git:
      repo: 'https://github.com/oh-my-fish/oh-my-fish'
      dest: '/tmp/omf'
      clone: yes

  - name: Installing omf for fish user
    become: yes
    become_user: "{{ item }}"
    command: /tmp/omf/bin/install -y --offline --noninteractive
    loop: "{{ fish_users }}"

  when: omf_user_status.item.stat.exists == 'False'

So maybe my approach is not good...

Currently I can get 'omf', installed for all fish users. But I really struggle to generate a usable list , to only install omf for user who haven't it

Obviously the condition doesn't work.

omf_user_status variable is a dict, here an example of the content.

"omf_user_status": {
        "changed": false, 
        "msg": "All items completed", 
        "results": [
            {
                "ansible_loop_var": "item", 
                "changed": false, 
                "failed": false, 
                "invocation": {
                    "module_args": {
                        "checksum_algorithm": "sha1", 
                        "follow": false, 
                        "get_attributes": true, 
                        "get_checksum": true, 
                        "get_md5": false, 
                        "get_mime": true, 
                        "path": "/home/test_ansible/.local/share/omf"
                    }
                }, 
                "item": "test_ansible", 
                "stat": {
                    "atime": 1608164175.7067902, 
                    "attr_flags": "e", 
                    "attributes": [
                        "extents"
                    ], 
                    "block_size": 4096, 
                    "blocks": 8, 
                    "charset": "binary", 
                    "ctime": 1608164176.1907954, 
                    "dev": 1800, 
                    "device_type": 0, 
                    "executable": true, 
                    "exists": true, 
                    "gid": 1343, 
                    "gr_name": "test_ansible", 
                    "inode": 397192, 
                    "isblk": false, 
                    "ischr": false, 
                    "isdir": true, 
                    "isfifo": false, 
                    "isgid": false, 
                    "islnk": false, 
                    "isreg": false, 
                    "issock": false, 
                    "isuid": false, 
                    "mimetype": "inode/directory", 
                    "mode": "0755", 
                    "mtime": 1608164176.1907954, 
                    "nlink": 12, 
                    "path": "/home/test_ansible/.local/share/omf", 
                    "pw_name": "test_ansible", 
                    "readable": true, 
                    "rgrp": true, 
                    "roth": true, 
                    "rusr": true, 
                    "size": 4096, 
                    "uid": 1343, 
                    "version": "3120069218", 
                    "wgrp": false, 
                    "woth": false, 
                    "writeable": true, 
                    "wusr": true, 
                    "xgrp": true, 
                    "xoth": true, 
                    "xusr": true
                }
            }
        ]
    }

Cheers

LeXaNZ
  • 35
  • 5
  • 1
    Not understanding how `.results` works seems to be a FAQ this week; (a) don't compare boolean fields to the **string** `'False'` (b) you can easily get a list of relevant usernames via `with_items: '{{ omf_user_status.results | selectattr("exists") | map(attribute="item") }}'` – mdaniel Dec 17 '20 at 15:59
  • Thanks for your comment Daniel. But I can't make it work with your line: Tried to display the list of user generated, but I got : `FAILED! => {"msg": "Invalid data passed to 'loop', it requires a list, got this instead: ` I called with : `- name: Display list of users debug: msg: "users: {{ item }}" loop: '{{ omf_user_status.results | selectattr("exists") | map(attribute="item") }}'` – LeXaNZ Jan 05 '21 at 04:04
  • Sorry about that, add `| list` to the end to materialize the generator – mdaniel Jan 05 '21 at 04:28
  • Thanks Daniel, really helped me – LeXaNZ Jan 05 '21 at 22:08

1 Answers1

0

I finally make it works with this code.

- name: Register users who need omf
  set_fact:
    list_of_user: "{{ omf_user_status.results | rejectattr('stat.exists') | map(attribute='item') | list }}"

Here the full plabook

# OMF install
- name: Read local user database
  getent:
    database: passwd

- name: List local user of fish
  set_fact:
    fish_users: "{{ getent_passwd | dict2items | json_query('[? contains(value, `/usr/bin/fish`)].key') }}"

- name: Check if omf is installed for fish users
  stat:
    path: "/home/{{ item }}/.local/share/omf"
  loop: "{{ fish_users }}"
  register: omf_user_status

- name: Register users who need omf
  set_fact:
    user_need_omf: "{{ omf_user_status.results | rejectattr('stat.exists') | map(attribute='item') | list }}"

- name: Install omf when absent of fish user's home
  block:
  - name: Get lastest omf from git 
    git:
      repo: 'https://github.com/oh-my-fish/oh-my-fish'
      dest: '/tmp/omf'
      clone: yes

  - name: Installing omf for fish user
    become: yes
    become_user: "{{ item }}"
    command: /tmp/omf/bin/install -y --offline --noninteractive
    loop: "{{ user_need_omf }}"

  - name: Cleanup omf install files
    file:
      path: '/tmp/omf'
      state: absent
  # only run this block if the user_need_omf list is not empty
  when: user_need_omf | length > 0
LeXaNZ
  • 35
  • 5