# Terraform | Utilizando módulos com outros módulos

# Utilizando módulos com outros módulos

Primeira coisa que devemos fazer é destruir toda sua infraestrutura (caso ainda não tenha feito) com o comando:


```
$ terraform destroy -auto-approve
```

Crie um novo repositório chamado `gcp-networks` no GitLab e outro repositório chamado `gcp-subnetworks`.

Faça o clone dos repositórios.


```
$ git clone git@gitlab.com:rd-public/blog-blog-tf-modules/4linux/gcp-networks.git
```

Você receberá mensagem para cada um dos repositórios que está clonando um repositório em branco.

Entre no diretório do `gcp-networks` e vamos iniciar a criação deste módulo com algumas coisas novas, como o arquivo `outputs.tf` que será explicado em breve.

Crie o arquivo `main.tf`:


```
resource "google_compute_network" "this" {
  name                    = var.name
  description             = var.description
  auto_create_subnetworks = var.auto_create_subnetworks
}
```

Arquivo `variables.tf`


```
variable "name" {
  description = "Nome para sua rede"
  type        = string
}

variable "description"  {
  description = "Descrição para sua rede"
  type        = string
}

variable "auto_create_subnetworks" {
  description = "Redes devem criar automaticamente subredes?"
  type        = bool
  default     = true
}
```

Arquivo `outputs.tf`


```
output "gateway_ipv4" {
  value = google_compute_network.this.gateway_ipv4
}

output "self_link" {
  value = google_compute_network.this.self_link
}
```

O arquivo `outputs` é responsável por basicamente imprimir no seu terminal a saída do recurso criado, porém ele também é o ponto de ligação quando você precisa fazer o vínculo de um módulo com outro módulo, que é o nosso caso pra ligar instâncias com as redes.

Antes de enviarmos o código para o repositório devemos fazer um teste local para verificar se ele está funcionando corretamente e para isso precisamos primeiro fazer uma outra alteração em nosso módulo que gerencia as instâncias.

Vá até seu módulo que gerencia instâncias e abra o arquivo `main.tf` alterando para:


```
resource "google_compute_instance" "this" {
  count        = var.amount

  name         = format("%s-%d", var.name, count.index)
  machine_type = var.machine_type
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = var.image
    }
  }

  network_interface {
    network = var.network
  }
}
```

Altere o arquivo `variables.tf` adicionando no fim do arquivo mais um bloco para a variável de rede:


```
variable "network" {
  description = "Qual rede deseja utilizar"
  type        = string
  default     = "default"
}
```

Abra o arquivo `instances.tf` (que consome os módulos), adicione a rede e faça o apontamento do módulo de instâncias também para local:


```
# Instâncias Linux
module "network-linux" {
  source = "./tf-modules/gcp-networks"

  name        = "network-linux"
  description = "Rede para o grupo de máquinas linux"
}

module "instances" {
  source = "./tf-modules/gcp-instances"

  amount  = 2
  name    = "linux-vm-1"
  network = module.network-linux.self_link
}

# Instâncias Web
module "network-web" {
  source = "./tf-modules/gcp-networks"

  name        = "network-web"
  description = "Rede para o grupo de máquinas web"
}

module "group-web" {
  source = "./tf-modules/gcp-instances"

  amount  = 3
  name    = "linux-web"
  image   = "centos-cloud/centos-8"
  network = module.network-web.self_link
}

# Instâncias Gitlab
module "network-gitlab" {
  source = "./tf-modules/gcp-networks"

  name        = "network-gitlab"
  description = "Rede para o grupo de máquinas gitlab"
}

module "group-gitlab" {
  source = "./tf-modules/gcp-instances"

  amount  = 2
  name    = "linux-gitlab"
  image   = "centos-cloud/centos-7"
  network = module.network-gitlab.self_link
}
```

Faça a inicialização dos módulos:


```
$ terraform init
```

Com a seguinte saída:


```
Initializing modules...
- group-gitlab in ../../tf-modules/gcp-instances
- group-web in ../../tf-modules/gcp-instances
- instances in ../../tf-modules/gcp-instances
- network-gitlab in ../../tf-modules/gcp-networks
- network-linux in ../../tf-modules/gcp-networks
- network-web in ../../tf-modules/gcp-networks

Initializing the backend...
......
......
......
......
```

Faça o plano de execução e verifique a criação das redes:


```
......
......
......
......
  # module.network-gitlab.google_compute_network.this will be created
  + resource "google_compute_network" "this" {
      + auto_create_subnetworks         = false
      + delete_default_routes_on_create = false
      + description                     = "Rede para o grupo de máquinas gitlab"
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + ipv4_range                      = (known after apply)
      + name                            = "network-gitlab"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)
    }

  # module.network-linux.google_compute_network.this will be created
  + resource "google_compute_network" "this" {
      + auto_create_subnetworks         = false
      + delete_default_routes_on_create = false
      + description                     = "Rede para o grupo de máquinas linux"
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + ipv4_range                      = (known after apply)
      + name                            = "network-linux"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)
    }

  # module.network-web.google_compute_network.this will be created
  + resource "google_compute_network" "this" {
      + auto_create_subnetworks         = false
      + delete_default_routes_on_create = false
      + description                     = "Rede para o grupo de máquinas web"
      + gateway_ipv4                    = (known after apply)
      + id                              = (known after apply)
      + ipv4_range                      = (known after apply)
      + name                            = "network-web"
      + project                         = (known after apply)
      + routing_mode                    = (known after apply)
      + self_link                       = (known after apply)
    }

Plan: 10 to add, 0 to change, 0 to destroy.
```

Crie esta infraestrutura:


```
$ terraform apply -auto-approve
```

Com a saída:


```
......
......
......
......
......
module.group-web.google_compute_instance.this[1]: Still creating... [10s elapsed]
module.group-web.google_compute_instance.this[0]: Still creating... [10s elapsed]
module.group-web.google_compute_instance.this[2]: Creation complete after 10s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-web-2]
module.group-web.google_compute_instance.this[0]: Creation complete after 10s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-web-0]
module.group-gitlab.google_compute_instance.this[0]: Still creating... [10s elapsed]
module.group-gitlab.google_compute_instance.this[1]: Still creating... [10s elapsed]
module.group-web.google_compute_instance.this[1]: Creation complete after 10s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-web-1]
module.group-gitlab.google_compute_instance.this[1]: Creation complete after 11s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-gitlab-1]
module.group-gitlab.google_compute_instance.this[0]: Creation complete after 11s [id=projects/projeto-1-265222/zones/us-central1-a/instances/linux-gitlab-0]

Apply complete! Resources: 10 added, 0 changed, 3 destroyed.
```

Okay, tudo funcionando, hora de versionarmos nossos módulos. Primeiro vamos versionar o módulo de instâncias:

Adicione os dois arquivos que foram modificados.


```
$ git add main.tf variables.tf
```

Faça o commit das alterações.


```
$ git commit -m 'Adição de rede para o modulo'
```

Envie para o repositório:


```
$ git push origin master
```

Crie uma nova tag:


```
$ git tag -a v1.1 -m 'Adição de rede'
```

Envie a tag para o repositório:


```
$ git push --tags
```

Vamos para o módulo de rede e fazer o versionamento.

Adicione os 3 arquivos.


```
$ git add main.tf variables.tf outputs.tf
```

Faça o commit:


```
$ git commit -m 'Envio de módulo'
```

Envie para o repositório:


```
$ git push origin master
```

Crie a primeira tag:


```
$ git tag -a v1.0 -m 'Versão 1.0 do módulo'
```

Envie a tag para o repositório:


```
$ git push --tags
```

Perfeito! todos os módulos versionados, agora é hora de novamente alterar o arquivo `instances.tf` para suportar o novo código.

Arquivo `instances.tf`:


```

# Instâncias Linux
module "network-linux" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-linux"
  description = "Rede para o grupo de máquinas linux"
}

module "instances" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1"

  amount  = 2
  name    = "linux-vm-1"
  network = module.network-linux.self_link
}

# Instâncias Web
module "network-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-web"
  description = "Rede para o grupo de máquinas web"
}

module "group-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1"

  amount  = 3
  name    = "linux-web"
  image   = "centos-cloud/centos-8"
  network = module.network-web.self_link
}

# Instâncias Gitlab
module "network-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-gitlab"
  description = "Rede para o grupo de máquinas gitlab"
}

module "group-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1"

  amount  = 2
  name    = "linux-gitlab"
  image   = "centos-cloud/centos-7"
  network = module.network-gitlab.self_link
}
```

Faça a inicialização do Terraform para buscar o novo código:


```
$ terraform init
```

Com o resultado:


```
Initializing modules...
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1 for group-gitlab...
- group-gitlab in .terraform/modules/group-gitlab
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1 for group-web...
- group-web in .terraform/modules/group-web
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.1 for instances...
- instances in .terraform/modules/instances
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0 for network-gitlab...
- network-gitlab in .terraform/modules/network-gitlab
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0 for network-linux...
- network-linux in .terraform/modules/network-linux
Downloading git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0 for network-web...
- network-web in .terraform/modules/network-web
......
......
......
......
......
```

Verifique no seu painel do GCP todas instâncias criadas assim como todas redes que foram criadas.

Estas redes estão com o atributo para criar automaticamente subredes. Estas subredes são criadas automaticamente pelo nosso atributo `auto_create_subnetworks = var.auto_create_subnetworks` onde nossa variável está setada como true.

Nós não queremos que seja gerada automaticamente mas sim gerenciada por nós e pra isso precisamos alterar este atributo na nossa chamada e passar ela para false, mas este atributo podemos agora setar na chamada de nosso módulo e faremos isso em breve.

Por fim, nosso último módulo que irá gerenciar subredes.

Crie um diretório chamado `gcp-subnetworks` e dentro deste diretório:

Crie um arquivo chamado `main.tf` com o seguinte conteúdo:


```
resource "google_compute_subnetwork" "this" {
  name          = var.name
  ip_cidr_range = var.ip_cidr_range
  region        = var.region
  network       = var.network
}
```

Arquivo `variables.tf`


```
variable "name" {
  type        = string
  description = "Nome para a subrede"
}

variable "ip_cidr_range" {
  type        = string
  description = "IP CIDR"
}

variable "region" {
  type        = string
  description = "Nome da região que será utilizada"
  default     = "us-central1"
}

variable "network" {
  type        = string
  description = "Nome da rede que será conectada com esta subrede"
}
```

Arquivo `outputs.tf`


```
output "creation_timestamp" {
  value = google_compute_subnetwork.this.creation_timestamp
}

output "gateway_address" {
  value = google_compute_subnetwork.this.gateway_address
}

output "self_link" {
  value = google_compute_subnetwork.this.self_link
}
```

Também devemos criar uma nova versão do nosso módulo que gerencia as instâncias para que passe a suportar as subredes:

Altere o arquivo `main.tf` e altere o bloco de network de:


```
network_interface {
  network = var.network
}
```

para:


```
network_interface {
  network    = var.network
  subnetwork = var.subnetwork
}
```

Altere também o arquivo `variables.tf` com um novo bloco no fim do arquivo:


```
variable "subnetwork" {
  description = "Qual subrede deseja utilizar"
  type        = string
}
```

Altere o arquivo do `instances.tf` mais uma vez para fazer o teste local com o novo módulo.


```
# Instâncias Linux
module "network-linux" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-linux"
  description = "Rede para o grupo de máquinas linux"
}

module "subnetwork-linux" {
  source = "./tf-modules/gcp-subnetworks"

  name          = "subnetwork-linux"
  ip_cidr_range = "10.10.1.0/24"
  network       = module.network-linux.self_link
}

module "instances" {
  source = "./tf-modules/gcp-instances"

  amount     = 2
  name       = "linux-vm-1"
  network    = module.network-linux.self_link
  subnetwork = module.subnetwork-linux.self_link
}

# Instâncias Web
module "network-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-web"
  description = "Rede para o grupo de máquinas web"
}

module "subnetwork-web" {
  source = "./tf-modules/gcp-subnetworks"

  name          = "subnetwork-web"
  ip_cidr_range = "10.10.2.0/24"
  network       = module.network-web.self_link
}

module "group-web" {
  source = "./tf-modules/gcp-instances"

  amount     = 3
  name       = "linux-web"
  image      = "centos-cloud/centos-8"
  network    = module.network-web.self_link
  subnetwork = module.subnetwork-web.self_link
}

# Instâncias Gitlab
module "network-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-gitlab"
  description = "Rede para o grupo de máquinas gitlab"
}

module "subnetwork-gitlab" {
  source = "./tf-modules/gcp-subnetworks"

  name          = "subnetwork-gitlab"
  ip_cidr_range = "10.10.3.0/24"
  network       = module.network-gitlab.self_link
}

module "group-gitlab" {
  source = "./tf-modules/gcp-instances"

  amount     = 2
  name       = "linux-gitlab"
  image      = "centos-cloud/centos-7"
  network    = module.network-gitlab.self_link
  subnetwork = module.subnetwork-gitlab.self_link
}
```

Funcionando? então devemos enviar nosso módulo de instâncias com suas devidas modificações para serem versionadas.


```
$ git add .
```

Faça o commit:


```
$ git commit -m 'Suporte a subredes'
```

Envie para o repositório:


```
$ git push origin master
```

Crie a tag:


```
$ git tag -a v1.2 -m 'Suporte a subredes'
```

Envie a tag para o repositório:


```
$ git push --tags
```

Agora no novo novo módulo `gcp-subnetworks` faça o processo de envio de código e crie a tag (processo já é conhecido, certo?)

Finalmente altere o arquivo `instances.tf` para a versão final.


```
# Instâncias Linux
module "network-linux" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-linux"
  description = "Rede para o grupo de máquinas linux"
}

module "subnetwork-linux" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-subnetworks.git?ref=v1.0"

  name          = "subnetwork-linux"
  ip_cidr_range = "10.10.1.0/24"
  network       = module.network-linux.self_link
}

module "instances" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.2"

  amount     = 2
  name       = "linux-vm-1"
  network    = module.network-linux.self_link
  subnetwork = module.subnetwork-linux.self_link
}

# Instâncias Web
module "network-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-web"
  description = "Rede para o grupo de máquinas web"
}

module "subnetwork-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-subnetworks.git?ref=v1.0"

  name          = "subnetwork-web"
  ip_cidr_range = "10.10.2.0/24"
  network       = module.network-web.self_link
}

module "group-web" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.2"

  amount     = 3
  name       = "linux-web"
  image      = "centos-cloud/centos-8"
  network    = module.network-web.self_link
  subnetwork = module.subnetwork-web.self_link
}

# Instâncias Gitlab
module "network-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-networks.git?ref=v1.0"

  name        = "network-gitlab"
  description = "Rede para o grupo de máquinas gitlab"
}

module "subnetwork-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-subnetworks.git?ref=v1.0"

  name          = "subnetwork-gitlab"
  ip_cidr_range = "10.10.3.0/24"
  network       = module.network-gitlab.self_link
}

module "group-gitlab" {
  source = "git@gitlab.com:rd-public/4linux/blog-tf-modules/gcp-instances.git?ref=v1.2"

  amount     = 2
  name       = "linux-gitlab"
  image      = "centos-cloud/centos-7"
  network    = module.network-gitlab.self_link
  subnetwork = module.subnetwork-gitlab.self_link
}
```

Estes módulos estão disponíveis em:

* https://gitlab.com/rd-public/4linux/blog-tf-modules/gcp-networks
* https://gitlab.com/rd-public/4linux/blog-tf-modules/gcp-subnetworks

