Ansible — Фильтровать Значения Словаря

#ansible #filtering #ansible-module

Вопрос:

Я собрал список всех пользователей с помощью getent_module:

 - name: Get user info
  getent:
    database: passed
 

Это возвращает эту переменную как getent_passwd, словарь, подобный этому:

 {
    "uuidd": [
        "x",
        "107",
        "112",
        "",
        "/run/uuidd",
        "/usr/sbin/nologin"
    ],
    "www-data": [
        "x",
        "33",
        "33",
        "www-data",
        "/var/www",
        "/usr/sbin/nologin"
    ]
}
 

Я пытаюсь вернуть массив пользователей, включая некоторых конкретных пользователей, найдя ключ item.value, в котором «/home» является частью одного из элементов массива значений, а «nologin» — нет.
Это код, который я написал до сих пор, но он неверен.

 - name: style the user list
  set_fact:
    my_users: "{{ item.key | default([]) }}"
  when:
    - "'nologin' not in (item.value)"
    - "'/home' search in (item.value)"
  loop: "{{ lookup('dict', getent_passwd) }}"
 

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

Ответ №1:

Как вы правильно поняли, поскольку сопоставление шаблонов/регулярных выражений работает со строками, а не с элементами списка, when условие не будет работать. При сопоставлении элементов из списка нам нужно сопоставить полный элемент, т. е.

 when:
  - "'/home/someuser' in item.value"
  - "'/usr/sbin/nologin' not in item.value"
 

Как правило, $HOME путь в Linux таков /home/$USER . Полученный результат getent_passwd содержит имя пользователя в item.key . А это значит, что мы можем использовать /home/{{ item.key }} их для сопоставления item.value .

Задача, подобная приведенной ниже, должна выполнить эту работу:

     - name: save users with actual login
      set_fact:
        my_users: "{{ my_users | default([])   [ item.key ] }}"
      when:
        - "'/home/' ~ item.key in item.value"
        - "'/usr/sbin/nologin' not in item.value"
      loop: "{{ lookup('dict', getent_passwd) }}"
 

Другой подход может заключаться в том, чтобы на самом деле join item.value получить строку, аналогичную той, в /etc/passwd которой мы можем выполнить текстовый поиск, например: '/home' search in (item.value) .

Пример:

    # item.value | join(':') is the same as each line of '/etc/passwd'
    - name: save users with actual login
      set_fact:
        my_users: "{{ my_users | default([])   [ item.key ] }}"
      when:
        - "'/home' in item.value | join(':')"
        - "'nologin' not in item.value | join(':')"
      loop: "{{ lookup('dict', getent_passwd) }}"