Come testare una configurazione Terraform?


37

Se avessi una configurazione Terraform con un moderato grado di complessità, come scriveresti dei test intorno alla configurazione che potrebbero essere eseguiti come parte di una pipeline di integrazione continua / consegna continua?

Ad esempio, potresti avere una configurazione multi-cloud che specifica il seguente stato desiderato:

  • Servizi contenitore di Azure per ospitare Docker in Azure
  • Archiviazione BLOB di Azure
  • SQL Azure
  • Servizio container EC2 per ospitare Docker in AWS
  • Servizio di archiviazione Amazon S3
  • Database Amazon RDS SQL Server

Potenzialmente terraform applypotrebbe creare il precedente da zero o passare da uno stato parzialmente distribuito allo stato desiderato sopra.

Sono consapevole che Terraform suddivide il suo lavoro nella fase del piano di esecuzione e nella fase dell'applicazione che in realtà apporta modifiche all'architettura di destinazione. Questo può essere usato per scrivere test rispetto al piano di esecuzione, se sì ci sono framework per aiutarli a scriverli?



Davvero interessante, forse risposta degna.
Richard Slater,

Non sto usando terraform me stesso, quindi lascio che qualcuno con esperienza reale scriva una risposta :)
Tensibai,

Risposte:


20

Al momento non esiste una soluzione completa a questo integrato in Terraform, ma ci sono alcuni elementi che potrebbero essere utili per aiutare a scrivere test in un linguaggio di programmazione separato.

Terraform produce file di stato in formato JSON che, in linea di principio, possono essere utilizzati da programmi esterni per estrarre determinati dati su ciò che Terraform ha creato. Sebbene questo formato non sia ancora considerato ufficialmente stabile, in pratica cambia abbastanza raramente che le persone si sono integrate con successo, accettando che potrebbe essere necessario apportare modifiche durante l'aggiornamento di Terraform.

Quale strategia è appropriata qui dipenderà molto da ciò che si desidera testare. Per esempio:

  • In un ambiente che sta trasformando server virtuali, strumenti come Serverspec possono essere utilizzati per eseguire test dal punto di vista di questi server. Questo può essere eseguito separatamente da Terraform utilizzando alcuni processi fuori banda o come parte di Terraform applicare utilizzando il remote-execprovisioner . Ciò consente la verifica di domande come "il server può raggiungere il database?", Ma non è adatto a domande come "il gruppo di sicurezza dell'istanza è abbastanza restrittivo?", Dal momento che il controllo rigoroso richiede l'accesso ai dati dall'esterno dell'istanza stessa.

  • È possibile scrivere test utilizzando un framework di test esistente (come RSpec per Ruby, unittestper Python, ecc.) Che raccolga gli ID o gli indirizzi delle risorse rilevanti dal file di stato Terraform e quindi utilizza l'SDK della piattaforma pertinente per recuperare i dati sulle risorse e affermare che sono impostati come previsto. Questa è una forma più generale dell'idea precedente, che esegue i test dal punto di vista di un host al di fuori dell'infrastruttura in prova e può quindi raccogliere una serie più ampia di dati su cui fare affermazioni.

  • Per esigenze più modeste, si può scegliere di fidarsi che lo stato Terraform è una rappresentazione accurata della realtà (un presupposto valido in molti casi) e semplicemente affermarlo direttamente su questo. Ciò è particolarmente appropriato per semplici casi "simili a lanugine", come la verifica che lo schema di codifica delle risorse corretto venga seguito a fini di allocazione dei costi.

C'è qualche discussione in più su questo in un rilevante problema di Terraform Github .

Nelle ultime versioni di Terraform si consiglia vivamente di utilizzare un back-end remoto per qualsiasi applicazione non giocattolo, ma ciò significa che i dati sullo stato non sono direttamente disponibili sul disco locale. Tuttavia, è possibile recuperare un'istantanea dal back-end remoto utilizzando il terraform state pullcomando, che stampa i dati di stato in formato JSON su stdout in modo che possano essere acquisiti e analizzati da un programma chiamante.


12

Come aggiornamento a questa domanda, ora c'è Kitchen-Terraform che consente di testare i file di configurazione Terraform senza interrompere gli ambienti di produzione. Il repository include anche alcuni esempi per diversi fornitori di Terraform.


12

Di recente abbiamo aperto Terratest , il nostro coltellino svizzero per testare il codice dell'infrastruttura.

Oggi, probabilmente stai testando tutto il codice dell'infrastruttura manualmente distribuendo, convalidando e non implementando. Terratest ti aiuta ad automatizzare questo processo:

  1. Scrivi test in Go.
  2. Usa gli helper di Terratest per eseguire i tuoi veri strumenti IaC (ad es. Terraform, Packer, ecc.) Per distribuire infrastrutture reali (ad es. Server) in un ambiente reale (ad es. AWS).
  3. Usa gli helper in Terratest per verificare che l'infrastruttura funzioni correttamente in quell'ambiente effettuando richieste HTTP, chiamate API, connessioni SSH, ecc.
  4. Usa gli helper in Terratest per disimpegnare tutto alla fine del test.

Ecco un esempio di test per alcuni codici 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)

Questi sono test di integrazione e, a seconda di ciò che stai testando, possono richiedere da 5 a 50 minuti. Non è veloce (anche se usando Docker e le fasi di test , puoi accelerare alcune cose) e dovrai lavorare per rendere i test affidabili, ma vale la pena.

Dai un'occhiata al repository Terratest per i documenti e molti esempi di vari tipi di codice di infrastruttura e i test corrispondenti per loro.


1
Ho anche scritto un post sul blog che illustra in dettaglio uno dei miei progetti di esempio con Terratest in modo più dettagliato: brightfame.co/blog/… . Potrebbe essere di valore per chiunque. Saluti, Rob!
Rob Morgan,

Grande fan di Terratest!
Jlucktay,

7

Oltre a tutte le altre opzioni menzionate, vorrei ricordare che InSpec 2.0 ha aggiunto il supporto per le API del provider cloud. Fondamentalmente, puoi continuare a scrivere su IaC con Terraform, quindi scrivere controlli di conformità con InSpec per le tue risorse cloud. Inoltre, InSpec supporta la scrittura di test per le singole macchine se ne hai bisogno.

Ecco un articolo di Christoph Hartmann (co-creatore di Inspec) su come utilizzare Inspec con Terraform: https://lollyrock.com/articles/inspec-terraform/


5

Su Aws-Side c'è https://github.com/k1LoW/awspec - dovrebbe essere possibile, alimentare in terraform.state e testare, se terraform applicato correttamente.

Ma penso che, oltre a testare a basso livello lo strumento che hai usato, è probabilmente un'idea migliore pensare a come testare intere infrastrutture.

Stiamo discutendo di questa idea qui:

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

Per testare gli invarianti in anticipo, non conosco una soluzione pronta per l'uso ...

Abbiamo fatto alcuni esperimenti usando un mix di terraform plan -out=plan.dumpe grepper l'assenza di nomi di elementi. C'è una discussione su un formato di piano più accessibile qui: github.com/hashicorp/terraform/issues/11883

Ma al momento stiamo utilizzando un processo di revisione manuale del piano per parti importanti della nostra infrastruttura.


4
L'obiettivo è testare i cambiamenti nella configurazione terraform che non rompano i bisogni previsti, una volta distribuiti è troppo tardi, nella migliore delle ipotesi si ha un errore nel vedere che un DB è stato rimosso dove non dovrebbe, ma si è già rotto l'ambiente di destinazione. .. la domanda è di testare il codice terraform, non testare il risultato finale, unit test vs test di integrazione.
Tensibai,

buon punto ... aggiunta una sezione per testare gli invarianti.
jerger

0

Ho visto questo metodo elegante e di bassa tecnologia per testare Terraform suggerito da Apparentlymart in una discussione su GitHub. Non è appropriato per ogni situazione ma è ottimo per verificare la logica del modulo.

Creare un modulo radice che include il modulo in prova e verifica gli output in fase di test. Ecco un semplice esempio usando due file:

  • main.tf che eseguirà i test
  • simple_module/outputs.tf che rappresenta un modulo in prova

./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
}

Esegui i test

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

Outputs:

expect-1 = TRUE
expect-other = FALSE. Got 1
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.