Im Oktober 2023, genauer gesagt mit dem Release 1.6, hat Terraform sein eigenes Testframework bekommen. Bisher können damit hauptsächlich Inputs validiert werden. Seit Version 1.7 sind auch Mocks von Ressourcen und Providern möglich, damit müssen Infrastrukturen also nicht mehr real erstellt werden. Das spart Zeit und Geld.
Testen. Du solltest testen!
Es folgt ein kleiner Werbeblock – das Angebot gilt nur heute und ist völlig unverbindlich! Diese Gratis-Artikel sagen dir, warum das mit dem Testen so wichtig ist:
- Warum ihr testen solltet?
» Gute Gründe für Tests in Softwareprojekten - Hier die Realität, wozu Tests auch sehr wichtig sind
» Effiziente Modernisierung – Tests als Grundpfeiler für eine erfolgreiche Code-Transformation - Jetzt noch ein bisschen Futter, was dazu führen kann, dass es zum vorherigen Link kommt.
» Die Evolution der Softwarearchitektur
Ein Test in Terraform mit AWS
Wir wollen mit Hilfe des AWS Key Management Service einen Key zum Verschlüsseln einer Ressource erstellen. Ich empfehle grundsätzlich, nie die eigens von AWS generierten zu verwenden. Irgendwann fällt es einem immer auf die Füße, daher immer eigene Keys generieren lassen. Mehr dazu aber ein anderes Mal.
In einem einfachen Beispiel testen wir die Erstellung des Keys und legen einen Alias dazu an, der zusätzlich validiert wird.
Die Dateistruktur sieht so aus:
Testfiles enden immer mit dem Postfix .tftest.hcl
. kms.tf
ist hier so etwas wie ein Helper, der uns den KMS Key erstellt, auf den wir ein Alias anlegen wollen.
// main.tf terraform { required_providers { aws = { source = "hashicorp/aws" } } } variable "kms_key_alias" { type = string default = "alias/my-alias" validation { condition = length(var.kms_key_alias) >= 9 error_message = "The kms_key_alias name must be longer than 3 chars and contain 'alias/' prefix" } } variable "kms_key_id" { type = string default = "null" } resource "aws_kms_alias" "alias-key" { name = var.kms_key_alias != "" ? var.kms_key_alias : null target_key_id = var.kms_key_id != "" ? var.kms_key_id : null }
// kms.tf resource "aws_kms_key" "test-key" { description = "test KMS key" deletion_window_in_days = 7 } output "kms_key_id" { value = aws_kms_key.test-key.arn }
// basic_with_kms.tftest.hcl run "setup" { // wie sonst auch, führt 'terraform test' ein apply aus command = apply // erstellt uns den KMS Key im AWS module { source = "./setup" } } run "create_kms_key" { command = plan variables { kms_key_id = run.setup.kms_key_id } assert { condition = aws_kms_alias.alias-key.target_key_id != null error_message = "KMS key ID attribute value is null" } } run "test_alias_creation" { command = plan variables { kms_key_alias = "alias/alias-name" kms_key_id = "111199992-199219191" } assert { condition = startswith(aws_kms_alias.alias-key.name, "alias/") error_message = "KMS key alias name did not start with the expected value of ‘alias/*’." } assert { condition = aws_kms_alias.alias-key.target_key_id == "111199992-199219191" error_message = "KMS key target_id did not match with the expected value of ‘111199992-199219191’." } }
Ein Extra-Häppchen: Mocks
Jeder Entwickler freut sich über Mocks. Und auch bei IaC ist es ein Grund zum Jubeln, wenn wir die Infrastruktur nicht jedesmal vollständig bauen und abreißen müssen: Es spart einfach Zeit und Geld. Aktuell sind Terraform Mocks noch in der Beta-Phase, aber sie können offiziell schon verwendet werden.
Hier direkt eine Umsetzung mit dem KMS Key aus dem vorherigen Beispiel:
//main.tf terraform { required_providers { aws = { source = "hashicorp/aws" } } } variable "kms_key_alias" { type = string default = "alias/my-alias" validation { condition = length(var.kms_key_alias) >= 9 error_message = "The kms_key_alias name must be longer than 3 chars and contain 'alias/' prefix" } } variable "kms_key_id" { type = string default = "null" } resource "aws_kms_alias" "alias-key" { name = var.kms_key_alias != "" ? var.kms_key_alias : null target_key_id = var.kms_key_id != "" ? var.kms_key_id : null } resource "aws_kms_key" "test-key" { description = "test KMS key for CodeCommit repo" deletion_window_in_days = 7 } output "kms_key_id" { value = aws_kms_key.test-key.arn }
// basic_with_kms_mock.tftest.hcl mock_provider "aws" { // der eigentliche Mock für unseren KMS Key mock_resource "aws_kms_key" { defaults = { arn = "arn:aws:kms:eu-central-1:123456789012:key/111199992-199219191" } } } run "create_kms_mock_key" { assert { condition = aws_kms_key.test-key.arn != null error_message = "KMS key could not created" } } run "test_alias_creation" { variables { kms_key_alias = "alias/alias-name" kms_key_id = "111199992-199219191" } assert { condition = startswith(aws_kms_alias.alias-key.name, "alias/") error_message = "KMS key alias name did not start with the expected value of ‘alias/*’." } assert { condition = aws_kms_alias.alias-key.target_key_id == "111199992-199219191" error_message = "KMS key target_id did not match with the expected value of ‘111199992-199219191’." } }
Time is running …
Alles schön und gut, aber was bedeutet das für die Laufzeiten? Lasst uns also einen Blick darauf werfen:
Hinweis: aws-vault wird hier nicht benötigt, da wir mocken und damit keine AWS-Verbindung aufbauen.
Wir sehen eine große Zeitdifferenz von ca. fünf Sekunden bei so einem kleinen Test und einfachen Service. Der Mock hat sich jetzt also schon gelohnt.
Fazit
Wir haben gesehen: Mocks lohnen sich, da wir keine oder weniger Infrastruktur bei AWS auf- und abbauen müssen. Je nach Service kommt bei den Kosten eine Menge zusammen, wenn unsere Tests täglich viele Male laufen.
… übrigens: Wenn ihr das alles nachvollziehen möchtet, haben wir für euch den Code auch noch einmal in einem Repo abgelegt.
So, test and mock it!
Schreibe einen Kommentar