LINUX.ORG.RU
решено ФорумAdmin

Цикл в цикле или вложеный в словарь список

 , ,


0

2

Привет!

Пишу, я значит, простую (казалось) роль для создания пользователей и групп на узлах в сети, копирование ключей и т.п.

Вот пример вводной конфигурации:

users:
  woozymasta:
    enabled: yes
    sudoers: yes
    comment: 'Woozy Masta'
    group: 'ops'
    shell: '/bin/bash'
    groups: [ sudo, wheel, docker, lxd, adm ] # Зоопарк дистрибутивов
  
  some_user:
    enabled: yes

ОК, первые шаги идут, пользователь создан, теперь нужно добавить группы и только те что есть на узле.

Казалось не проблема, получмем список групп, если желаемой группы нет в списке то её просто не добавляем к пользователю.

- name: Get available groups list
  getent:
    database:     'group'
    split:        ':'

- name: Add additional groups to user if group exsist
  user:
    name:         "{{ item.key }}"
    groups:       "{{ item.value.groups | default('') }}"
    append:       yes
  loop: '{{ users|dict2items }}'
  when: item.value.groups.key in getent_group

Но на проверке when: item.value.groups.key in getent_group падаем с логичной ошибкой, что в списке нет такого атрибута как ключ.

The conditional check 'item.value.groups.key in ansible_facts.getent_group' failed. The error was: error while evaluating conditional (item.value.groups.key in ansible_facts.getent_group): 'list object' has no attribute 'key'

Но вот как решить эту задачу так и не понял, subelements крутил по всякому, join-ом и map-ом пытался обработать, в json даже превращал, как только не куртил но успеха не добился.

Помогите пожалуйста эту проверку сделать правильно. ignore_errors не использую, должно же быть элегантное решение.

Протестировал такую конструкцию. Должно работать.
Необходимо немножко допилять под Вашу задачу.
Юзера создаем отдельно, а там где у меня debug - туда засовываем задачу на добавление в группу. Оно циклом пробегает, и если группа есть в getent_group - делает.
Иначе - пропускает.

Screenshot: https://imgur.com/a/IASXzAH

---
- name: User create
  hosts: localhost 
  gather_facts: yes
  become: yes
  become_method: sudo

  vars:
    users:
      woozymasta:
        enabled: yes
        sudoers: yes
        comment: 'Woozy Masta'
        group: 'ops'
        shell: '/bin/bash'

    group_user: [ wheel, sudo ]

  tasks:
  - name: Get available groups list
    getent:
      database:     'group'
      split:        ':'

  - name: Users
    user: 
      name: "{{ item.key }}"
      append: yes
    with_dict: "{{ users }}" 

  - name: "This command will only run if {{ item }} is a non-empty group that exists"
    debug:
      msg: The group "{{ item }}" 'existent' exists and contains hosts!
    when: item in getent_group
    with_items: "{{ group_user }}"

i3wm ()
Последнее исправление: i3wm (всего исправлений: 1)
Ответ на: комментарий от i3wm

Спасибо большое за помощь, но я хочу добиться рабочего состояния именно при вложенном списке в словарь, и здесь у меня трудности с сравнением групп.

Для разных пользователей могут быть разные группы. Видимо пример конфигурации указал не очень подходящий, как-то так:

users:
  foo:
    enabled: yes
    groups: [ sudo, wheel, docker, lxd, adm ] 
  
  bar:
    enabled: yes
    groups: [ docker, lxd ] 

  baz:
    enabled: yes
    groups: [ sudo, wheel ] 
WoozyMasta ()
Ответ на: комментарий от WoozyMasta

Решил)
Благодарю за столь интересную задачу.

Screenshot: https://imgur.com/a/MxWHxCq

---
- name: User create
  hosts: localhost 
  gather_facts: yes
  become: yes
  become_method: sudo

  vars:
    users:
      - name: woozymasta
        enabled: yes
        sudoers: yes
        comment: 'Woozy Masta'
        shell: '/bin/bash'
        groups: [ wheel, sudo ]

      - name: woozy
        enabled: yes
        sudoers: yes
        comment: 'Woozy Masta'
        shell: '/bin/bash'
        groups: [ wheel, adm ]

      - name: masta
        enabled: yes
        sudoers: yes
        comment: 'Woozy Masta'
        shell: '/bin/bash'
        groups: [ sudo, wheel ]

  tasks:
  - name: Get available groups list
    getent:
      database: 'group'
      split: ':'
  
  - name: "This command will only run if {{ item }} is a non-empty group that exists"
    user:
      name: "{{ item.0.name }}"
      append: yes
      comment: "{{ item.0.comment }}"
      shell: "{{ item.0.shell }}"
      groups: "{{ item.1 }}"
    when: item.1 in getent_group
    with_subelements: 
     - "{{ users }}"
     - groups

i3wm ()
Последнее исправление: i3wm (всего исправлений: 4)
Ответ на: комментарий от i3wm

Спасибо за помощь! А ведь сразу же структуру конфигурации в виде списка делал, но черт дернул в словарь превратить.

Добавил проверок, loop: "{{ lookup('subelements', users, 'groups', {'skip_missing': True})}}", так не падает если списка групп нет.

Вот промежуточный результат:

---
- name: Add group
  group:
    name: "{{ item.group | default(default_group) | default(item.name) }}"
    state: present
  loop: "{{ users }}"
  when: item.enabled|default('true')|bool

- name: Add user
  user:
    name:         "{{ item.name }}"
    comment:      "{{ item.comment     | default(item.name) }}"
    create_home:  "{{ item.create_home | default('yes') }}"
    group:        "{{ item.group       | default(default_group) | default(item.name) }}"
    home:         "{{ item.home        | default('/home/' + item.name) }}"
    shell:        "{{ item.shell       | default('/bin/bash') }}"
  loop: "{{ users }}"
  when: item.enabled|default('true')|bool

- name: Determine available groups
  getent:
    database: group
    split: ':'

- name: Add additional groups to user
  user:
    name:         "{{ item.0.name }}"
    groups:       "{{ item.1 | default(item.0.name) }}"
    append:       yes
  loop: "{{ lookup('subelements', users, 'groups', {'skip_missing': True})}}"
  when: 
  - item.1 in getent_group
  - item.0.enabled|default('true')|bool
WoozyMasta ()