Ansible eigene Module Tutorial Teil 8

Ansible Logo (Quelle: Von Ansible/Red Hat – Wikipedia)
Ansible Logo (Quelle: Von Ansible/Red Hat – Wikipedia)
1Einführung
2Das Inventory
3Über Rollen und Tasks
4Die Module
5Playbooks
6Konfiguration
7gather_facts
8eigene 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.

Schreibe einen Kommentar

Creative Commons License
Except where otherwise noted, the content on this site is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Olli Graf - raspithek.de
WordPress Cookie Hinweis von Real Cookie Banner