在我的 Ansible 劇本中,我有這樣的內容:
- name: "A: Check to see if we need to run task B"
[... implementation omitted, not relevant ...]
register: task_a_result
check_mode: no # even run in check mode
changed_when: no # this only reads/checks stuff
- name: "B: Write x to file"
shell: "echo {{ my_var|quote }} > /path/to/file"
when: task_a_result.stdout_lines[0].startswith('ABCDEF')
changed_when: yes # when run, it always changes the state
我願意不是想要在檢查模式下運行 B (因此, no check_mode: no
),但我想報告如果它在非檢查模式下運行,它就會改變。我想要這種行為,因為我不希望在非檢查模式下運行時出現意外。然而,儘管changed_when: yes
我自己設定了條件,Ansible 仍然將任務顯示為跳過因此不變大部頭書:
skipping: [myhost] => changed=false msg: skipped, running in check mode
(以上在檢查模式下,它在常規非檢查模式下報告“已更改”。)
我發現這個錯誤報告似乎被誤解並不適當地關閉:14950,但我不能再對此發表評論了。
我是否忽略了一些基本的東西?其他模組通常在 Ansible 中報告「本來會改變」的狀態,但對於 shell/命令來說這也可能嗎?
使用 Ansible 2.7.12 和 2.8.2 會產生相同的結果。
我希望避免命令本身出現令人討厭的駭客行為,例如:
- name: "B: Write x to file"
shell: "echo {{ my_var|quote }} {{ '>' if task_a_result.stdout_lines[0].startswith('ABCDEF') else '' }} /path/to/file"
when: task_a_result.stdout_lines[0].startswith('ABCDEF')
changed_when: yes
是的,我知道我可以使用複製/模板模組寫入文件,但我似乎無法覆蓋文件,例如echo 1234 > /sys/module/zfs/parameters/zfs_arc_max
,因為複製/模板會嘗試替換看起來的文件,並且設置內核參數不會像那樣工作。不,這個核心模組參數不會透過 Linux 上的 sysctl 公開。
答案1
我知道這有點老了,但我正在尋找這個問題的解決方案。我也厭倦了命令模組作為 OP 帶來的驚喜。
如果我們更改“命令”部分,以便它在檢查模式下執行不同的命令會怎麼樣?我們始終運行該任務,即使在檢查模式下也是如此。
注意:在你抱怨之前,我知道這是一個壞例子。我知道“命令”模組中有一個“創建”選項。這只是舉個例子。
到目前為止,這是我的解決方案:
- name: Get some info
stat: {path: /tmp/somefile}
register: file_info
- name: Run the command conditionally
command:
"{{ 'true' if (file_info['stat']['exists'] or ansible_check_mode)
else 'touch /tmp/somefile' }}"
changed_when: not file_info['stat']['exists']
check_mode: false
它有效,但臃腫。
請告訴我是否有更好的解決方案。
答案2
我有類似的需求。我想看看該命令是否會運行,以便在不以檢查模式運行時不會出現任何意外。
作為解決方法,我新增了一個偵錯任務,報告將發生更改,並使用命令任務中的when條件在偵錯任務上設定changed_when,即
- name: "Report pending change"
debug:
msg: "Change pending"
changed_when: task_a_result.stdout_lines[0].startswith('ABCDEF')
when: ansible_check_mode|bool