Task-Status mit changed_when und failed_when steuern
In diesem Schritt lernen Sie, wie Sie die Interpretation von Task-Ergebnissen durch Ansible feiner steuern. Sie lernen zwei leistungsstarke Direktiven kennen: changed_when
und failed_when
.
changed_when
: Standardmäßig melden Module wie ansible.builtin.command
oder ansible.builtin.shell
fast immer einen "changed"-Status, auch wenn der von ihnen ausgeführte Befehl das System nicht verändert hat. changed_when
ermöglicht es Ihnen, eine benutzerdefinierte Bedingung zu definieren, die bestimmt, ob eine Aufgabe als "changed" gemeldet werden soll. Dies ist entscheidend für das Schreiben idempotenter Playbooks und für das genaue Auslösen von Handlern.
failed_when
: Manchmal kann ein Befehl mit einem Rückgabecode ungleich Null beendet werden (was Ansible als Fehler betrachtet), auch wenn das Ergebnis akzeptabel ist. failed_when
ermöglicht es Ihnen, die Standardfehlerbedingungen zu überschreiben, sodass Ihr Playbook auf der Grundlage intelligenterer Kriterien fortgesetzt werden kann, wie z. B. der Ausgabe des Befehls oder einem bestimmten Rückgabecode.
Beginnen wir mit der Einrichtung eines neuen Projektverzeichnisses.
cd ~/project
mkdir control-state-lab
cd control-state-lab
Erstellen Sie die Standard-Inventardatei für localhost
.
nano inventory
Fügen Sie den folgenden Inhalt hinzu:
localhost ansible_connection=local
Speichern und beenden Sie den Editor (Ctrl+X
, Y
, Enter
).
Verwendung von changed_when
Sehen wir uns zunächst an, wie sich eine Befehlsaufgabe standardmäßig verhält. Wir erstellen ein Playbook, das den Befehl date
ausführt. Dieser Befehl gibt einfach das Datum aus und verändert das System nicht, aber das command
-Modul meldet ihn als Änderung.
Erstellen Sie ein neues Playbook namens playbook.yml
.
nano playbook.yml
Geben Sie den folgenden Inhalt ein:
---
- name: Control Task State
hosts: localhost
tasks:
- name: Check local time (default behavior)
ansible.builtin.command: date
Speichern und beenden Sie. Führen Sie nun das Playbook aus.
ansible-playbook -i inventory playbook.yml
Beachten Sie in der Ausgabe, dass die Aufgabe als changed=1
gemeldet wird, obwohl nichts auf dem System verändert wurde.
...
TASK [Check local time (default behavior)] *************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 ...
Verwenden wir nun changed_when
, um Ansible mitzuteilen, dass dieser Befehl das System niemals verändert. Ändern Sie playbook.yml
.
nano playbook.yml
Fügen Sie der Aufgabe changed_when: false
hinzu.
---
- name: Control Task State
hosts: localhost
tasks:
- name: Check local time (with changed_when)
ansible.builtin.command: date
changed_when: false
Speichern und beenden Sie. Führen Sie das Playbook erneut aus.
ansible-playbook -i inventory playbook.yml
Diesmal meldet die Aufgabe ok
, und die abschließende Zusammenfassung zeigt changed=0
. Sie haben das Standardverhalten erfolgreich überschrieben.
...
TASK [Check local time (with changed_when)] ************************************
ok: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 ...
Verwendung von failed_when
Als Nächstes untersuchen wir failed_when
. Wir erstellen eine Aufgabe, die auf die Existenz einer Datei prüft, die nicht vorhanden ist. Der Befehl wird standardmäßig "fehlschlagen".
Erstellen Sie zunächst eine Dummy-Datei, in der gesucht werden soll.
echo "System is running" > status.txt
Ändern Sie nun playbook.yml
, um nach dem Wort "ERROR" in dieser Datei zu suchen. Der Befehl grep
wird mit dem Rückgabecode 1 beendet, da das Wort nicht gefunden wird, was Ansible als Fehler interpretiert.
nano playbook.yml
Ersetzen Sie den Inhalt durch Folgendes:
---
- name: Control Task State
hosts: localhost
tasks:
- name: Check for ERROR in status file (will fail)
ansible.builtin.command: grep ERROR status.txt
Speichern und beenden Sie. Führen Sie das Playbook aus.
ansible-playbook -i inventory playbook.yml
Wie erwartet stoppt die Ausführung des Playbooks mit der Meldung FAILED!
.
...
TASK [Check for ERROR in status file (will fail)] ******************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["grep", "ERROR", "status.txt"], "delta": "...", "end": "...", "msg": "non-zero return code", "rc": 1, ...}
...
Das ist nicht das, was wir wollen. Das Fehlen von "ERROR" ist für uns eine Erfolgsbedingung. Wir können failed_when
verwenden, um neu zu definieren, was einen Fehler darstellt. Wir weisen Ansible an, nur dann fehlzuschlagen, wenn der Rückgabecode des Befehls größer als 1 ist. Ein Rückgabecode von 1 (Muster nicht gefunden) wird nun als Erfolg gewertet. Wir müssen auch das Ergebnis der Aufgabe register
en, um ihren Rückgabecode (rc
) zu überprüfen.
Ändern Sie playbook.yml
ein letztes Mal.
nano playbook.yml
Aktualisieren Sie das Playbook mit register
und failed_when
.
---
- name: Control Task State
hosts: localhost
tasks:
- name: Check for ERROR in status file (with failed_when)
ansible.builtin.command: grep ERROR status.txt
register: grep_result
failed_when: grep_result.rc > 1
changed_when: false
Wir haben auch changed_when: false
hinzugefügt, da grep
eine schreibgeschützte Operation ist und das System nicht verändert.
Speichern und beenden Sie. Führen Sie das endgültige Playbook aus.
ansible-playbook -i inventory playbook.yml
Erfolg! Die Aufgabe meldet nun ok
, da ihr Rückgabecode 1 war, was unserer neuen Fehlerbedingung (rc > 1
) nicht entspricht. Das Playbook wird erfolgreich abgeschlossen.
...
TASK [Check for ERROR in status file (with failed_when)] ***********************
ok: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 ...
Sie haben nun gelernt, wie Sie mit changed_when
und failed_when
die Erfolgs-, Änderungs- und Fehlerzustände Ihrer Aufgaben präzise definieren können, was zu robusterer und intelligenterer Automatisierung führt.