У меня возникли проблемы с настройкой условия 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]
@ U880D Цикл проверяет репозиторий git в папке BY client, это то, о чем вы спрашивали. Добавление нового клиента и повторное воспроизведение плейбука клонирует репозиторий и не трогает других с помощью примечания Local modifications
. Я хочу, чтобы эта заметка проходила каждый раз, оставляя «настоящие» ошибки.
=> changed_when: '"Local modifications" in result.msg'
. См. последний абзац в docs.ansible.com/ansible/latest/playbook_guide/…
Ваше состояние должно выглядеть так:
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
.
Как выглядит ваш дикт clients
? Можете ли вы привести пример, отредактировав свой пост?
Я добавил больше пояснений к моему сообщению.
Обратите внимание, что вы перебираете список клиентов (
with_dict: "{{ clients }}"
), создавая список результатов ({ - result: { - msg: One or more items failed - results: [ {} } - ansible_loop_var: item } ] ...
). Поэтому вам нужно подумать, хотите ли вы проверить, изменилось ли что-то, например, для 1 из всех клиентов, нескольких из списка клиентов или конкретного. Так что же означает «локальные модификации» в отношении списка клиентов?