Сравнивайте только точные строки, а не частичные.

Вопрос или проблема

- name: Установленные пакеты.
  ansible.builtin.shell:
    cmd: apt list --installed | cut -d"https://serverfault.com/" -f1 | uniq
  register: установленные_пакеты

- name: Установить пакеты.
  ansible.builtin.apt:
    name: "{{ item }}"
    state: present
  when: 'item not in установленные_пакеты.stdout.splitlines()'
  loop:
    - 7zip
    - acl

У меня есть вышеуказанная задача. Работает отлично, ЗА ИСКЛЮЧЕНИЕМ того, что ‘string’ соответствует частичным именам пакетов. То есть, если я хочу установить пакет ‘acl’, он пропускается, потому что ‘libacl1’ уже установлен. Мне нужно, чтобы соответствие происходило по полному имени пакета и ТОЛЬКО по полному имени пакета.

Есть ли способ сделать это?

Ответ или решение

Для решения проблемы с установкой пакетов в Ansible и предотвращения пропуска требуемых пакетов из-за неполного совпадения названий, необходимо изменить условие проверки. В текущем коде используется конструкция when: 'item | string not in installed_packages.stdout', которая действительно позволяет осуществлять частичное совпадение имен пакетов, что приводит к проблеме при установке, например, пакета ‘acl’, когда установлен ‘libacl1’.

Чтобы обеспечить полное совпадение имен пакетов, вы можете воспользоваться фильтрацией списка установленных пакетов и проверкой с помощью регулярного выражения. Ниже представлен обновленный вариант вашего кода, который учитывает только полные совпадения имен пакетов:

- name: Получить список установленных пакетов.
  ansible.builtin.shell:
    cmd: apt list --installed | cut -d"/" -f1 | uniq
  register: installed_packages

- name: Установить пакеты.
  ansible.builtin.apt:
    name: "{{ item }}"
    state: present
  when: "'{{ item }}' not in installed_packages.stdout.splitlines() | map('trim') | list"
  loop:
    - 7zip
    - acl

Объяснение изменений:

  1. Получение списка установленных пакетов: Команда apt list --installed возвращает полный список установленных пакетов на системе. В скрипте используется cut -d"/" -f1 для получения только имен пакетов (игнорируя информацию о версии), а uniq убирает дубликаты.

  2. Проверка на полное совпадение: Ошибка, связанная с частичными совпадениями, исправляется с помощью when: "'{{ item }}' not in installed_packages.stdout.splitlines() | map('trim') | list". Этот подход разбивает stdout на строки с помощью метода splitlines(), затем применяет фильтр map('trim'), чтобы удалить лишние пробелы. Это позволяет делать корректную проверку наличия полного имени пакета в списке установленных пакетов.

  3. Использование loop: Через цикл loop задаются пакеты для установки, как в исходном варианте. Если пакет уже установлен (полное совпадение), он не будет установлен повторно.

Рекомендации по улучшению:

  • Логи: Рекомендуется добавить задачу логирования, чтобы отслеживать, какие пакеты были установлены или пропущены. Это поможет в диагностике и обеспечит прозрачность выполнения playbook.
  • Тестирование: Перед запуском в производственной среде протестируйте новый код в безопасной среде, чтобы удостовериться, что все работает согласно ожиданиям.
  • Версия Ansible: Убедитесь, что используете актуальную версию Ansible, так как новые релизы могут содержать улучшения и исправления, касающиеся выполнения задач.

Приведенное решение должно полностью устранить проблему с частичным совпадением имен пакетов и обеспечить корректное поведение вашего Ansible playbook.

Оцените материал
Добавить комментарий

Капча загружается...