Ansible stdout из элемента, собранного с помощью цикла

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

Я пытаюсь напечатать stdout зарегистрированных элементов в соответствии с документацией документации. Вот мой yaml файл:

- name: network-check
  tags: stats
  shell: "tail -n 3 {{ ansible_facts['nodename'] }}_{{ item }}.out | awk '/Mbits/ { sum += $7; n++} END { print sum / n }'"
  loop: "{{ groups['all'] }}"
  when: ansible_facts['nodename'] != item
  register: check

- name: network-check
  tags: stats
  shell: "echo {{ item.stdout }}"
  loop: "{{ check.results }}"

И я все еще получаю ошибку “атрибут stdout”, как ниже:

TASK [pretests : network-stat] ***************************************************************************************************************************************************************************************************************************************************************************************************************
fatal: [card-kub000]: FAILED! => {"msg": "Задача включает опцию с неопределенной переменной. Ошибка: 'dict object' не имеет атрибута 'stdout'\n\nОшибка, похоже, была в '/home/holo/cardinality/source/sysop/ansible/roles/pretests/tasks/main.yaml': строка 21, столбец 3, но может\nнаходиться в другом месте файла в зависимости от точной проблемы с синтаксисом.\n\nПростой строкой, вызывающей ошибку, является:\n\n\n- name: network-stat\n  ^ здесь\n"}

Что я делаю не так?

Вот как выглядит мой вывод для:

- debug: msg="{{ item.item }}"
  loop: "{{ check.results }}"

выглядит так

ok: [card-kub000] => (item={'changed': True, 'end': '2019-01-31 00:36:50.479743', 'stdout': '128', 'cmd': "tail -n 3 card-kub000_card-kub004.out | awk '/Mbits/ { sum += $7; n++} END { print sum / n }'", 'rc': 0, 'start': '2019-01-31 00:36:50.470371', 'stderr': '', 'delta': '0:00:00.009372', 'invocation': {'module_args': {'creates': None, 'executable': None, '_uses_shell': True, '_raw_params': "tail -n 3 card-kub000_card-kub004.out | awk '/Mbits/ { sum += $7; n++} END { print sum / n }'", 'removes': None, 'argv': None, 'warn': True, 'chdir': None, 'stdin': None}}, '_ansible_parsed': True, 'stdout_lines': ['128'], 'stderr_lines': [], '_ansible_no_log': False, 'failed': False, 'item': 'card-kub004', '_ansible_item_result': True, '_ansible_ignore_errors': None, '_ansible_item_label': 'card-kub004'}) => {
    "msg": "card-kub004"

В конечном счете, я выяснил, где была проблема. У меня было условие “when”, которое сказало ansible пропустить некоторые элементы, если они совпадают с nodename, из-за этого первый элемент не имел поля stdout. Я добавил условие, чтобы проверить, что элемент не пропускается, и это начало работать.

- name: network-check
  tags: stats
  shell: "echo {{ item.stdout }}"
  loop: "{{ check.results }}"
  when: item.changed != False

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

Ansible: Обработка stdout зарегистрированных элементов с использованием циклов

В процессе работы с Ansible возникают ситуации, когда необходимо получать данные, зарегистрированные в результате выполнения задач в цикле. В вашем случае вы столкнулись с проблемой, связанной с отсутствием поля stdout у некоторых элементов. Давайте подробно разберем, как можно решить эту проблему.

Описание проблемы

Вы создали задачу Ansible для выполнения команды shell, которая использует цикл loop для обхода группы хостов. Далее вы регистрируете результаты выполнения в переменной check. Однако, когда вы пытаетесь обратиться к stdout результатов выполнения задач, возникает ошибка "dict object has no attribute 'stdout'", указывающая на отсутствие данного поля у некоторых итемов.

Проблема с условием

Вы правильно отметили, что причина возникновения этой ошибки заключается в условии when, которое контролирует выполнение задач. Это условие пропускает итемы, для которых имя узла совпадает с текущим узлом. В результате, для этих пропущенных элементов не создается запись о stdout, что и приводит к ошибке.

Решение проблемы

Чтобы избежать данной ошибки, вам следует добавить проверку в ваше условие when, которая будет удостоверяться в том, что элемент действительно был изменен, прежде чем пытаться получить его stdout. Вы уже внесли изменения подобным образом:

- name: network-check
  tags: stats
  shell: "echo {{ item.stdout }}"
  loop: "{{ check.results }}"
  when: item.changed != False

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

Полный пример

Вот как выглядит обновленный код с правильным условием:

- name: network-check
  tags: stats
  shell: "tail -n 3 {{ ansible_facts['nodename'] }}_{{ item }}.out | awk '/Mbits/ { sum += $7; n++} END { print sum / n }'"
  loop: "{{ groups['all'] }}"
  when: ansible_facts['nodename'] != item
  register: check

- name: Display Network Check Results
  tags: stats
  shell: "echo {{ item.stdout }}"
  loop: "{{ check.results }}"
  when: item.changed != False

Заключение

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

Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их. Мы всегда рады помочь!

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

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