DEV Community

Cover image for Terraform APPLY + DESTROY
Igor Souza
Igor Souza

Posted on • Edited on

Terraform APPLY + DESTROY

Curso Completo Gratis!

Esse post faz parte de um curso completo sobre Terraform, caso voce queira saber mais sobre terraform da um pulo no meu blog ou no meu youtube para ter acesso ao curso completo 100% gratuito.

Mas se quiser contribuir:

Aqui no Udemy tem o mesmo curso que esta disponivel 100% gratuito no youtube pra quem quiser e puder contribuir financeiramete :)

Terraform Apply

Vamos utilizar o comando terraform apply para tentarmos criar nosso droplet.

 terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # digitalocean_droplet.web will be created
  + resource "digitalocean_droplet" "web" {
      + backups              = false
      + created_at           = (known after apply)
      + disk                 = (known after apply)
      + id                   = (known after apply)
      + image                = "ubuntu-20-04-x64"
      + ipv4_address         = (known after apply)
      + ipv4_address_private = (known after apply)
      + ipv6                 = false
      + ipv6_address         = (known after apply)
      + locked               = (known after apply)
      + memory               = (known after apply)
      + monitoring           = false
      + name                 = "web-1"
      + price_hourly         = (known after apply)
      + price_monthly        = (known after apply)
      + private_networking   = (known after apply)
      + region               = "nyc2"
      + resize_disk          = true
      + size                 = "s-1vcpu-1gb"
      + status               = (known after apply)
      + urn                  = (known after apply)
      + vcpus                = (known after apply)
      + volume_ids           = (known after apply)
      + vpc_uuid             = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:
Enter fullscreen mode Exit fullscreen mode

Se você prestar atenção, vai perceber que a saída até aqui é bem similar a que tivemos no plan, isso acontece por que o apply antes de realmente aplicar as alterações ele executa um plan para que você possa se certificar de que realmente quer fazer isso.

Se você quiser burlar esse plan e simplesmente aceitar o que vai ser criado, basta executar terraform apply -auto-approve.

terraform apply -auto-approve
digitalocean_droplet.web: Creating...

Error: Error creating droplet: POST https://api.digitalocean.com/v2/droplets: 401 Unable to authenticate you
Enter fullscreen mode Exit fullscreen mode

Achou que eu ia te livrar de todos os erros? Achou errado!

Bom, 401 Unable to authenticate you significa que não foi possível se autenticar com a api da Digital Ocean. Se voltarmos lá na página sobre o provider vamos conseguir entender melhor como corrigir o erro.

De toda forma, a primeira coisa que precisamos fazer é criar um token no painel da Digital Ocean. Acesse o painel de controle da sua conta e procure por API, no momento que escrevo é o último item da coluna esquerda. Clique em generate new token de um nome para o seu token e copie o token que vai aparecer para você. Algo como:

 b783123asd294f002c5ea9af1231298327903284kmmsadoiu48d02707a2018588d
Enter fullscreen mode Exit fullscreen mode

Agora vamos seguir o jeito mais simples e completamente

variable "do_token" {
  default = "b783123asd294f002c5ea9af1231298327903284kmmsadoiu48d02707a2018588d"
}

provider "digitalocean" {
  token = var.do_token
}
Enter fullscreen mode Exit fullscreen mode

O nome do_token poderia ser qualquer coisa, esse é o campo onde você nomeia sua variável e o parametro default e onde você cadastra um valor padrão pra ela. Sem esse parâmetro, toda vez que você rodar o plan ou o apply ele vai te perguntar o valor da variável. Se isso é o que você quer, basta remover a linha com o parâmetro default.

Vamos executar novamente nosso apply:

terraform apply -auto-approve
digitalocean_droplet.web: Creating...

Error: Error creating droplet: POST https://api.digitalocean.com/v2/droplets: 401 Unable to authenticate you
Enter fullscreen mode Exit fullscreen mode

Mesmo com o token cadastrado, a gente continua recebendo o mesmo erro. Isso acontece por que apesar de termos criado uma variável, não contamos para o provider que ele deve utilizar essa variável. Vamos fazer isso agora.

 provider "digitalocean" {
  token = var.do_token
}

variable "do_token" {
  default = "b783726c929c48febf8555eee856f84f002c5ea9af7d49648d02707a2018588d"
}

resource "digitalocean_droplet" "web" {
  image  = "ubuntu-20-04-x64"
  name   = "web-1"
  region = "nyc2"
  size   = "s-1vcpu-1gb"
}
Enter fullscreen mode Exit fullscreen mode

Agora o provider digitalocean sabe que ele deve procurar por uma variável chamada do_token e utilizar no parâmetro token.

Vamos tentar mais uma vez criar nossa máquina.

terraform apply -auto-approve
digitalocean_droplet.web: Creating...

Error: Error creating droplet: POST https://api.digitalocean.com/v2/droplets: 422 nyc2 is unavailable.
Enter fullscreen mode Exit fullscreen mode

Opa, agora aconteceu uma das maiores felicidades de quem escreve código. Mudou o erro! O que é bom pois antes estavamos recebendo uma mensagem de que não conseguíamos nos conectar e agora a mensagem foi 422 nyc2 nao esta disponivel. Acontece que apesar da documentação do provider dar o exemplo com a região nyc2, essa região não está disponível a algum tempo já. Eu não sei exatamente se eles nunca se preocuparam em corrigir isso ou se o objetivo é fazer a gente aprender a debugar o problema. Enfim, a solução é só alterar a região para qualquer outra que exista, vamos mudar pra ams3 que e a região de Amsterdam pra ficar mais pertinho de mim, mas você pode usar outra qualquer como nyc3 por exemplo.

Mais uma tentativa:

terraform apply -auto-approve

digitalocean_droplet.web: Creating...
digitalocean_droplet.web: Still creating... [10s elapsed]
digitalocean_droplet.web: Still creating... [20s elapsed]
digitalocean_droplet.web: Still creating... [30s elapsed]
digitalocean_droplet.web: Creation complete after 33s [id=232247846]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Enter fullscreen mode Exit fullscreen mode

Muito bom, mas agora vem a questão! Como a gente pode ter alguns dados desse droplet que acabamos de criar? Por exemplo, se eu quiser saber o IP desse droplet, como a gente faz?

Pra isso vamos utilizar os outputs.

Terraform Output

Toda documentação de um resource é dividido em pelo menos tres níveis.

  • Exemplo de Uso
  • Referência de Argumento (ou parâmetro)
  • Referência de Atributos

Todos os itens que tivermos dentro do nível de referência de atributo podem ser utilizados seja para passar para um outro resource ou para ser utilizado como output do nosso código. Antes de começarmos a misturar atributos de um recurso com argumento de outro, vamos usar os atributos na sua forma mais simples, como um output.

O output em si é uma feature que permite voce apresentar o valor de alguma coisa do seu código na tela. Mais pra frente vamos ver uma outra utilidade do output que é retornar os valores de um módulo. Mas fica tranquilo que isso é mais pra frente.

Por hora vamos adicionar o seguinte num arquivo chamado output.tf, que esteja na mesma pasta que nosso main.tf.

output "droplet_ip" {
  value = "hashicourse"
}
Enter fullscreen mode Exit fullscreen mode

Vamos executar novamente o comando apply e vamos ver que agora temos mais um retorno no nosso código.

terraform apply -auto-approve
digitalocean_droplet.web: Refreshing state... [id=232247846]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

droplet_ip = "hashicourse"
Enter fullscreen mode Exit fullscreen mode

Nada foi criado ou alterado, como esperado, mas vemos um Outputs: na resposta e o valor que a gente cadastrou pro ip do nosso droplet. Agora manter esse valor hardcoded não vai nos ajudar muito. Vamos então utilizar um atributo do nosso droplet pra isso.

Primeiro, deixa eu te mostrar o código:

 resource "digitalocean_droplet" "web" {
  image  = "ubuntu-20-04-x64"
  name   = "web-1"
  region = "ams3"
  size   = "s-1vcpu-1gb"
}

output "droplet_ip" {
  value = digitalocean_droplet.web.ipv4_address
}
Enter fullscreen mode Exit fullscreen mode

.A forma de chegarmos nesse atributo é bem simples.

  • [A] Primeiro você precisa pegar o nome do recurso, que é aquele primeiro ali "digitalocean_droplet" que nada mais é como uma forma de dizer para o provedor qual o recurso você tá querendo criar.
  • [B] Segundo pega o nome que você deu para aquele recurso, no nosso caso "web". É muito comum precisarmos utilizar mais de uma vez um recurso no nosso código e essa é uma das formas de nomear aquele recurso. Vale lembrar que esse nome é único, ok?
  • [C] Por último precisamos ir lá na documentação e ver qual dos atributos disponíveis nos fornece o que precisamos. É raro que você precise de algo que não está ali disponível, mas raro não é impossível.

Por fim basta montar sempre no formato A.B.C :)

Se você rodar o seu código agora deve ter um retorno como o seguinte:

terraform apply -auto-approve
digitalocean_droplet.web: Refreshing state... [id=232247846]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

droplet_ip = "104.248.203.68"
Enter fullscreen mode Exit fullscreen mode

Muito provavelmente seu numero de ip é diferente do meu, mas se por algum milagre você pegou o mesmo, bate um print e me manda :)

Uma última dica no que se refere a outputs é que você não precisa utilizar apenas o apply para ter acesso a todos os outputs do seu código. Considerando que você já tenha executado o apply pelo menos uma vez, você pode utilizar o terraform output:

terraform output
droplet_ip = "104.248.203.68"
Enter fullscreen mode Exit fullscreen mode

Terraform Destroy

Agora que já criamos um droplet, você talvez esteja se perguntando "Beleza, agora como eu desligo esse droplet pra não gastar meu bônus?", bom pra isso tem um comando com nome bem sugestivo destroy.
O terraform destroy é o oposto do apply. Uma das coisas que ambos tem em comum é o plan antes de executar. A gente não falou antes, mas existe um parâmetro no plan chamado de -destroy. E esse é o parâmetro que o terraform usa quando a gente executa o terraform destroy, a saída deve ser parecida com a seguinte:

terraform destroy

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # digitalocean_droplet.web will be destroyed
  - resource "digitalocean_droplet" "web" {
      - backups              = false -> null
      - created_at           = "2021-02-17T19:34:37Z" -> null
      - disk                 = 25 -> null
      - id                   = "232254786" -> null
      - image                = "ubuntu-20-04-x64" -> null
      - ipv4_address         = "104.248.197.79" -> null
      - ipv4_address_private = "10.110.0.2" -> null
      - ipv6                 = false -> null
      - locked               = false -> null
      - memory               = 1024 -> null
      - monitoring           = false -> null
      - name                 = "web-1" -> null
      - price_hourly         = 0.00744 -> null
      - price_monthly        = 5 -> null
      - private_networking   = true -> null
      - region               = "ams3" -> null
      - resize_disk          = true -> null
      - size                 = "s-1vcpu-1gb" -> null
      - status               = "active" -> null
      - urn                  = "do:droplet:232254786" -> null
      - vcpus                = 1 -> null
      - volume_ids           = [] -> null
      - vpc_uuid             = "b83009d3-8cb0-4545-8123-6f2238e40284" -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Changes to Outputs:
  - droplet_ip = "104.248.197.79" -> null

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value:
Enter fullscreen mode Exit fullscreen mode

O que vemos aqui é que vamos destruir todos os nossos recursos, que no caso é apenas um droplet. Você pode digitar yes no comando acima ou utilizar o -auto-approve junto com o destroy para destruir todos os recursos sem nem olhar pro plan -destroy.

terraform destroy -auto-approve
digitalocean_droplet.web: Destroying... [id=232247846]
digitalocean_droplet.web: Still destroying... [id=232247846, 10s elapsed]
digitalocean_droplet.web: Still destroying... [id=232247846, 20s elapsed]
digitalocean_droplet.web: Destruction complete after 22s

Destroy complete! Resources: 1 destroyed.
Enter fullscreen mode Exit fullscreen mode

Beleza, agora você pode descansar em paz que seu bônus/dinheiro não está sendo mais consumido. Lembre-se sempre de destruir os recursos da sua conta pra garantir que não tenha surpresa no fim do mês. Importante também é criar um alerta lá na digitalocean, eu recomendo criar um valor de 5$ que é o custo de um droplet, se passar disso provavelmente algo está errado.

Arquivo de Variaveis

Uma coisa comum de se ver são códigos que utilizam uma variável da seguinte forma:

 variable "do_token" {
  description = "Uma descricao bacana!"
  type        = string
}
Enter fullscreen mode Exit fullscreen mode

Ou seja, nao possuem um valor padrão para a variável, acontece que dependendo da quantidade de variáveis que existem nesse formato, pode ser bem chato de ficar colocando uma a uma.

Uma solução, bem gambiarra, que eu já fiz muito é colocar um valor default para cada uma dessas variáveis e garantir que não iria adicionar as alterações desse arquivo no repositório git. O que normalmente acabava acontecendo depois de um tempo. Acontece que o terraform te dá a possibilidade de usar um arquivo só para adicionar esse valores. Basta criarmos um arquivo qualquer_coisa.tfvars. Normalmente as pessoas utilizam terraform.tfvars ou então nome_do_ambiente.tfvars. Vamos criar o nosso como terraform.tfvars mesmo.

 do_token = "b783123asd294f002c5ea9af1231298327903284kmmsadoiu48d02707a2018588d"
Enter fullscreen mode Exit fullscreen mode

Esse é o formato do arquivo de variáveis, caso exista um valor padrão e você queira sobrescrever ele, pode colocar o novo valor nesse arquivo e vai funcionar também. Agora precisamos dizer para o terraform que ele deve buscar os valores das variáveis primeiro nesse arquivo, para isso vamos executar o apply novamente passando o -var-file como parâmetro. Esse -varfile vale para o plan e o destroy também.

terraform apply -var-file terraform.tfvars

An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:
  # digitalocean_droplet.web will be created
  + resource "digitalocean_droplet" "web" {
      + backups              = false
      + created_at           = (known after apply)
      + disk                 = (known after apply)
      + id                   = (known after apply)
      + image                = "ubuntu-20-04-x64"
      + ipv4_address         = (known after apply)
      + ipv4_address_private = (known after apply)
      + ipv6                 = false
      + ipv6_address         = (known after apply)
      + locked               = (known after apply)
      + memory               = (known after apply)
      + monitoring           = false
      + name                 = "web-1"
      + price_hourly         = (known after apply)
      + price_monthly        = (known after apply)
      + private_networking   = (known after apply)
      + region               = "ams3"
      + resize_disk          = true
      + size                 = "s-1vcpu-1gb"
      + status               = (known after apply)
      + urn                  = (known after apply)
      + vcpus                = (known after apply)
      + volume_ids           = (known after apply)
      + vpc_uuid             = (known after apply)
    }
Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + droplet_ip = (known after apply)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

digitalocean_droplet.web: Creating...
digitalocean_droplet.web: Still creating... [10s elapsed]
digitalocean_droplet.web: Still creating... [20s elapsed]
digitalocean_droplet.web: Still creating... [30s elapsed]
digitalocean_droplet.web: Creation complete after 34s [id=232397944]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

droplet_ip = "206.189.0.61"
Enter fullscreen mode Exit fullscreen mode

Top comments (0)