1 | Einführung |
---|---|
2 | Das Inventory |
3 | Über Rollen und Tasks |
4 | Die Module |
5 | Playbooks |
6 | Konfiguration |
7 | gather_facts |
8 | eigene Module |
eigene Module für Ansible
In diesem Teil des Tutorial wollen wir unser eigenes Modul für die Verwendung in Tasks schreiben. Trotz der Vielzahl der bereits bestehenden Module stehst du irgendwann an dem Punkt, wo du ein für dich maßgeschneidertes benötigst.Wir beginnen damit,
eine virtuelle Umgebung einzurichten
virtualenv ansible-dev
cd ansible-dev
source bin/activate
In die Umgebung installierst du nun das Python Modul ansible-core
pip install ansible-core
Damit ist eigentlich schon alles Wesentliche erledigt. Zur Erinnerung: Ein Ansible Modul ist nichts anderes als ein Python Programm, dass beim Durchlauf eines Playbooks auf den Managed Node kopiert und dort über den Python Interpreter gestartet wird.
Modul Grundgerüst
Wir nennen unser Modul temperature_info.py. Es liegt bei mir zunächst im Verzeichnis git/ansible-tutorial/
Zunächst benötigen wir ein Grundgerüst für ein startbares Pythonprogramm.
#! /usr/bin/python3
# encoding:utf-8
from __future__ import (absolute_import, division, print_function)
from ansible.module_utils.basic import AnsibleModule
import logging
def run_module():
def main():
run_module()
if __name__ == '__main__':
main()
Das ist nichts besonderes: Wenn das Programm gestartet wird, wird zunächst main()
Methode gestartet, die dann run_module()
als eigentliche Arbeitsmethode aufruft.
CPU Temperatur
Die Temperatur der sog. thermal_zone0 kannst du mit
cat /sys/class/thermal/thermal_zone0/temp
in der Shell auslesen. Dazu implementieren wir eine Python Methode, die uns den Wert als float
auf zwei Nachkommastellen gerundet zurückliefert.Den Dateinamen legen wir in der Konstante __thermal_zone__
ab.
# Name der Temperaturdatei
__thermal_zone__ ='/sys/class/thermal/thermal_zone0/temp'
# Temperatur auslesen und als float liefern (gerundet auf zwei Nackommastellen)+
def read_temp():
with open(__thermal_zone__,'r') as f :
str = f.readline()
return round(float(str)/1000,2)
run_module()
Jetzt geht es darum, die run_module()
Methode zu befüllen. Zunächst mal benötigen wir ein Dictionary, mit dessen Hilfe die übermittelten Parameter an das Modul ausgelesen und abgelegt werden.
module_args = dict(unit=dict(type='str', required=False, default='Celsius'))
Zu Demonstrationszwecken soll unser Modul die Temperatur auf Wunsch auch in Grad Fahrenheit liefern können. Das machen mir mit dem Modulparameter unit
vom Typ String
. Er ist nicht notwendig. Der voreingestellte Wert ist „Celsius“. Solltest du in einem Modul weitere Parameter erwarten, nimmst du einfach einen weiteren Eintrag in das Dictionary auf.
Wie wir jetzt an den Wert des übergebenen Parameters kommen, zeige ich die gleich
Ergebnis
Jedes Modul liefert ein Ergebnis an den Managed Node zurück. Dafür initialisieren wir und ein Dictionary
result = dict(
changed=False,
message=''
)
Minimal enthält das result
Dictionary einen Wert für changed und einen für message
. changed
ist nur dann True
wenn das Modul Änderungen am Managed Node vorgenommen hat, in message
ein beliebiger Text, der an den Control Node geliefert wird. In letzteres können wir die ermittelte Temperatur hinein schreiben.
Auch dieses Dictionary kannst du um eigene Werte erweitern. Um das zu demonstrieren, schaffen wir uns einen eigenen Key für deine Temperatur
result = dict(
changed=False,
message='',
temperatur=''
)
Diese Schreibweise lässt message
frei für Statusmeldungen des Moduls.
Die Klasse AnsibleModul
Die Klasse AnsibleModul
haben wir oben importiert und sie stellt uns Methoden zur Verfügung, die uns die Arbeit erleichtern. Zunächst müssen wir ein Objekt instanziieren.
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
Unser Dictionary module_args
geht als Parameter in den Konstruktor hinein. Dort werden die übergebenen Parameter aus dem Task geparsed und im Dictionary abgelegt.
Ergebnis zurückgeben
Die ermittelte Temperatur müssen wir natürlich jetzt vom Managed zum Control Node zurückliefern. Zunächst lesen wir die Temperatur aus, falls der unit
Parameter auf ‚Fahrenheit‘ gesetzt ist, rechnen wir die Temperatur um:
temp = read_temp()
units = module.params['unit']
if units != None and units.lower() == 'Fahrenheit'.lower():
temp = fahrenheit(temp)
Hier noch die Hilfsmethode zur Umrechnung von °C in °Fahrenheit:
def fahrenheit(celsius):
return (celsius * 9/5) +32
Den ermittelten Wert schreiben wir jetzt in die Werte von message
und temperatur
unseres result
Dictionary.
result['message'] = str(temp)
result['temperatur'] = str(temp)
Alles, was wir jetzt noch tun müssen, ist das Dictionary an module
zu übergeben, wodurch es dann als JSON-Objekt an den Control Node geliefert wird:
module.exit_json(**result)
Modul installieren
Um das Modul zu installieren, erzeugst du dir in deinem Ansible Verzeichnis ein Unterverzeichnis
mkdir library
Dort kopierst du dir dein selbstgeschriebenes Modul hinein:
cp ansible-dev/temperature_info.py ./library
In der Ansible Konfiguration musst du noch bekannt machen, wo das Library Verzeichnis liegt und folgenden Key eintragen:
default_module_path = ./library
Modul testen
Am einfachsten testest du das neue Modul zunächst mal mit einem einzelnen Managed Node, um die Übersicht zu behalten. Unser Modul legt ein Logfile auf dem Managed Node an, was das Debugging erleichtert. Allerdings entspricht das nicht ganz den Konventionen (dazu gleich mehr). Wenn du dein Modul erfolgreich auf einem Node getestet hast, versuch es mit weiteren.
Module veröffentlichen
So lang du ein Modul nur für deinen eigenen Bedarf schreibst, bist du völlig frei von Regeln. Sobald du das Modul aber in der Ansible Collection veröffentlichen möchtest, musst du einige Regeln beachten. So muss dein Modul unter GPL stehen, ein Test muss vorhanden sein. _info oder _facts Module dürfen keine Änderungen am Managed Node vornehmen. Letzteres erfüllt unser Modul hier durch das Logging nicht, aber wir sind ja hier unter uns. ;-)Die kompletten Regeln gibt es auf der Seite von Ansible.
Im nächsten Tutorial zeige ich dir, wie mit subtasks den Wiederverwendungsgrad steigern kannst.