¿Cómo probar una configuración de Terraform?

37

Si tuviera una configuración de Terraform que tuviera un grado moderado de complejidad, ¿cómo escribiría pruebas en torno a la configuración que podría ejecutarse como parte de una tubería de Integración continua / Entrega continua?

Como ejemplo, puede tener una configuración de varias nubes que especifique el siguiente estado deseado:

  • Servicios de contenedor de Azure para alojar Docker en Azure
  • Azure Blob Storage
  • SQL Azure
  • Servicio de contenedor EC2 para alojar Docker en AWS
  • Servicio de almacenamiento de Amazon S3
  • Base de datos de Amazon RDS SQL Server

Potencialmente terraform applypodría crear lo anterior desde cero, o pasar de un estado parcialmente desplegado al estado deseado anterior.

Soy consciente de que Terraform divide su trabajo en la etapa del plan de ejecución y en la fase de aplicación que realmente realiza cambios en la arquitectura de destino. ¿Se puede usar para escribir pruebas contra el plan de ejecución, si es así, existen marcos para ayudar a escribirlos?

Richard Slater
fuente
Interesante de hecho, posiblemente responda digno.
Richard Slater
No estoy usando Terraform, así que dejo que alguien con experiencia real escriba una respuesta :)
Tensibai

Respuestas:

20

Actualmente no hay una solución completa para esto integrado en Terraform, pero hay algunos bloques de construcción que podrían ser útiles para ayudar a escribir pruebas en un lenguaje de programación separado.

Terraform produce archivos de estado en formato JSON que, en principio, pueden ser utilizados por programas externos para extraer ciertos datos sobre lo que Terraform creó. Si bien este formato aún no se considera oficialmente estable, en la práctica cambia con poca frecuencia como para que las personas se hayan integrado con éxito, aceptando que podrían necesitar hacer ajustes a medida que actualizan Terraform.

La estrategia adecuada aquí dependerá en gran medida de lo que desea probar exactamente. Por ejemplo:

  • En un entorno que hace girar servidores virtuales, se pueden usar herramientas como Serverspec para ejecutar pruebas desde la perspectiva de estos servidores. Esto puede ejecutarse por separado de Terraform usando algún proceso fuera de banda, o como parte de la aplicación de Terraform usando el remote-execaprovisionador . Esto permite la verificación de preguntas como "¿puede el servidor llegar a la base de datos?", Pero no es adecuado para preguntas como "¿el grupo de seguridad de la instancia es lo suficientemente restrictivo?", Ya que la verificación robusta requiere acceso a datos desde fuera de la propia instancia.

  • Es posible escribir pruebas usando un marco de prueba existente (como RSpec para Ruby, unittestpara Python, etc.) que reúne identificadores o direcciones de recursos relevantes del archivo de estado de Terraform y luego usa el SDK de la plataforma relevante para recuperar datos sobre los recursos y afirmar que están configurados como se esperaba. Esta es una forma más general de la idea anterior, ejecutar las pruebas desde la perspectiva de un host fuera de la infraestructura bajo prueba y, por lo tanto, puede recopilar un conjunto más amplio de datos para hacer afirmaciones.

  • Para necesidades más modestas, uno puede elegir confiar en que el estado de Terraform es una representación precisa de la realidad (una suposición válida en muchos casos) y simplemente afirmar directamente sobre eso. Esto es más apropiado para casos simples de "pelusa", como verificar que se siga el esquema correcto de etiquetado de recursos para fines de asignación de costos.

Hay más discusión sobre esto en un tema relevante de Terraform Github .

En las últimas versiones de Terraform, se recomienda utilizar un back-end remoto para cualquier aplicación que no sea de juguete, pero eso significa que los datos de estado no están disponibles directamente en el disco local. Sin embargo, se puede recuperar una instantánea del backend remoto utilizando el terraform state pullcomando, que imprime los datos de estado con formato JSON en stdout para que pueda ser capturado y analizado por un programa de llamada.

Martin Atkins
fuente
12

Como actualización de esta pregunta, ahora hay Kitchen-Terraform que permite probar los archivos de configuración de Terraform sin romper los entornos de producción. El repositorio también incluye algunos ejemplos para diferentes proveedores de Terraform.

PrestonM
fuente
12

Recientemente abrimos Terratest , nuestra navaja suiza para probar el código de infraestructura.

Hoy, probablemente esté probando todo su código de infraestructura manualmente mediante la implementación, la validación y la eliminación de la implementación. Terratest te ayuda a automatizar este proceso:

  1. Escribe pruebas en Go.
  2. Use ayudantes en Terratest para ejecutar sus herramientas IaC reales (por ejemplo, Terraform, Packer, etc.) para implementar infraestructura real (por ejemplo, servidores) en un entorno real (por ejemplo, AWS).
  3. Use ayudantes en Terratest para validar que la infraestructura funciona correctamente en ese entorno al hacer solicitudes HTTP, llamadas API, conexiones SSH, etc.
  4. Use ayudantes en Terratest para anular la implementación de todo al final de la prueba.

Aquí hay una prueba de ejemplo para algún código de 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)

Estas son pruebas de integración y, dependiendo de lo que esté probando, puede tomar de 5 a 50 minutos. No es rápido (aunque con Docker y las etapas de prueba , puede acelerar algunas cosas), y tendrá que trabajar para que las pruebas sean confiables, pero vale la pena el tiempo.

Consulte el repositorio de Terratest para obtener documentos y muchos ejemplos de varios tipos de código de infraestructura y las pruebas correspondientes para ellos.

Yevgeniy Brikman
fuente
1
También escribí una publicación de blog que explica cómo probar uno de mis proyectos de ejemplo con Terratest con más detalle: brightfame.co/blog/… . Puede ser de valor para cualquiera. Saludos, Rob!
Rob Morgan
Gran fan de Terratest!
jlucktay
7

Además de todas las otras opciones mencionadas, me gustaría mencionar que InSpec 2.0 agregó soporte para API de proveedores de nube. Básicamente, puede continuar escribiendo IaC con Terraform, luego escribir verificaciones de conformidad con InSpec para sus recursos en la nube. Además, InSpec admite pruebas de escritura para máquinas individuales si alguna vez lo necesita.

Aquí hay un artículo de Christoph Hartmann (cocreador de Inspec) sobre cómo utilizar Inspec con Terraform: https://lollyrock.com/articles/inspec-terraform/

Yekta Leblebici
fuente
5

En Aws-Side hay https://github.com/k1LoW/awspec : debería ser posible alimentar en terraform.state y probar, si la terraforma aplicada es correcta.

Pero creo que, más allá de probar en la herramienta de bajo nivel, usted usó, probablemente sea una mejor idea, pensar en cómo probar infraestructuras enteras.

Estamos discutiendo sobre esta idea aquí:

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

Para probar invariantes por adelantado, no conozco una solución lista para usar ...

Hicimos algunos experimentos usando una mezcla de terraform plan -out=plan.dumpy greppor la ausencia de nombres de elementos. Aquí hay una discusión sobre un formato de plan más accesible: github.com/hashicorp/terraform/issues/11883

Pero en este momento estamos usando un proceso de revisión manual del plan para partes importantes de nuestra infraestructura.

jerger
fuente
44
El objetivo es probar que los cambios en la configuración de terraformación no rompan las necesidades esperadas, una vez implementado es demasiado tarde, en el mejor de los casos, se produce un error al ver que se ha eliminado un DB donde no debería, pero ya rompió el entorno de destino. .. la pregunta es sobre probar el código de terraformación, no probar el resultado final, pruebas unitarias versus pruebas de integración.
Tensibai
buen punto ... se agregó una sección para probar invariantes.
jerger
0

Vi este método elegante y de baja tecnología para probar Terraform sugerido por aparentementemart en un tema de GitHub. No es apropiado para cada situación, pero es excelente para verificar la lógica del módulo.

Cree un módulo raíz que incluya el módulo bajo prueba y verifique las salidas bajo prueba. Aquí hay un ejemplo simple que usa dos archivos:

  • main.tf eso correrá las pruebas
  • simple_module/outputs.tf que representa un módulo bajo prueba

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

Ejecuta las pruebas

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
fuente