Das war 2025 & Jahresausblick 2025
Jahresrückblick 2024 und Ausblick auf 2025 bei Infralovers 2024 war für uns ein Jahr voller Innovationen und neuer Lernmöglichkeiten. Wir haben unser
Infrastructure as Code (IaC) hat die Art und Weise, wie wir Cloud-Ressourcen verwalten, revolutioniert, und Terraform hat sich zu einem führenden Tool in diesem Bereich entwickelt. Um die Zuverlässigkeit und Stabilität von Terraform-Konfigurationen zu gewährleisten, ist das Testen entscheidend. In diesem Blog werden wir verschiedene Ansätze für das Testen in Terraform untersuchen und Ihnen dabei helfen, Best Practices für ein sicheres Infrastrukturmanagement anzuwenden.
Das Testen von Terraform Code ist wichtig für:
Terraform bietet verschiedene Methoden zum Testen der Infrastruktur, von Unit-Tests bis hin zu Acceptance-Tests. Sehen wir uns jeden Ansatz an.
Unit-Tests sind eine grundlegende Praxis in der Softwareentwicklung und das gilt auch für Terraform-Plugins. Unit-Tests werden verwendet, um die Korrektheit von kleinen, isolierten Codeeinheiten zu überprüfen, wie z.B. Hilfsfunktionen oder Methoden, die API-Antworten in Terraform-freundliche Datenstrukturen umwandeln. Diese Tests erfordern in der Regel keine Netzwerkverbindungen und konzentrieren sich auf die Überprüfung einzelner Teile der Logik in Isolation.
Ein häufiger Anwendungsfall in Terraform-Plugins ist die Verflachung komplexer Datenstrukturen, die von APIs zurückgegeben werden, in einfachere Formate, die im Terraform-Status gespeichert werden können. AWS-Sicherheitsgruppenregeln werden beispielsweise oft in einer verschachtelten Struktur geliefert, und eine Flattener-Funktion wird benötigt, um diese Daten in ein Format umzuwandeln, das Terraform verwalten kann. Im Folgenden ist ein Beispiel für einen Unit-Test zu sehen, der eine Flattening-Funktion für AWS-Sicherheitsgruppenregeln verifiziert:
1func TestFlattenSecurityGroups(t *testing.T) {
2 cases := []struct {
3 ownerId *string
4 pairs []*ec2.UserIdGroupPair
5 expected []*GroupIdentifier
6 }{
7 // Testfälle hier...
8 }
9 for _, c := range cases {
10 out := flattenSecurityGroups(c.pairs, c.ownerId)
11 if !reflect.DeepEqual(out, c.expected) {
12 t.Fatalf("Error matching output and expected: %#v vs %#v", out, c.expected)
13 }
14 }
15}
Dieser Testfall prüft, ob die Flattening-Funktion verschiedene Varianten von AWS-Sicherheitsgruppenregeln korrekt umwandelt, und stellt sicher, dass die Logik wie erwartet funktioniert.
Acceptance-Tests sind ein wichtiger Teil des Testens von Terraform Plugins. Diese Tests wurden entwickelt, um das tatsächliche Verhalten von Terraform bei der Interaktion mit der realen Infrastruktur zu überprüfen. Das Ziel von Acceptance-Tests ist es, sicherzustellen, dass Terraform Ressourcen korrekt erstellen, verändern und zerstören kann und dass die Statusdatei die Ressourcenkonfiguration korrekt wiedergibt.
Das Test-Framework von Terraform unterstützt eine Vielzahl von Testmustern, die es einfach machen, Acceptance-Tests zu schreiben und auszuführen. Acceptance-Tests können in jeder Umgebung ausgeführt werden, die in der Lage ist, Go-Tests auszuführen, z. B. auf einer lokalen Workstation-Befehlszeile oder einem Continuous-Integration-Runner, wie z. B. GitHub Actions.
Der grundlegendste Akzeptanztest prüft, ob eine Ressource erstellt werden kann und ob ihre Attribute korrekt in der Terraform-Statusdatei gespeichert sind. Dieser Test stellt sicher, dass Terraform eine Konfiguration ohne Fehler anwenden kann und dass die entfernte Ressource mit Terraform Status übereinstimmt.
1package example
2// example.Widget stellt einen konkreten Go-Typ dar, der eine API-Ressource repräsentiert
3func TestAccExampleWidget_basic(t *testing.T) {
4 var widget example.Widget
5 // es wird einen zufälligen Namen für jeden Widget-Testlauf erzeugen, um
6 // Kollisionen durch mehrere gleichzeitige Tests zu vermeiden.
7 // Das acctest-Paket enthält viele Hilfsprogramme wie RandStringFromCharSet
8 // Siehe https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/helper/acctest
9 rName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
10 resource.Test(t, resource.TestCase{
11 PreCheck: func() { testAccPreCheck(t) },
12 Providers: testAccProviders,
13 CheckDestroy: testAccCheckExampleResourceDestroy,
14 Steps: []resource.TestStep{
15 {
16 // Es wird eine dynamische Konfiguration mit dem zufälligen Namen von oben verwenden
17 Config: testAccExampleResource(rName),
18 // Representiert einen einfachen Test, der sowohl remote als auch lokale Werte überprüft
19 ConfigStateChecks: []statecheck.StateCheck{
20 // benutzerdefinierte State-Überprüfung - Abfrage der API zum Abrufen des Widget-Objekts
21 stateCheckExampleResourceExists("example_widget.foo", &widget),
22 // benutzerdefinierte State-Überprüfung - Überprüfung von Remote-Werten
23 stateCheckExampleWidgetValues(widget, rName),
24 // eingebaute State-Überprüfung - Überprüfung lokaler (State-)Werte
25 statecheck.ExpectKnownValue("example_widget.foo", tfjsonpath.New("active"), knownvalue.Bool(true)),
26 statecheck.ExpectKnownValue("example_widget.foo", tfjsonpath.New("name"), knownvalue.StringExact(rName)),
27 },
28 },
29 },
30 })
31}
32// testAccExampleResource gibt eine Konfiguration für ein Beispiel-Widget mit dem angegebenen Namen zurück
33func testAccExampleResource(name string) string {
34 return fmt.Sprintf(`
35resource "example_widget" "foo" {
36 active = true
37 name = "%s"
38}`, name)
39}
Dieser Test prüft, ob eine Widget-Ressource mit den richtigen Attributen erstellt wird und ob diese Attribute sowohl in der Terraform- Statusdatei als auch in der Remote-API korrekt gespeichert sind.
Regressionstests sind essentiell, um sicherzustellen, dass Bugfixes oder Updates für Terraform Plugins keine neuen Probleme einführen. Wenn ein Fehler gemeldet wird, sollte ein Regressionstest folgen, der sicherstellt, dass das Problem behoben wird, ohne die bestehende Funktionalität zu zerstören.
Regressionstests sind besonders nützlich, um zu überprüfen, ob Codeänderungen, die einen Fehler beheben sollen, nicht unbeabsichtigt andere Teile der Codebasis beeinflussen. Diese Tests sollten eindeutig benannt werden, um das behobene Problem widerzuspiegeln, und sollten neben der Fehlerbehebung hinzugefügt werden, um eine umfassende Überprüfung zu gewährleisten.
Ein Beispiel für Regressionstests ist hier zu sehen.
Das native Testing Framework von Terraform ermöglicht die Validierung der Modulkonfiguration durch den Build einer ephemeren Infrastruktur. Diese Tests laufen unabhängig von den regulären Plan- oder Apply-Workflows. Anstatt die bestehende Infrastruktur zu verändern, erstellen die Tests temporäre Ressourcen, die Terraform nur während der Testphase verwaltet. Dieser Ansatz stellt sicher, dass Tests nicht in bestehenden Statusdateien eingreifen und bietet eine sichere Umgebung, um Änderungen zu validieren.
Die Syntax für Terraform-Tests ist relativ einfach. Es werden .tftest.hcl
-Dateien für die Definition von Testfällen und optionale Hilfsmodule für die Verwaltung von testspezifischen Ressourcen verwendet. Sehen wir uns nun an, wie man diese Tests Schritt für Schritt implementiert.
Die Verzeichnisstruktur für native Terraform-Tests sieht etwa so aus:
1.
2├── LICENSE
3├── README.md
4├── main.tf
5├── outputs.tf
6├── terraform.tf
7├── tests
8│ ├── setup
9│ │ ├── main.tf
10│ └── website.tftest.hcl
11├── variables.tf
12└── www
13 ├── error.html
14 └── index.html
Die Datei main.tf
definiert die zu testende Infrastruktur (z. B. ein S3-Bucket). Der Ordner tests
enthält die Testkonfiguration.
Terraform-Tests bestehen aus zwei Komponenten:
.tftest.hcl
und enthalten die eigentliche Testlogik.Das Verzeichnis tests
enthält die Testkonfigurationsdatei website.tftest.hcl
, die zwei Hauptblöcke enthält:
true
bewertet werden, damit der Test erfolgreich ist.Hier ist ein Beispiel für die Datei website.tftest.hcl
:
1run "setup_tests" {
2 module {
3 source = "./tests/setup"
4 }
5}
6run "create_bucket" {
7 command = apply
8 variables {
9 bucket_name = "${run.setup_tests.bucket_prefix}-aws-s3-website-test"
10 }
11 assert {
12 condition = aws_s3_bucket.s3_bucket.bucket == "${run.setup_tests.bucket_prefix}-aws-s3-website-test"
13 error_message = "Invalid bucket name"
14 }
15 assert {
16 condition = aws_s3_object.index.etag == filemd5("./www/index.html")
17 error_message = "Invalid eTag for index.html"
18 }
19 assert {
20 condition = aws_s3_object.error.etag == filemd5("./www/error.html")
21 error_message = "Invalid eTag for error.html"
22 }
23}
In dieser Konfiguration:
run setup_tests
erzeugt einen zufälligen Bucket-Namen mit Hilfe des Helper-Moduls.run create_bucket
prüft, ob der Bucketname und die hochgeladenen Dateien mit den erwarteten Werten übereinstimmen.Um die Tests auszuführen, muss Terraform initialisiert und alle benötigten Provider installiert werden:
1$ terraform init
Als nächstes werden die Tests durchgeführt:
1$ terraform test
Wenn dies erfolgreich war, erhalten wir eine Ausgabe wie diese:
1Success! 2 passed, 0 failed.
Um das Testen zu beschleunigen und den Overhead bei der Erstellung echter Ressourcen zu vermeiden, ermöglicht Terraform das Mocking. Mocking simuliert Ressourcen und Datenquellen, so dass diese nicht mehr bereitgestellt werden müssen.
Ein Beispiel für eine reale Ressource, die wir mocken wollen, wäre:
1resource "aws_instance" "backend_api" {
2 ami = data.aws_ami.ubuntu.id
3 instance_type = "t3.micro"
4 tags = {
5 Name = "backend"
6 }
7}
Beispiel für das Mocking einer EC2-Instanz:
1override_resource {
2 target = aws_instance.backend_api
3}
4run "check_backend_api" {
5 assert {
6 condition = aws_instance.backend_api.tags.Name == "backend"
7 error_message = "Invalid name tag"
8 }
9}
Dadurch wird eine EC2-Instanz simuliert, anstatt sie zu erstellen, so dass wir Konfigurationen schneller testen können.
HCP Terraform ist eng mit dem Testen von Modulen verknüpft und bietet Entwicklern und Unternehmen, die Terraform verwenden, mehrere Vorteile. So können wir die von uns erstellten Module in eine private Registry hochladen, die viele Funktionalitäten bietet:
1$ terraform test -cloud-run=app.terraform.io/ORG/s3-website-tests/aws
Das Testen mit Terraform ist ein wichtiger Prozess, um sicherzustellen, dass der Code für die Infrastruktur korrekt ist, bevor er in der Produktion eingesetzt wird. Durch die Verwendung von Tests können wir unsere Konfigurationen mit minimalen Auswirkungen auf unsere bestehenden Ressourcen validieren. In diesem Artikel wurde das Wesentliche behandelt, von der Einrichtung von Tests bis hin zu deren Veröffentlichung und der Remote-Ausführung von Tests in HCP Terraform.
Denken Sie bei der Weiterentwicklung Ihrer Terraform-Konfigurationen daran, die Tests auf dem neuesten Stand zu halten, um die Vorhersagbarkeit der Infrastruktur aufrechtzuerhalten und das Einführen von Breaking-Changes.
Sie interessieren sich für unsere Trainings oder haben einfach eine Frage, die beantwortet werden muss? Sie können uns jederzeit kontaktieren! Wir werden unser Bestes tun, um alle Ihre Fragen zu beantworten.
Hier kontaktieren