Wie melde ich einen Ansible-Befehl/eine Ansible-Shell-Aufgabe im Prüfmodus als geändert?

Wie melde ich einen Ansible-Befehl/eine Ansible-Shell-Aufgabe im Prüfmodus als geändert?

In meinem Ansible-Playbook habe ich Folgendes:

- 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

Ich tuenichtmöchte B im Prüfmodus ausführen (deshalb kein check_mode: no), aber ich möchteBerichtes wäre anders, wenn es im Nicht-Check-Modus ausgeführt worden wäre. Ich möchte dieses Verhalten, weilIch möchte keine Überraschungen erleben, wenn ich im Nicht-Check-Modus arbeite. Obwohl ich changed_when: yesselbst eine Bedingung festgelegt habe, zeigt Ansible die Aufgabe immer alsübersprungenund somitunverändertmir:

skipping: [myhost] => changed=false 
  msg: skipped, running in check mode

(Das Obige im Prüfmodus, und im normalen Nicht-Prüfmodus wird „geändert“ gemeldet.)

Ich habe diesen Fehlerbericht gefunden, der anscheinend falsch interpretiert und unangemessen geschlossen wurde:14950, aber dazu kann ich keinen weiteren Kommentar abgeben.

Übersehe ich etwas Grundlegendes? Andere Module melden in Ansible normalerweise problemlos den Status „hätte sich geändert“, aber ist dies auch für Shell/Befehl möglich?

Die Verwendung von Ansible 2.7.12 und 2.8.2 führt zu denselben Ergebnissen.

Ich hoffe, böse Hacks im Befehl selbst zu vermeiden, wie:

- 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

Und ja, ich weiß, dass ich mit den Kopier-/Vorlagenmodulen in eine Datei schreiben kann, aber ich kann anscheinend nichtüberschreibenDateien damit, z. B. echo 1234 > /sys/module/zfs/parameters/zfs_arc_max, weil copy/template anscheinend versuchen würde, die Datei zu ersetzen, und das Setzen eines Kernelparameters würde so nicht funktionieren. Und nein, dieser Kernelmodulparameter wird unter Linux nicht über sysctl verfügbar gemacht.

Antwort1

Ich weiß, das ist schon etwas älter, aber ich suche nach einer Lösung für dieses Problem. Außerdem habe ich die Überraschungen mit dem Befehlsmodul als OP satt.

Was wäre, wenn wir den „Befehls“-Teil so ändern würden, dass er im Prüfmodus einen anderen Befehl ausführt? Und wir führen die Aufgabe immer aus, auch im Prüfmodus.

Hinweis: Bevor Sie sich beschweren, ich weiß, dass dies ein schlechtes Beispiel ist. Ich weiß, dass es im Modul „Befehl“ eine Option zum Erstellen gibt. Dies soll nur ein Beispiel sein.

Dies ist meine bisherige Lösung:

- 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

Es funktioniert, ist aber aufgebläht.

Bitte sagen Sie mir, ob es bessere Lösungen gibt.

Antwort2

Ich habe ein ähnliches Bedürfnis. Ich möchte sehen, ob der Befehl ausgeführt wird, damit ich keine Überraschungen erlebe, wenn er nicht im Prüfmodus ausgeführt wird.

Als Workaround habe ich eine Debug-Aufgabe hinzugefügt, die meldet, dass es eine Änderung geben wird und habe die „Wann“-Bedingung der Befehlsaufgabe verwendet, um „changed_when“ für die Debug-Aufgabe festzulegen, d. h.

- name: "Report pending change"
  debug:
    msg: "Change pending"
  changed_when: task_a_result.stdout_lines[0].startswith('ABCDEF')
  when: ansible_check_mode|bool

verwandte Informationen