Что такое циклы в Ansible playbook?

Ответ

Циклы (Loops) в Ansible позволяют повторять выполнение задачи для каждого элемента в списке или словаре, что устраняет дублирование кода. Основной и рекомендуемый способ — использование директивы loop.

Основные типы циклов:

  1. loop (современный):
    - name: Ensure multiple users exist
      ansible.builtin.user:
        name: "{{ item }}"
        state: present
        groups: "developers"
      loop:
        - alice
        - bob
        - charlie
  2. Цикл по списку словарей (часто для пакетов):
    - name: Install a list of packages
      ansible.builtin.apt:
        name: "{{ item.name }}"
        state: "{{ item.state | default('present') }}"
      loop:
        - { name: 'nginx', state: 'latest' }
        - { name: 'postgresql', state: 'present' }
        - { name: 'old_package', state: 'absent' }
  3. Цикл с регистрацией результата каждой итерации:

    - name: Create directories for app logs
      ansible.builtin.file:
        path: "/var/log/{{ item }}"
        state: directory
      loop: "{{ ['app1', 'app2', 'app3'] }}"
      register: dir_creation_results
    
    - name: Debug results
      ansible.builtin.debug:
        var: dir_creation_results.results

Управление циклом (loop_control):

- name: Configure services with readable output
  ansible.builtin.service:
    name: "{{ item }}"
    enabled: true
  loop:
    - docker
    - ssh
  loop_control:
    label: "Enabling service: {{ item }}"  # Скрывает содержимое item в выводе
    pause: 2  # Пауза в 2 секунды между итерациями (например, для graceful restarts)

Циклы — фундаментальный инструмент для создания гибких и поддерживаемых плейбуков, особенно при работе с динамическими списками из переменных или результатов предыдущих задач.

Ответ 18+ 🔞

А, ну вот, циклы в Ansible, ебать мои старые костыли! Это ж самая соль, когда надо одно и то же по десять раз не копировать, а сделать красиво. Сейчас разжуем.

Смотри, основной прикол — это директива loop. Всё остальное — старьё, типа with_items, можно забыть, как страшный сон. loop — наш новый царь и бог.

Ну и какие они бывают, эти циклы:

  1. Просто loop — классика жанра. Допустим, тебе надо трёх юзеров создать. Ну ты же не будешь три одинаковые задачи писать? Вот и я о том же.

    - name: Ensure multiple users exist
      ansible.builtin.user:
        name: "{{ item }}"  # Сюда на каждой итерации подставится имя из списка
        state: present
        groups: "developers"
      loop:  # А вот и сам список, ёпта
        - alice
        - bob
        - charlie

    Всё, задача прогонится три раза: для Алисы, Боба и этого, Чарли. Красота.

  2. Цикл по списку словарей — для хитрожопых случаев. Чаще всего для пакетов, когда у каждого своя судьба: один — последней версии, другой — просто установлен, а третий — нахуй удалён.

    - name: Install a list of packages
      ansible.builtin.apt:
        name: "{{ item.name }}"
        state: "{{ item.state | default('present') }}"  # Если state не указали, будет 'present'
      loop:
        - { name: 'nginx', state: 'latest' }   # Ставим свежак
        - { name: 'postgresql', state: 'present' } # Просто ставим
        - { name: 'old_package', state: 'absent' }  # А этот долой, нахуй

    Видишь? В item теперь не просто строка, а целый словарик, и ты из него тащишь name и state. Удобно, как хуй с винтом.

  3. Цикл с регистрацией результата — когда тебе важно не просто сделать, но и посмотреть, что получилось в каждой итерации. А то вдруг одна папка создалась, а другая — нет?

    - name: Create directories for app logs
      ansible.builtin.file:
        path: "/var/log/{{ item }}"
        state: directory
      loop: "{{ ['app1', 'app2', 'app3'] }}"  # Список можно и так задать, из переменной
      register: dir_creation_results  # Регистрируем ВЕСЬ результат цикла
    
    - name: Debug results
      ansible.builtin.debug:
        var: dir_creation_results.results  # А вот тут results — это уже список результатов КАЖДОЙ итерации!

    После этого в dir_creation_results.results будет массив, где можно посмотреть item, stdout, changed и прочее для каждой созданной папки. Пизда рулю, а не фича.

А ещё есть loop_control — такая хитрая жопа для тонкой настройки. Например, чтобы в выводе не светить содержимым item (особенно если там пароли), или чтобы между итерациями делать паузу.

- name: Configure services with readable output
  ansible.builtin.service:
    name: "{{ item }}"
    enabled: true
  loop:
    - docker
    - ssh
  loop_control:
    label: "Enabling service: {{ item }}"  # В выводе будет эта красивая строка вместо сырого `item`
    pause: 2  # Пауза в 2 секунды между включением сервисов. Чтобы, например, не все сразу легли при рестарте.

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