Change_when: в Ansible

У меня возникли проблемы с настройкой условия changed_when для конкретной задачи в моей книге игр.

Раньше я использовал ignore_errors: true, используя модуль git:

- name: Checkout in client folder
  ansible.builtin.git:
    repo: "{{ item.value.dev_repo | default('git@*****:***/****.git') }}"
    key_file: /tmp/oci_odoo.rsa
    accept_hostkey: true
    dest: "/opt/odoo/odoo_{{ item.key }}/addons"
    version: "{{ item.value.repo_branch | default('main') }}"
    force: false
  with_dict: "{{ clients }}"
  when: inventory_hostname in groups['main']
  ignore_errors: true
  tags: tag1

Этот код дает мне ошибку каждый раз, когда я запускаю playbook, поскольку на самом деле в папке есть локальные изменения:

[11:06:42]   ↳ module : Checkout in client folder  | hostname | FAILED | 1.08s
{
  - msg: One or more items failed
  - results: [ {
    - msg: Local modifications exist in the destination: /opt/odoo/odoo/addons (force=no).
    - changed: False
    - before: 1c9a771969222f8ebbab57bd1e173b821f684a04
    - failed: True
    }
    - ansible_loop_var: item
  } ]
  - changed: False
}

Затем я попытался использовать условное условие, чтобы увидеть изменение, когда текст «Локальные модификации» присутствует в результате с помощью

  register: result
  changed_when: '"Local modifications" in result.results[msg]'

или

  register: result
  changed_when: '"Local modifications" in result.results.msg'

Поскольку отладка result var дает:

{
  - result: {
    - msg: One or more items failed
    - results: [ {
      - msg: Local modifications exist in the destination: /opt/odoo/odoo/addons (force=no).
      - changed: False
      - before: 1c9a771969222f8ebbab57bd1e173b821f684a04
      - failed: True
      - changed_when_result: The conditional check '"Local modifications" in result.results[msg]' failed. The error was: error while evaluating conditional ("Local modifications" in result.results[msg]): 'dict object' has no attribute 'results'
      }
      - ansible_loop_var: item
    } ]
    - skipped: False
    - failed: True
    - changed: False
  }
}

И с этим вы увидите ошибку:

he conditional check '"Local modifications" in result.results[msg]' failed. The error was: error while evaluating conditional ("Local modifications" in result.results[msg]): 'dict object' has no attribute 'results'

Как я могу заставить ansible думать, что есть изменения, когда «Локальные модификации» возвращаются модулем git?

Спасибо,

Обновлено: dict используется:

clients:
  client1:
    odoo_version: "15"
    odoo_subnet: "22"
    port_ending_number: "02"
    odoo_passwd: "azertyuiop"
    domain: doe
    dev_repo: [email protected]

Обратите внимание, что вы перебираете список клиентов (with_dict: "{{ clients }}"), создавая список результатов ({ - result: { - msg: One or more items failed - results: [ {} } - ansible_loop_var: item } ] ...). Поэтому вам нужно подумать, хотите ли вы проверить, изменилось ли что-то, например, для 1 из всех клиентов, нескольких из списка клиентов или конкретного. Так что же означает «локальные модификации» в отношении списка клиентов?

U880D 01.02.2023 11:50

@ U880D Цикл проверяет репозиторий git в папке BY client, это то, о чем вы спрашивали. Добавление нового клиента и повторное воспроизведение плейбука клонирует репозиторий и не трогает других с помощью примечания Local modifications. Я хочу, чтобы эта заметка проходила каждый раз, оставляя «настоящие» ошибки.

Louis Gromb 01.02.2023 15:34

=> changed_when: '"Local modifications" in result.msg'. См. последний абзац в docs.ansible.com/ansible/latest/playbook_guide/…

Zeitounator 01.02.2023 16:33
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
109
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваше состояние должно выглядеть так:

  register: result
  changed_when: '"Local modifications" in result.msg'

Такие условия, как changed_when и failed_when, оцениваются для каждой итерации. Во время выполнения итерации результат каждого шага итерации доступен исключительно в переменной register (в вашем примере result).

Только после окончания цикла результаты всех шагов итерации суммируются в списке results. Таким образом, записи списка в results — это те результаты, которые ранее были доступны исключительно через переменную, определенную register во время выполнения.


Вот еще один небольшой пример.

Следующая задача:

- debug:
    msg: "{{ item }}"
  with_items:
    - Hello John.
    - The sun is shining.
    - John and Joe drinking a beer.
  register: result
  changed_when: '"John" in result.msg'

Результаты в этом поведении относительно ok и changed:

TASK [debug] *********************************************************
changed: [localhost] => (item=Hello John.) => {
    "msg": "Hello John."
}
ok: [localhost] => (item=The sun is shining.) => {
    "msg": "The sun is shining."
}
changed: [localhost] => (item=John and Joe drinking a beer.) => {
    "msg": "John and Joe drinking a beer."
}

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

TASK [debug] ***********************************************
ok: [localhost] => {
    "result": {
        "changed": true,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": true,
                "failed": false,
                "item": "Hello John.",
                "msg": "Hello John."
            },
            {
                "ansible_loop_var": "item",
                "changed": false,
                "failed": false,
                "item": "The sun is shining.",
                "msg": "The sun is shining."
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "failed": false,
                "item": "John and Joe drinking a beer.",
                "msg": "John and Joe drinking a beer."
            }
        ],
        "skipped": false
    }
}

По сути, with_dict работает точно так же, как with_items, внутренне все это оценивается как loop. Цикл может работать только с объектами, которые можно повторять, поэтому внутри dict автоматически преобразуется в список dicts с filter dict2items.

Поэтому все будет работать так же, если я заменю with_items на with_dict следующим образом:

- debug:
    msg: "{{ item.key }}: {{ item.value  }}"
  with_dict:
    sentence1: Hello John.
    sentence2: The sun is shining.
    sentence3: John and Joe drinking a beer.
  changed_when: '"John" in result.msg'
  register: result

Однако вы пытаетесь применить changed_when, но при этом поставили ignore_errors: true. Это не будет прервано при ошибке, но ошибка все равно будет зарегистрирована как таковая.

Применяется следующий порядок приоритета:

не удалось > изменено > ок

Если я включу сбой в свой пример задачи, вы увидите, что первый шаг итерации оценивается как failed, хотя это также changed.

- debug:
    msg: "{{ item.key }}: {{ item.value  }}"
  with_dict:
    sentence1: Hello John.
    sentence2: The sun is shining.
    sentence3: John and Joe drinking a beer.
  changed_when: '"John" in result.msg'
  failed_when: '"Hello" in result.msg'
  ignore_errors: true
  register: result

Результат выглядит следующим образом:

TASK [debug] ***************************************************************************************
failed: [localhost] (item = {'key': 'sentence1', 'value': 'Hello John.'}) => {
    "msg": "sentence1: Hello John."
}
ok: [localhost] => (item = {'key': 'sentence2', 'value': 'The sun is shining.'}) => {
    "msg": "sentence2: The sun is shining."
}
changed: [localhost] => (item = {'key': 'sentence3', 'value': 'John and Joe drinking a beer.'}) => {
    "msg": "sentence3: John and Joe drinking a beer."
}
fatal: [localhost]: FAILED! => {"msg": "One or more items failed"}
...ignoring

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

TASK [debug] ***********************************************
ok: [localhost] => {
    "result": {
        "changed": true,
        "failed": true,
        "msg": "One or more items failed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": true,
                "failed": true,
                "failed_when_result": true,
                "item": {
                    "key": "sentence1",
                    "value": "Hello John."
                },
                "msg": "sentence1: Hello John."
            },
            {
                "ansible_loop_var": "item",
                "changed": false,
                "failed": false,
                "failed_when_result": false,
                "item": {
                    "key": "sentence2",
                    "value": "The sun is shining."
                },
                "msg": "sentence2: The sun is shining."
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "failed": false,
                "failed_when_result": false,
                "item": {
                    "key": "sentence3",
                    "value": "John and Joe drinking a beer."
                },
                "msg": "sentence3: John and Joe drinking a beer."
            }
        ],
        "skipped": false
    }
}

В result.msg содержится строка "Локальные модификации", однако распознается ошибка и это преобладает. Поэтому определите либо failed_when: false, либо найдите осмысленное условие для варианта failed_when в будущем.

По failed_when: false ваша задача никогда не будет оцениваться как невыполненная и никогда не станет игнорироваться, но таким образом изменение может быть оценено как таковое.

Итак, попробуйте следующее:

  register: result
  changed_when: '"Local modifications" in result.msg'
  failed_when: false

Спасибо за ответ phanaz, вроде нормально работает с with_items, но with_dict нет. На этот раз у меня нет changed_when_result в выводе, но задачи по-прежнему отображаются как сбои в выполнении. Я зарегистрировал переменную с именем output и указал changed_when на output.msg.

Louis Gromb 02.02.2023 09:28

Как выглядит ваш дикт clients? Можете ли вы привести пример, отредактировав свой пост?

phanaz 02.02.2023 09:36

Я добавил больше пояснений к моему сообщению.

phanaz 02.02.2023 23:52

Другие вопросы по теме