Ansible ist ein leistungsfähiges Automatisierungstool, das zahlreiche integrierte Module für die Verwaltung von Infrastrukturen bietet. Manchmal reichen diese jedoch nicht aus, um spezielle Anforderungen zu erfüllen. In solchen Fällen können eigene Module in Ansible geschrieben werden, entweder in Bash oder Python. In diesem Blogbeitrag zeigen wir, wie Sie ein eigenes Ansible-Modul erstellen, testen und verwenden können.
1. Grundlagen der Ansible-Module
Ein Ansible-Modul ist ein kleines Programm, das von Ansible auf den verwalteten Hosts (Zielsystemen) ausgeführt wird, um eine bestimmte Aufgabe zu erledigen. Jedes Ansible-Modul gibt eine JSON-Antwort zurück, die Informationen über den Status der Ausführung und die vorgenommenen Änderungen enthält.
Typische Aufgaben von Modulen:
- Ändern von Dateien oder Konfigurationen auf einem Remote-Host
- Ausführen von Befehlen und Skripten
- Bereitstellen von Software und Diensten
Standardmäßig sind viele Ansible-Module in Python geschrieben, da es auf fast allen Linux-Systemen verfügbar ist. Allerdings kann auch jede andere Sprache verwendet werden, solange das Modul eine JSON-kompatible Ausgabe generiert und die erforderlichen Rückgabewerte liefert.
2. Modulstruktur
Ein Ansible-Modul muss bestimmte Rückgabewerte liefern:
changed
: Gibt an, ob eine Änderung auf dem Zielsystem vorgenommen wurde (boolean).failed
: Gibt an, ob ein Fehler aufgetreten ist (boolean).- Andere Schlüssel: Können benutzerdefinierte Informationen oder Ergebnisse der Modulausführung enthalten.
Die Ausgabe muss im JSON-Format erfolgen, da Ansible die Ausgabe in dieser Form verarbeitet.
3. Erstellung eines Moduls in Bash
Wir beginnen mit der Erstellung eines einfachen Bash-Moduls. Stellen Sie sich vor, wir möchten ein Modul erstellen, das prüft, ob eine Datei existiert, und optional eine Datei erstellt.
3.1 Bash-Modul erstellen
Erstellen Sie eine Datei namens check_file.sh
:
#!/bin/bash
# Parameter aus Ansible lesen
FILE_PATH=$1
# JSON-Ausgabe vorbereiten
if [[ -f "$FILE_PATH" ]]; then
# Datei existiert, keine Änderung
echo "{\"changed\": false, \"msg\": \"Datei existiert bereits\", \"path\": \"$FILE_PATH\"}"
exit 0
else
# Datei existiert nicht, erzeuge Datei
touch "$FILE_PATH"
if [[ $? -eq 0 ]]; then
echo "{\"changed\": true, \"msg\": \"Datei wurde erstellt\", \"path\": \"$FILE_PATH\"}"
exit 0
else
echo "{\"failed\": true, \"msg\": \"Konnte Datei nicht erstellen\", \"path\": \"$FILE_PATH\"}"
exit 1
fi
fi
Dieses Bash-Skript:
- Liest den Dateipfad als Eingabeparameter.
- Überprüft, ob die Datei existiert.
- Wenn sie nicht existiert, wird die Datei erstellt.
- Gibt eine JSON-Antwort zurück, die den Status der Änderung anzeigt.
3.2 Integration in Ansible Playbook
Um dieses Modul in einem Ansible Playbook zu verwenden, können wir es mit dem command
Modul aufrufen.
---
- hosts: localhost
tasks:
- name: Überprüfe und erstelle Datei
command: /path/to/check_file.sh /tmp/testdatei.txt
register: result
- name: Ausgabe des Ergebnisses
debug:
var: result.stdout
4. Erstellung eines Moduls in Python
Python ist aufgrund seiner Integration in Ansible die empfohlene Sprache für die Erstellung von Modulen. Hier ist ein einfaches Beispiel für ein Python-Modul, das dieselbe Aufgabe wie das Bash-Skript übernimmt.
4.1 Python-Modul erstellen
Erstellen Sie eine Datei namens check_file.py
:
#!/usr/bin/python
import os
import json
import sys
def main():
# Parameter von Ansible erhalten
file_path = sys.argv[1]
result = {
"changed": False,
"failed": False,
"msg": "",
"path": file_path
}
# Überprüfe, ob die Datei existiert
if os.path.exists(file_path):
result["msg"] = "Datei existiert bereits"
else:
# Versuche, die Datei zu erstellen
try:
with open(file_path, "w") as file:
file.write("")
result["changed"] = True
result["msg"] = "Datei wurde erstellt"
except Exception as e:
result["failed"] = True
result["msg"] = f"Konnte Datei nicht erstellen: {str(e)}"
# JSON-Antwort ausgeben
print(json.dumps(result))
if __name__ == "__main__":
main()
4.2 Integration in Ansible Playbook
Ähnlich wie beim Bash-Skript können wir das Python-Modul in einem Ansible Playbook verwenden:
---
- hosts: localhost
tasks:
- name: Überprüfe und erstelle Datei (Python)
command: /path/to/check_file.py /tmp/testdatei.txt
register: result
- name: Ausgabe des Ergebnisses
debug:
var: result.stdout
5. Entwicklung von Ansible-Modulen mit ansible.module_utils.basic
Ansible bietet eine spezielle Python-Bibliothek, ansible.module_utils.basic
, die die Erstellung eigener Module vereinfacht. Sie nimmt einem das Parsen von Eingabedaten und das Erstellen von JSON-Antworten ab.
5.1 Verbesserte Version des Python-Moduls mit AnsibleModule
#!/usr/bin/python
from ansible.module_utils.basic import AnsibleModule
import os
def main():
module_args = dict(
path=dict(type='str', required=True)
)
module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)
file_path = module.params['path']
result = {
"changed": False,
"path": file_path
}
# Check-Modus: Keine Änderungen vornehmen
if module.check_mode:
if os.path.exists(file_path):
module.exit_json(**result)
else:
result["changed"] = True
module.exit_json(**result)
# Überprüfe, ob die Datei existiert
if os.path.exists(file_path):
result["msg"] = "Datei existiert bereits"
else:
# Versuche, die Datei zu erstellen
try:
with open(file_path, "w") as file:
file.write("")
result["changed"] = True
result["msg"] = "Datei wurde erstellt"
except Exception as e:
module.fail_json(msg=f"Konnte Datei nicht erstellen: {str(e)}")
module.exit_json(**result)
if __name__ == "__main__":
main()
Dieses Modul nutzt AnsibleModule
, um Eingaben zu verarbeiten und die JSON-Ausgabe zu erstellen. Es unterstützt auch den Check-Modus, der ohne Änderungen auf den Hosts getestet werden kann.
5.2 Verwendung im Playbook
---
- hosts: localhost
tasks:
- name: Überprüfe und erstelle Datei (AnsibleModule)
check_mode: yes
command: /path/to/check_file.py /tmp/testdatei.txt
register: result
- name: Ausgabe des Ergebnisses
debug:
var: result.stdout
6. Testen und Validieren eigener Module
Um ein selbst erstelltes Modul gründlich zu testen:
- Modultests: Führen Sie es mit verschiedenen Szenarien aus (Datei existiert bereits, Schreibrechte fehlen, etc.).
- Check-Modus verwenden: Testen Sie, ob Ihr Modul den Check-Modus korrekt unterstützt.
- Integrationstests: Verwenden Sie das Modul in verschiedenen Playbooks, um sicherzustellen, dass es robust ist.
Fazit
Die Erstellung eigener Module in Ansible, sei es in Bash oder Python, ist eine mächtige Möglichkeit, spezifische Aufgaben zu automatisieren. Python-Module bieten dabei den Vorteil einer besseren Integration in Ansible und die Möglichkeit, die AnsibleModule
-Bibliothek zu nutzen. Durch die Erstellung eigener Module können Sie die Grenzen der Standardmodule erweitern und maßgeschneiderte Lösungen für Ihre Infrastruktur schaffen.