Start / Seminare / Terraform und OpenTofu in der Praxis
Modul
Automatisierte Tests und Qualitätsprüfungen
Modul 10 von 14 aus dem Seminar Terraform und OpenTofu in der Praxis
6 Kapitel in diesem Modul-Video · Laufzeit
Für Teams
Die Videos zeigen, wie es geht. Die Schulung sorgt dafür, dass Ihr Team es danach tut.
Ein Video kann niemanden fragen, warum es ausgerechnet in Ihrem Repository nicht funktioniert. Es kann kein Team auf eine gemeinsame Konvention bringen. Und es setzt sich niemand freiwillig drei Tage hin. In der Schulung sind am Ende alle auf demselben Stand, gearbeitet wurde am eigenen Code, und die offenen Fragen sind entschieden — in ein paar Tagen statt irgendwann nebenbei.
Vorgespräch am Telefon · Programm nach Maß · ab 1 Tag (8 Unterrichtseinheiten) · Teilnahmezertifikat
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Automatisierte Tests und Qualitätsprüfungen
0:00 Infrastruktur-Code hat einen merkwürdigen Ruf: Er wird gründlich geplant, aber selten getestet. Der Plan gilt vielen als Test genug. Das ist er nicht, denn ein Plan beschreibt nur, was passieren wird — ob es passieren darf, sagt er nicht. In diesem Modul bauen wir deshalb eine Prüfkette für die Saatplan-Module auf. Sie reicht von der einfachen Formatprüfung über native Tests in HCL, Mocks und Regelwerke für Sicherheit bis zu einem Smoke Test, der nachsieht, ob der Dienst tatsächlich antwortet.
0:28 Und wir werden ehrlich sein, wo die Werkzeuge für Docker an ihre Grenzen stoßen. Denn eine grüne Ampel ist nur so viel wert wie die Regeln dahinter.
Automatisierte Tests und Qualitätsprüfungen
0:38 Der vierte Tag dreht sich um Vertrauen in Änderungen, und er beginnt mit den Tests. Der Satz auf der Folie bringt den Unterschied auf den Punkt: Ein Plan zeigt, was passieren wird, ein Test sagt, ob es passieren darf. Wir gehen in fünf Etappen vor — von der Strategie über native Tests, Mocks und Regelwerke bis zu Smoke Tests und dem Aufräumen danach.
0:58 Am Ende steht eine Übung, in der jeder Test einmal rot werden muss.
Teststrategie für IaC
1:02 Bevor wir den ersten Test schreiben, eine Frage der Ökonomie: Welche Prüfung kostet wie viel, und welche findet was? Die Antwort bestimmt, in welcher Reihenfolge eine Pipeline prüfen sollte. Diese Schichtung kennt man aus der Softwareentwicklung als Testpyramide, nur mit anderen Bausteinen. Am Anfang stehen Prüfungen, die in Sekunden laufen und nichts weiter brauchen als die Dateien: Formatierung, Syntax, Typen.
1:28 Darunter kommen Regelwerke für Konventionen und riskante Einstellungen. Dann Tests auf Basis des Plans, bei denen Mocks den Docker-Host ersetzen. Erst danach wird es teuer: Tests, die wirklich etwas anlegen, und schließlich der Smoke Test, der fragt, ob der Dienst antwortet. Die Faustregel lautet: Jeder Fehler soll auf der billigsten Stufe auffallen, die ihn überhaupt finden kann. Was eine Formatprüfung erwischt, darf nie erst den Docker-Host bemühen.
1:56 Die Tabelle beantwortet zwei Fragen pro Zeile: Was findet die Prüfung, und was braucht sie dafür? Lesen Sie sie am besten von rechts. Je weiter unten, desto mehr Umgebung wird vorausgesetzt — von bloßen Dateien bis zu einem echten Docker-Host. Genau daran entscheidet sich, wo eine Prüfung in der Pipeline stehen kann. Ein Detail lohnt den genaueren Blick: validate braucht zwar ein init, aber kein Backend.
2:20 Mit der Option, das Backend beim init abzuschalten, prüft die Pipeline den Code, ohne den Remote State auch nur anzufassen. Das ist wichtig, denn eine Prüfung, die Zugriff auf den echten State braucht, wird schnell zum Sicherheitsthema.
Native Tests
2:34 Terraform und OpenTofu bringen ihr eigenes Testwerkzeug mit. Die Tests sind in derselben Sprache geschrieben wie die Infrastruktur — keine zweite Programmiersprache, kein zusätzliches Framework. Ein nativer Test funktioniert wie eine Probefahrt mit Checkliste. Jeder run-Block ist eine Fahrt: Er führt entweder einen Plan oder ein Apply aus, und danach hakt er seine Prüfpunkte ab, die assert-Blöcke.
2:58 Jeder davon besteht aus einer Bedingung und einer Fehlermeldung für den Fall, dass sie nicht hält. Wichtig ist der Standard: Ohne weitere Angabe macht ein run-Block ein Apply, legt also wirklich etwas an. Damit nichts liegen bleibt, räumt das Werkzeug am Ende jeder Testdatei alles wieder ab. Für OpenTofu gibt es eine Besonderheit: Es liest zusätzlich eigene Testdateien mit der Endung tofutest, die bei gleichem Namen Vorrang haben.
3:24 Dieser Test stellt eine einfache, aber wichtige Regel sicher: Die Saatplan-Datenbank veröffentlicht keine Ports nach außen. Er läuft nur als Plan, legt also nichts an, und er bekommt ein Test-Passwort, das ausdrücklich nur hierfür gedacht ist. Die Prüfung selbst zählt die Ports des Containers und erwartet null. Der Charme liegt in der Absicherung für die Zukunft.
3:45 Wer in einem halben Jahr aus Bequemlichkeit den Datenbank-Port öffnet, bekommt sofort eine verständliche Fehlermeldung. Eine Grenze hat ein solcher Plan-Test allerdings: Er sieht nur, was zum Zeitpunkt des Plans schon feststeht. Eine Container-ID zum Beispiel entsteht erst beim Apply. Ein guter Test prüft nicht nur, dass Richtiges funktioniert, sondern auch, dass Falsches abgelehnt wird.
4:08 Hier übergeben wir dem App-Modul absichtlich einen Web-Port unter 1024 und erwarten, dass die Validierung der Variable anschlägt. Der Test ist also genau dann grün, wenn das Modul den Fehler erkennt. So wird eine Schnittstelle zum Vertrag, den man nicht versehentlich aufweicht. Beachten Sie die Einschränkung im Fuß: Erwartete Fehler können nur aus eigenen Bedingungen stammen — Validierungen, Vor- und Nachbedingungen oder check-Blöcke.
4:33 Einen Fehler, den der Provider selbst meldet, kann man auf diesem Weg nicht als erwartet markieren.
Mocking und Overrides
4:40 Bisher brauchten unsere Plan-Tests noch einen echten Provider. Jetzt nehmen wir auch diese Abhängigkeit heraus — Tests, die laufen, ohne dass irgendwo ein Docker-Daemon antwortet. Ein Mock ist wie ein Flugsimulator. Die Piloten üben alle Handgriffe, aber kein echtes Flugzeug hebt ab. Genauso ersetzt ein mock_provider den echten Docker-Provider: Es wird nichts angelegt, und Werte, die sonst erst der Provider berechnet, erfindet das Werkzeug — Zahlen werden null, Texte zufällig, Listen bleiben leer.
5:11 Das reicht oft, aber nicht immer. Wenn ein Test einen ganz bestimmten Wert braucht, kommen die Overrides ins Spiel. Damit setzen Sie gezielt Werte für eine einzelne Ressource, eine Data Source oder einen ganzen Modulaufruf. Der Gewinn ist enorm: Tests laufen in Sekunden, überall, auch in einer Pipeline ohne jeden Docker-Host.
5:31 Hier sehen Sie beides zusammen. Die erste Zeile ersetzt den Docker-Provider vollständig durch einen Mock. Der Block darunter legt für das API-Image eine feste Image-ID fest, statt sie zufällig erzeugen zu lassen. Damit kann der Test zum Beispiel prüfen, ob genau diese ID im Container ankommt. Der eigentliche run-Block ist dann nur noch ein schlichter Plan.
5:53 Das funktioniert in Terraform und OpenTofu gleich. Eine Mahnung gehört aber dazu, und sie steht im Fuß: Ein Mock bestätigt Ihre eigene Logik, nicht das Verhalten des Providers. Ob Docker den Container am Ende wirklich so startet, kann er nicht beweisen. Bei den Grundlagen sind sich Terraform und OpenTofu einig: Mocks und Overrides gibt es in beiden. An den Rändern laufen die Werkzeuge auseinander.
6:17 Terraform kann zum Beispiel Mock-Daten in eigene Dateien auslagern und steuern, ob ein Override im Plan oder im Apply greift. OpenTofu erlaubt dafür Overrides für einzelne Instanzen und Mock-Provider mit for_each. Achten Sie auf die Formulierung: nicht dokumentiert heißt nicht zwingend nicht vorhanden, aber eben nicht zugesichert. Der Stand bezieht sich auf Terraform 1.16 und OpenTofu 1.13.
6:41 Die praktische Konsequenz ist schlicht: Wer seine Module für beide Werkzeuge pflegt, bleibt bei der gemeinsamen Teilmenge.
Linting und Sicherheitsprüfungen
6:49 Tests prüfen, was man gezielt prüfen will. Regelwerke finden das, woran niemand gedacht hat — vorausgesetzt, es gibt überhaupt Regeln für die eigene Plattform. TFLint ist so etwas wie die Rechtschreibprüfung für Infrastruktur-Code. Es meckert über ungenutzte Variablen, fehlende Versionsangaben und Ähnliches, das zwar funktioniert, aber auf Dauer Ärger macht. Die Konfiguration hier ist bewusst schlank.
7:14 Sie aktiviert das mitgelieferte Plugin für die Terraform-Sprache mit dem empfohlenen Regelsatz und schaltet zusätzlich eine Regel ein, die für jede Variable eine Beschreibung verlangt. Gerade bei geteilten Modulen ist das Gold wert. Vor dem ersten Lauf lädt ein init die Plugins, danach prüft TFLint rekursiv alle Ordner.
7:33 Eine Einschränkung laut Doku: TFLint versteht die Terraform-Sprache bis Version 1.15. Checkov ist ein Sicherheitsscanner mit einem großen Regelwerk für riskante Einstellungen. Er lässt sich auf zwei Arten einsetzen, und beide stehen auf der Folie. Der erste Aufruf scannt einfach den Code im Verzeichnis. Der zweite ist aufwendiger, aber gründlicher: Erst wird ein Plan gespeichert, dann als JSON ausgegeben, und dieses JSON prüft Checkov.
8:00 Der Vorteil ist, dass der Scanner dann die aufgelösten Werte sieht — also das, was nach allen Variablen und Ausdrücken tatsächlich angelegt würde. Mit OpenTofu funktioniert das genauso, die JSON-Darstellung des Plans ist dieselbe und wird gleich geprüft. Jetzt kommt der unbequeme Teil, und er ist wichtig. Die großen Regelwerke sind für die großen Clouds geschrieben.
8:23 TFLint pflegt Regelsätze für AWS, Azure und Google Cloud, aber keinen für den Docker-Provider. Checkov kennt keine einzige Regel für Docker-Container, Images oder Netze. Ein grünes Ergebnis heißt für Saatplan also nicht: alles sicher, sondern: nichts geprüft. Das ist kein Grund, die Werkzeuge wegzulassen. Sie prüfen weiterhin Sprache und Module, etwa ob Modulquellen auf eine feste Version gepinnt sind.
8:49 Und wer mehr will, kann eigene Regeln schreiben — in Checkov als YAML-Policies, in TFLint als Plugin oder in Rego.
Smoke Tests und Aufräumen
8:57 Bis hierhin haben wir geprüft, ob die Konfiguration stimmt. Jetzt die Frage, die Anwender wirklich interessiert: Der Container läuft — aber antwortet der Dienst auch? Ein Smoke Test ist der Moment, in dem man nach der Reparatur das Gerät einschaltet und schaut, ob es raucht. Der Test hier hat zwei Schritte. Der erste run-Block stellt die Umgebung wirklich bereit, und zwar mit dem Standard, also per Apply.
9:22 Der zweite ruft ein kleines Hilfsmodul auf, das die Adresse von saatplan-web abfragt, und erwartet als Antwort den Statuscode 200 — alles in Ordnung. Die Adresse kommt direkt aus dem Ergebnis des ersten Schritts. Das Hilfsmodul nutzt dafür den HTTP-Provider von HashiCorp, und ein Wiederholungsmechanismus überbrückt die Sekunden, die ein Dienst nach dem Start braucht.
9:44 Tests mit echter Umgebung sind langsam und aufwendig, also sollten sie sich lohnen. Sie lohnen sich immer dann, wenn das Verhalten des Providers selbst die Frage ist: Wird der Port wirklich gebunden, hängt der Container im richtigen Netz, ist das Volume eingebunden? Und natürlich, wenn ein Dienst antworten muss und nicht nur existieren. Für alles andere sind sie die falsche Wahl.
10:06 Eingabevalidierung, Namenslogik und Outputs klären Plan-Tests mit Mocks schneller und zuverlässiger. In einer Cloud kommt noch eine Kategorie hinzu, die kein Mock nachbilden kann: Berechtigungen und Quotas. Die zeigen sich erst, wenn wirklich jemand anklopft. Wer echte Ressourcen anlegt, muss sie auch wieder loswerden — und genau da lauern die Fallen.
10:27 Die gute Nachricht zuerst: Am Ende jeder Testdatei wird in umgekehrter Reihenfolge zerstört, auch wenn Prüfungen rot waren. Scheitert aber das Zerstören selbst, gibt das Werkzeug nur eine Liste der Reste aus; wegräumen muss dann ein Mensch. Noch unangenehmer ist ein harter Abbruch, denn dann bleibt einfach alles stehen. Deshalb sollten Testcontainer per Label markiert sein, damit man sie gezielt findet.
10:51 Und die wichtigste Regel: Tests mit Apply laufen auf einem eigenen Docker-Host oder mit eigenem Namenspräfix, niemals neben der Produktion.
Übung
10:59 Zeit, die Prüfkette selbst zu bauen. Das Ziel ist nicht nur, dass alles grün wird — sondern dass jeder Test beweist, dass er auch rot werden kann. In dieser Übung sichern Sie die Saatplan-Module mit Tests ab. Die Fähigkeit dahinter ist eine Abwägung: für ein Infrastrukturmodul die passenden Prüfungen auszuwählen und dabei positive wie negative Fälle ohne reale Umgebung zu testen.
11:23 Der Erfolg ist klar messbar. Terraform test und tofu test laufen ohne Docker-Host grün. Und drei typische Fehler machen sie zuverlässig rot: ein veröffentlichter Datenbank-Port, ein Port unter 1024 und ein falscher Output. Wer noch Zeit und Lust hat, nimmt sich die Zusatzaufgabe vor: einen Smoke Test mit echtem Apply gegen den lokalen Docker-Socket, der hinterher nachweislich aufräumt.
11:47 Die Schritte folgen der Pyramide von vorhin, von billig zu aufwendiger. Zuerst richten Sie die schnellen Prüfungen für beide Module ein: Formatierung, Validierung und TFLint. Dann kommt der Negativtest für den zu niedrigen Web-Port, danach der Plan-Test, der jeden veröffentlichten Datenbank-Port ablehnt. Im vierten Schritt holen Sie Mock und Override dazu, um die Outputs gegen feste Werte zu prüfen.
12:10 Und der letzte Schritt ist der entscheidende, auch wenn er sich seltsam anfühlt: Brechen Sie jeden Test einmal absichtlich und sehen Sie zu, wie er rot wird. Denn ein Test, der nie rot war, hat noch nichts bewiesen.
Dieses Modul als Schulung für Ihr Team
Das Video zeigt den Stoff. In der Schulung arbeitet Ihr Team damit — an Ihrem eigenen Code, mit Übungen und mit den Fragen, die ein Video nicht beantwortet. Sie wählen die Module aus Terraform und OpenTofu in der Praxis, wir bauen daraus ein Programm.
5 Tage·ab 900 EUR netto pro Tag (bis 3 Teilnehmende) ·Termin nach Vereinbarung