Como testar uma configuração do Terraform?


37

Se você tivesse uma configuração do Terraform com um grau moderado de complexidade, como você escreveria testes em torno da configuração que poderia ser executada como parte de um pipeline de Integração Contínua / Entrega Contínua?

Como exemplo, você pode ter uma configuração de várias nuvens que especifica o seguinte estado desejado:

  • Serviços de Contêiner do Azure para hospedar o Docker no Azure
  • Armazenamento de Blobs do Azure
  • SQL Azure
  • Serviço de contêiner EC2 para hospedar o Docker na AWS
  • Serviço de armazenamento Amazon S3
  • Banco de dados do Amazon RDS SQL Server

Potencialmente, terraform applypode criar o que foi dito acima, ou fazer a transição de um estado parcialmente implantado para o estado desejado acima.

Estou ciente de que o Terraform divide seu trabalho no estágio do plano de execução e na fase de aplicação , que efetivamente faz alterações na arquitetura de destino. Isso pode ser usado para escrever testes contra o plano de execução; se houver, existem estruturas para ajudar a escrevê-los?



Interessante de fato, possivelmente responda digno.
Richard Slater

Não estou usando terraform mim, então eu deixar alguém com experiência real escrever uma resposta :)
Tensibai

Respostas:


20

Atualmente, não há uma solução completa para isso integrada ao Terraform, mas existem alguns componentes que podem ser úteis para ajudar na gravação de testes em uma linguagem de programação separada.

O Terraform produz arquivos de estado no formato JSON que podem, em princípio, ser usados ​​por programas externos para extrair determinados dados sobre o que o Terraform criou. Embora esse formato ainda não seja considerado oficialmente estável, na prática ele muda com pouca frequência para que as pessoas tenham se integrado com sucesso, aceitando que talvez precisem fazer ajustes ao atualizar o Terraform.

Qual estratégia é apropriada aqui dependerá muito do que exatamente você deseja testar. Por exemplo:

  • Em um ambiente que está girando em servidores virtuais, ferramentas como Serverspec podem ser usadas para executar testes da perspectiva desses servidores. Isso pode ser executado separadamente do Terraform usando algum processo fora da banda ou como parte do Terraform aplicável usando o remote-execprovisionador . Isso permite a verificação de perguntas como "o servidor pode acessar o banco de dados?", Mas não é adequado para perguntas como "o grupo de segurança da instância é restritivo o suficiente?", Desde a verificação robusta que exige acesso a dados de fora da própria instância.

  • É possível escrever testes usando uma estrutura de teste existente (como RSpec para Ruby, unittestpara Python, etc) que reúne IDs ou endereços de recursos relevantes do arquivo de estado Terraform e, em seguida, usa o SDK da plataforma relevante para recuperar dados sobre os recursos e afirmar que eles são configurados conforme o esperado. Essa é uma forma mais geral da idéia anterior, executando os testes da perspectiva de um host fora da infraestrutura em teste e, portanto, pode coletar um conjunto mais amplo de dados para fazer afirmações.

  • Para necessidades mais modestas, pode-se optar por confiar que o estado Terraform é uma representação precisa da realidade (uma suposição válida em muitos casos) e simplesmente afirmar diretamente sobre isso. Isso é mais apropriado para casos simples "semelhantes a fiapos", como verificar se o esquema correto de identificação de recursos está sendo seguido para fins de alocação de custos.

Há mais discussões sobre isso em uma questão relevante do Terraform Github .

Nas versões mais recentes do Terraform, é altamente recomendável usar um back-end remoto para qualquer aplicativo que não seja de brinquedo, mas isso significa que os dados do estado não estão diretamente disponíveis no disco local. No entanto, um instantâneo dele pode ser recuperado do back-end remoto usando o terraform state pullcomando, que imprime os dados de estado formatados em JSON em stdout, para que possam ser capturados e analisados ​​por um programa de chamada.


12

Como uma atualização para essa pergunta, agora existe o Kitchen-Terraform, que permite testar os arquivos de configuração do Terraform sem interromper os ambientes de produção. O repositório também inclui alguns exemplos para diferentes provedores Terraform.


12

Recentemente, abrimos o Terratest , nosso canivete suíço para testes de código de infraestrutura.

Hoje, você provavelmente está testando todo o seu código de infraestrutura manualmente implantando, validando e desimplantando. O Terratest ajuda a automatizar esse processo:

  1. Escreva testes no Go.
  2. Use os auxiliares do Terratest para executar suas ferramentas IaC reais (por exemplo, Terraform, Packer etc.) para implantar infraestrutura real (por exemplo, servidores) em um ambiente real (por exemplo, AWS).
  3. Use os auxiliares do Terratest para validar se a infraestrutura funciona corretamente nesse ambiente, fazendo solicitações HTTP, chamadas de API, conexões SSH etc.
  4. Use ajudantes no Terratest para desimplementar tudo no final do teste.

Aqui está um exemplo de teste para algum código do 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)

Esses são testes de integração e, dependendo do que você está testando, podem levar de 5 a 50 minutos. Não é rápido (apesar de usar o Docker e as etapas de teste , você pode acelerar algumas coisas) e precisará trabalhar para tornar os testes confiáveis, mas vale a pena o tempo gasto.

Confira o repositório Terratest para obter documentos e vários exemplos de vários tipos de código de infraestrutura e os testes correspondentes para eles.


1
Também escrevi uma postagem de blog que analisa mais detalhadamente um dos meus projetos de exemplo com o Terratest: brightfame.co/blog/… . Pode ser de valor para qualquer um. Saúde, Rob!
Rob Morgan

Grande fã do Terratest!
jlucktay

7

Além de todas as outras opções mencionadas, gostaria de mencionar que o InSpec 2.0 adicionou suporte para APIs de provedor de nuvem. Basicamente, você pode continuar escrevendo o IaC com o Terraform e, em seguida, faça verificações de conformidade com o InSpec para seus recursos de nuvem. Além disso, o InSpec suporta testes de gravação para máquinas individuais, se você precisar.

Aqui está um artigo de Christoph Hartmann (co-criador do Inspec) sobre como usar o Inspec com Terraform: https://lollyrock.com/articles/inspec-terraform/


5

No Aws-Side, existe https://github.com/k1LoW/awspec - deve ser possível alimentar terraform.state e testar, se o terraform aplicado corretamente.

Mas acho que, além de testar a ferramenta em nível baixo, você usou, provavelmente é uma ideia melhor pensar em como testar infraestruturas inteiras.

Estamos discutindo essa idéia aqui:

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

Para testar antecipadamente os invariantes, não conheço uma solução pronta para usar ...

Fizemos alguns experimentos usando uma mistura de terraform plan -out=plan.dumpe greppara a ausência de nomes de elementos. Há uma discussão sobre um formato de plano mais acessível aqui: github.com/hashicorp/terraform/issues/11883

No momento, porém, estamos usando um processo de revisão manual do plano para partes importantes da nossa infraestrutura.


4
O objetivo é testar se as alterações na configuração do terraform não quebram as necessidades esperadas; uma vez implantado é tarde demais, na melhor das hipóteses, você vê uma falha ao ver que um banco de dados foi removido onde não deveria, mas você já quebrou o ambiente de destino. .. a questão é testar o código de terraform, não testar o resultado final, testes de unidade versus testes de integração.
Tensibai

bom ponto ... adicionou uma seção para testar invariantes.
Jerger

0

Eu vi esse método elegante e de baixa tecnologia para testar o Terraform sugerido pelo aparentementemart em um tópico do GitHub. Não é apropriado para todas as situações, mas é ótimo para verificar a lógica do módulo.

Crie um módulo raiz que inclua o módulo em teste e verifique as saídas em teste. Aqui está um exemplo simples usando dois arquivos:

  • main.tf que executará os testes
  • simple_module/outputs.tf que representa um módulo em teste

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

Execute os testes

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

Outputs:

expect-1 = TRUE
expect-other = FALSE. Got 1
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.