Jak przetestować konfigurację Terraform?

37

Jeśli miałeś konfigurację Terraform o umiarkowanym stopniu złożoności, jak napisałbyś testy wokół konfiguracji, które można wykonać w ramach potoku ciągłej integracji / ciągłej dostawy?

Na przykład może istnieć konfiguracja obejmująca wiele chmur, która określa następujący pożądany stan:

  • Azure Container Services do obsługi Docker na platformie Azure
  • Azure Blob Storage
  • SQL Azure
  • Usługa kontenerowa EC2 do obsługi Dockera w AWS
  • Usługa magazynowania Amazon S3
  • Baza danych Amazon RDS SQL Server

Potencjalnie terraform applymoże stworzyć powyższe od zera lub przejść ze stanu częściowo wdrożonego do powyższego pożądanego stanu.

Wiem, że Terraform dzieli swoją pracę na etap planu wykonania i etap aplikacji, który faktycznie wprowadza zmiany w architekturze docelowej. Czy można to wykorzystać do napisania testów w stosunku do planu wykonania, jeśli tak, czy istnieją ramy pomagające je napisać?

Richard Slater
źródło
Może przydatne: github.com/hashicorp/terraform/issues/5059
Tensibai
Rzeczywiście interesujące, być może godne odpowiedzi.
Richard Slater
Sam nie używam terraformu, więc pozwalam komuś z prawdziwym doświadczeniem napisać odpowiedź :)
Tensibai,

Odpowiedzi:

20

Obecnie nie ma pełnego rozwiązania tego zintegrowanego z Terraform, ale istnieją pewne elementy składowe, które mogą być pomocne w pisaniu testów w oddzielnym języku programowania.

Terraform tworzy pliki stanu w formacie JSON, które w zasadzie mogą być używane przez programy zewnętrzne w celu wyodrębnienia niektórych danych o tym, co Terraform utworzył. Chociaż ten format nie jest jeszcze uważany za oficjalnie stabilny, w praktyce zmienia się on na tyle rzadko, że ludzie z powodzeniem się z nim zintegrowali, akceptując, że może być konieczne wprowadzenie zmian podczas aktualizacji Terraform.

Wybór odpowiedniej strategii zależy w dużej mierze od tego, co dokładnie chcesz przetestować. Na przykład:

  • W środowisku, w którym wirują serwery wirtualne, narzędzia takie jak Serverspec mogą być używane do uruchamiania testów z perspektywy tych serwerów. Może to być albo prowadzone oddzielnie od Terraform użyciu niektórych out-of-band procesu, lub jako część Terraform zastosować używając remote-execProvisioner . Umożliwia to weryfikację pytań typu „czy serwer może dotrzeć do bazy danych?”, Ale nie nadaje się do pytań typu „czy grupa zabezpieczeń instancji jest wystarczająco restrykcyjna?”, Ponieważ dokładne sprawdzenie wymaga dostępu do danych spoza samej instancji.

  • Możliwe jest pisanie testów przy użyciu istniejącego środowiska testowego (takiego jak RSpec dla Ruby, unittestdla Pythona itp.), Które zbierają odpowiednie identyfikatory zasobów lub adresy z pliku stanu Terraform, a następnie używają zestawu SDK odpowiedniej platformy do pobierania danych o zasobach i potwierdzania, że są skonfigurowane zgodnie z oczekiwaniami. Jest to bardziej ogólna forma poprzedniego pomysłu, polegająca na przeprowadzaniu testów z perspektywy hosta poza testowaną infrastrukturą, a zatem może gromadzić szerszy zestaw danych w celu potwierdzenia.

  • W przypadku bardziej skromnych potrzeb można ufać, że stan Terraform jest dokładnym odwzorowaniem rzeczywistości (w wielu przypadkach uzasadnione założenie) i po prostu bezpośrednio o tym twierdzić. Jest to najbardziej odpowiednie w prostych przypadkach „przypominających kłaczki”, takich jak sprawdzenie, czy przestrzegany jest prawidłowy schemat oznaczania zasobów do celów alokacji kosztów.

Jest więcej dyskusji na ten temat w odpowiednim numerze Terraform Github .

W najnowszych wersjach Terraform zdecydowanie zaleca się stosowanie zdalnego zaplecza dla dowolnej aplikacji innej niż zabawka, ale oznacza to, że dane stanu nie są bezpośrednio dostępne na dysku lokalnym. Jednak jego migawkę można pobrać ze zdalnego zaplecza za pomocą terraform state pullpolecenia, które drukuje dane stanu w formacie JSON na standardowe wyjście, aby można je było przechwycić i przeanalizować przez program wywołujący.

Martin Atkins
źródło
12

W ramach aktualizacji tego pytania dostępna jest teraz Kitchen-Terraform, która umożliwia testowanie plików konfiguracyjnych Terraform bez niszczenia środowisk produkcyjnych. Repozytorium zawiera również kilka przykładów dla różnych dostawców Terraform.

PrestonM
źródło
12

Niedawno otworzyliśmy Terratest , nasz szwajcarski scyzoryk do testowania kodu infrastruktury.

Dzisiaj prawdopodobnie testujesz cały kod infrastruktury ręcznie, wdrażając, sprawdzając i wycofując. Terratest pomaga zautomatyzować ten proces:

  1. Napisz testy w Go.
  2. Użyj pomocników w Terratest, aby uruchomić swoje prawdziwe narzędzia IaC (np. Terraform, Packer itp.) W celu wdrożenia prawdziwej infrastruktury (np. Serwerów) w prawdziwym środowisku (np. AWS).
  3. Użyj pomocników w Terratest, aby sprawdzić poprawność działania infrastruktury w tym środowisku, wykonując żądania HTTP, wywołania API, połączenia SSH itp.
  4. Użyj pomocników w Terratestie, aby cofnąć wszystko pod koniec testu.

Oto przykładowy test dla niektórych kodów Terraform:

terraformOptions := &terraform.Options {
  // The path to where your Terraform code is located
  TerraformDir: "../examples/terraform-basic-example",
}

// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)

// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer terraform.Destroy(t, terraformOptions)

// Run `terraform output` to get the value of an output variable
instanceUrl := terraform.Output(t, terraformOptions, "instance_url")

// Verify that we get back a 200 OK with the expected text
// It can take a minute or so for the Instance to boot up, so retry a few times
expected := "Hello, World"
maxRetries := 15
timeBetweenRetries := 5 * time.Second
http_helper.HttpGetWithRetry(t, instanceUrl, 200, expected, maxRetries, timeBetweenRetries)

Są to testy integracyjne, w zależności od tego, co testujesz, może to zająć od 5 do 50 minut. Nie jest to szybkie (chociaż używając Dockera i etapów testowania , możesz przyspieszyć niektóre rzeczy) i będziesz musiał pracować, aby testy były wiarygodne, ale warto poświęcić czas.

Sprawdź repozytorium Terratest, aby uzyskać dokumenty i wiele przykładów różnych rodzajów kodu infrastruktury i odpowiadających im testów.

Jewgienij Brikman
źródło
1
Napisałem również post na blogu, który szczegółowo omawia jeden z moich przykładowych projektów z Terratest: brightfame.co/blog/… . Może być wartościowy dla każdego. Pozdrawiam, Rob!
Rob Morgan
Wielki fan Terratest!
jlucktay
7

Oprócz wszystkich innych wymienionych opcji chciałbym wspomnieć, że InSpec 2.0 dodał obsługę interfejsów API dostawców chmury. Zasadniczo możesz kontynuować pisanie IaC za pomocą Terraform, a następnie pisać kontrole zgodności z InSpec dla zasobów w chmurze. Ponadto InSpec obsługuje pisanie testów dla poszczególnych komputerów, jeśli kiedykolwiek będzie to potrzebne.

Oto artykuł Christopha Hartmanna (współtwórcy Inspec) na temat używania Inspec z Terraform: https://lollyrock.com/articles/inspec-terraform/

Yekta Leblebici
źródło
5

Na Aws-Side znajduje się https://github.com/k1LoW/awspec - powinno być możliwe, aby wprowadzić terraform.state i przetestować, czy terraform został poprawnie zastosowany.

Ale myślę, że poza testowaniem narzędzia na niskim poziomie, którego użyłeś, to prawdopodobnie lepszy pomysł, aby pomyśleć o tym, jak przetestować całą infrastrukturę.

Omawiamy tutaj ten pomysł:

https://github.com/DomainDrivenArchitecture/dda-cloudspec/blob/development/README.md

Do testowania niezmienników z góry nie znam gotowego rozwiązania ...

Przeprowadziliśmy kilka eksperymentów, używając kombinacji nazw elementów terraform plan -out=plan.dumpi grepdla ich braku. Dyskusja na temat bardziej dostępnego formatu planu tutaj: github.com/hashicorp/terraform/issues/11883

Ale obecnie korzystamy z procesu ręcznego przeglądu planu dla ważnych części naszej infrastruktury.

jerger
źródło
4
Celem jest przetestowanie zmian w konfiguracji terraformu, które nie złamią oczekiwanych potrzeb, po wdrożeniu jest już za późno, w najlepszym razie masz błąd, widząc, że DB zostało usunięte tam, gdzie nie powinno, ale już złamałeś środowisko docelowe. .. pytanie dotyczy testowania kodu terraform, nie testowania wyniku końcowego, testów jednostkowych a testów integracyjnych.
Tensibai
dobra uwaga ... dodano sekcję testowania niezmienników.
jerger
0

Widziałem tę elegancką, mało zaawansowaną technologicznie metodę testowania Terraform sugerowaną przez najwyraźniej w temacie GitHub. Nie jest odpowiedni dla każdej sytuacji, ale świetnie sprawdza się w sprawdzaniu logiki modułu.

Utwórz moduł główny, który zawiera testowany moduł i weryfikuje wyniki testu. Oto prosty przykład z użyciem dwóch plików:

  • main.tf które przeprowadzą testy
  • simple_module/outputs.tf który reprezentuje testowany moduł

./main.tf

terraform {
  required_version = ">= 0.12"
}

module "simple_module" {
  source = "./simple_module"
}

locals {
  expected = 1
  got      = module.simple_module.module-returns-1
}

# Test Output
output "expect-1" {
  value = upper(local.expected == local.got)
}

output "expect-other" {
  value = "other" == local.got ? upper(true) : "FALSE. Got ${local.got}"
}

./simple_module/outputs.tf

output "module-returns-1" {
  value = 1
}

Uruchom testy

terraform init
terraform apply -auto-approve
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

expect-1 = TRUE
expect-other = FALSE. Got 1
mmell
źródło