Comment tester une configuration Terraform?


37

Si vous aviez une configuration Terraform moyennement complexe, comment écririez-vous des tests autour de la configuration pouvant être exécutés dans le cadre d'un pipeline Continuous Integration / Continuous Delivery?

Par exemple, vous pouvez avoir une configuration multi-cloud qui spécifie l'état souhaité suivant:

  • Azure Container Services va héberger Docker dans Azure
  • Azure Blob Storage
  • SQL Azure
  • EC2 Container Service pour héberger Docker dans AWS
  • Service de stockage Amazon S3
  • Base de données Amazon RDS SQL Server

Potentiellement, terraform applypourrait créer ce qui précède à partir de zéro ou passer d’un état partiellement déployé à l’état souhaité ci-dessus.

Je suis conscient que Terraform divise son travail en une phase de plan d'exécution et une phase d' application qui modifie réellement l'architecture cible. Cela peut-il être utilisé pour écrire des tests par rapport au plan d’exécution? Si oui, existe-t-il des cadres pour aider à les écrire?



Intéressant en effet, répondez éventuellement digne.
Richard Slater

Je n'utilise pas moi-même terraform, alors je laisse une personne ayant une expérience réelle écrire une réponse :)
Tensibai

Réponses:


20

Il n’existe actuellement aucune solution complète à cette intégration dans Terraform, mais certains éléments de base pourraient être utiles pour faciliter la rédaction de tests dans un langage de programmation distinct.

Terraform produit des fichiers d'état au format JSON qui peuvent, en principe, être utilisés par des programmes externes pour extraire certaines données sur ce que Terraform a créé. Bien que ce format ne soit pas encore considéré comme officiellement stable, il change en pratique assez peu pour que les utilisateurs l’intègrent avec succès, acceptant ainsi la nécessité de procéder à des ajustements lors de la mise à niveau de Terraform.

Quelle stratégie est appropriée ici dépendra beaucoup de ce que vous voulez tester exactement. Par exemple:

  • Dans un environnement en train de créer des serveurs virtuels, des outils tels que Serverspec peuvent être utilisés pour exécuter des tests du point de vue de ces serveurs. Cela peut être exécuté séparément de Terraform en utilisant un processus hors bande, ou dans le cadre de l'application Terraform à l'aide du remote-execprovisioner . Cela permet de vérifier des questions telles que "le serveur peut-il accéder à la base de données?", Mais ne convient pas à des questions telles que "le groupe de sécurité de l'instance est-il suffisamment restrictif?"

  • Il est possible d'écrire des tests en utilisant un framework de test existant (tel que RSpec pour Ruby, unittestpour Python, etc.) qui rassemblent les identifiants de ressources ou adresses pertinents du fichier d'état de Terraform, puis utilisent le SDK de la plate-forme correspondante pour extraire des données sur les ressources et affirmer que ils sont configurés comme prévu. Il s’agit d’une forme plus générale de l’idée précédente, qui consiste à exécuter les tests du point de vue d’un hôte situé en dehors de l’infrastructure testée, ce qui permet de collecter un ensemble plus large de données sur lesquelles faire des affirmations.

  • Pour des besoins plus modestes, on peut choisir de croire que l’état de Terraform est une représentation exacte de la réalité (une hypothèse valable dans de nombreux cas) et d’affirmer cela directement. Ceci est plus approprié pour les cas simples «ressemblant à des peluches», tels que la vérification du respect du schéma de balisage correct des ressources aux fins de la répartition des coûts.

Il existe d'autres discussions à ce sujet dans un numéro pertinent de Terraform Github .

Dans les dernières versions de Terraform, il est fortement recommandé d'utiliser un serveur distant pour toute application non-jouet, mais cela signifie que les données d'état ne sont pas directement disponibles sur le disque local. Cependant, un instantané de celui-ci peut être récupéré à partir du serveur distant à l'aide de la terraform state pullcommande, qui imprime les données d'état au format JSON sur stdout afin de pouvoir les capturer et les analyser par un programme appelant.


12

Pour mettre à jour cette question, il existe maintenant Kitchen-Terraform qui permet de tester les fichiers de configuration Terraform sans casser les environnements de production. Le référentiel comprend également quelques exemples pour différents fournisseurs Terraform.


12

Nous avons récemment ouvert Terratest , notre couteau suisse spécialisé dans le code d’infrastructure.

Aujourd'hui, vous testez probablement tout votre code d'infrastructure manuellement en déployant, en validant et en annulant le déploiement. Terratest vous aide à automatiser ce processus:

  1. Ecrire des tests dans Go.
  2. Utilisez les utilitaires de Terratest pour exécuter vos outils IaC réels (Terraform, Packer, etc.) afin de déployer une infrastructure réelle (par exemple, des serveurs) dans un environnement réel (par exemple, AWS).
  3. Utilisez les utilitaires de Terratest pour valider que l'infrastructure fonctionne correctement dans cet environnement en effectuant des requêtes HTTP, des appels d'API, des connexions SSH, etc.
  4. Utilisez les utilitaires de Terratest pour annuler le déploiement de tous les éléments à la fin du test.

Voici un exemple de test pour du code 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)

Ce sont des tests d'intégration et, selon ce que vous testez, peuvent prendre entre 5 et 50 minutes. Ce n'est pas rapide (bien que vous utilisiez Docker et des étapes de test pour accélérer certaines choses), et vous devrez travailler pour rendre les tests fiables, mais cela en vaut vraiment la peine.

Consultez le référentiel Terratest pour la documentation et de nombreux exemples de différents types de code d’infrastructure et les tests correspondants.


1
J'ai également écrit un article de blog qui décrit plus en détail l'un de mes exemples de projets avec Terratest: brightfame.co/blog/… . Cela peut être utile à n'importe qui. Salut, Rob!
Rob Morgan

Grand fan de Terratest!
jlucktay

7

Outre toutes les autres options mentionnées, je voudrais mentionner qu'InSpec 2.0 a pris en charge les API de fournisseur de cloud. Fondamentalement, vous pouvez continuer à écrire l'IaC avec Terraform, puis écrire des contrôles de conformité avec InSpec pour vos ressources cloud. En outre, InSpec prend en charge la rédaction de tests pour des machines individuelles si vous en avez besoin.

Voici un article de Christoph Hartmann (co-créateur d’Inspec) sur la façon d’utiliser Inspec avec Terraform: https://lollyrock.com/articles/inspec-terraform/


5

Sur Aws-Side, il y a https://github.com/k1LoW/awspec - il devrait être possible d'alimenter terraform.state et de tester, que terraform soit appliqué correctement.

Mais je pense qu’au-delà de tester l’outil de bas niveau que vous avez utilisé, c’est probablement une meilleure idée de réfléchir à la façon de tester des infrastructures complètes.

Nous discutons autour de cette idée ici:

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

Pour tester les invariants au départ, je ne connais pas de solution prête à l'emploi ...

Nous avons fait quelques expériences en utilisant un mélange de terraform plan -out=plan.dumpet greppour l'absence de noms d'éléments. Il existe une discussion sur un format de plan plus accessible ici: github.com/hashicorp/terraform/issues/11883

Mais pour le moment, nous utilisons un processus manuel d’examen des plans pour des éléments importants de notre infrastructure.


4
Le but est de tester les modifications de la configuration de terraform pour ne pas casser les besoins attendus. Une fois déployé, il est trop tard, au mieux, vous ne pouvez pas voir une base de données supprimée là où elle ne devrait pas, mais vous avez déjà cassé l'environnement cible. .. la question concerne le test du code terraform, et non le résultat final, les tests unitaires et les tests d'intégration.
Tensibai

bon point ... a ajouté une section pour tester les invariants.
juillet

0

J'ai vu cette méthode élégante et de basse technologie pour tester Terraform suggérée par apparemmentmart dans un fil de discussion GitHub. Ce n'est pas approprié à toutes les situations, mais c'est très bien pour vérifier la logique du module.

Créez un module racine incluant le module à tester et vérifiant les sorties sous-test. Voici un exemple simple utilisant deux fichiers:

  • main.tf ça va faire les tests
  • simple_module/outputs.tf qui représente un module à tester

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

Lancer les tests

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

Outputs:

expect-1 = TRUE
expect-other = FALSE. Got 1
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.