Bom pessoal, simplesmente com essa refatoração, criando este módulo Network, nós já vimos que o nosso projeto já se tornou um pouco mais organizado. Criando esses arquivos adicionais também, nós temos um arquivo aqui principal muito mais simples, que referencia agora o nosso módulo de Network, onde temos simplesmente recursos relacionados à rede. Então nós já temos aqui um projeto mais estruturado, um projeto mais organizado. A questão é que este módulo não nos permite nenhuma customização. E a ideia dos módulos é permitir a reutilização deste módulo em diferentes projetos. Então nós vamos trabalhar agora pensando nisso, tendo esse mindset de reutilização do módulo. Então nós vamos abrir aqui o arquivo main.tf no módulo de network e a primeira coisa que nós temos aqui é um recurso sendo definido, e esse recurso é o recurso exampleVpc tá? Primeiro, que uma boa coisa que nós podemos fazer aqui é renomear, né? exampleVpc eu acho que é um nome muito interessante, então nós vamos colocar aqui somente como sendo Vpc a mesma coisa para exampleSub, então vamos renomear aqui o exemplo subnet, beleza? Vamos aqui renomear também o exemplo IGH do nosso internet gateway e vamos ir tirando todos esses exemplos, né? Eu acho que nós podemos simplesmente aqui substituir tudo que é exemplo por nada, né? Vamos dar um replace aqui e beleza. Então agora eu acho que nós já temos uma nomenclatura um pouquinho melhor, vamos até output Vamos dar um replace aqui. E beleza. Então agora eu acho que nós já temos uma nomenclatura um pouquinho melhor. Vamos até output. Vamos remover também o exemplo dos nossos outputs. Beleza. E agora vamos rodar aqui o nosso Terraform plan. Só para nós verificarmos se nós não quebramos nada. Sempre que nós refatoramos é bom rodar aqui o Terraform plan para garantir que tudo está funcionando. Perfeito. Temos aqui então a nossa refatoramos é bom rodar o Terraform Play para garantir que tudo está funcionando perfeito, temos aqui então a nossa refatoração ok agora voltando novamente aqui na nossa VPC nós informamos aqui o bloco CIDR, então REND de IPs eu acho que essa é uma boa coisa de nós de nós deixarmos customizável, então ao invés de nós deixarmos hardcode aqui, nós vamos ter uma variável que será a variável dpc ciderblock, tá? ciderblock. E é por isso que nós precisamos de defini-la aqui em variables. Então, nós teremos aqui variable dpc ciderblock e o tipo dessa variável será string. Beleza. Temos essa variável aqui, vamos deixar como variável por enquanto. Agora nós temos a nossa subnet e é claro que nós não podemos agora de forma alguma deixar este bloco como sendo o bloco de IP da nossa subnet como sendo hardcode. Agora nós precisamos de receber também das variáveis. Mas eu gostaria também de alterar essa subnet aqui para o seguinte. É bem comum que nós tenhamos várias subnets. Então a ideia de ter subnet é justamente dividir a sua rede em várias porções diferentes, em vários grupos diferentes, para que você possa administrá-las, cada uma com suas particularidades, cada uma com seu rende específico. Às vezes uma subnet precisa ser pública, outra vai ser privada e assim por diante. Então nós teremos, na verdade, um conjunto de subnets. Eu já vou renomear aqui para subnets e agora nós já vamos aprender algo novo, que é um meta-atributo, um meta-property do Terraform, que é o count. Então sempre que nós precisamos de criar vários recursos com a mesma configuração, nós podemos utilizar este count. Então, nós vamos utilizar aqui count. E agora, nós faremos o seguinte, nós poderíamos colocar aqui 2, poderíamos colocar 3 ou qualquer número que nós quiséssemos. Mas nós também deixaremos isso parametrizável, customizável. Será da seguinte forma, eu vou colocar aqui length, que é uma função também do terraform, e nós vamos colocar aqui var subnet ciderblocks. Dessa forma, subnet ciderblocks. Por quê? Porque nós teremos uma outra variável aqui dentro, nós já vamos definir aqui, variable subnet ciderider blocks, e o tipo dessa variável será uma lista de string, então utilizando esse lenfe aqui nós podemos pegar a quantidade de itens que existem nesses cider blocks, tá? E agora vem a dúvida, né? Como que nós vamos referenciar cada um desses blocos aqui dentro desse cider block? E é bem interessante, na verdade. Nós temos a seguinte opção, tá? Nós vamos copiar aqui var.subnet CIDER blocks. Eu vou substituir aqui. E nós podemos utilizar o índice aqui dentro. Poderíamos colocar 0, 1, 2 e assim por diante. Mas nós não sabemos qual é o índice que nós precisamos utilizar. E nós estamos criando vários recursos. Então, nós utilizamos para isso count.index. Então, se nós tivermos aqui, por exemplo, três blocos, vamos supor que nós passamos três blocos aqui. Quando nós utilizarmos count, nós teremos o valor 3 e ele vai criar um recurso e para este recurso count.index vai ser zero. Depois ele vai criar um outro recurso onde count.index vai ser 1. E depois ele criará um terceiro recurso countIndex vai ser 0. Depois ele vai criar um outro recurso onde countIndex vai ser 1. E depois ele criará um terceiro recurso onde countIndex vai ser 2. Então dessa forma nós podemos fazer essa referência do índice do nosso count. E aí outro problema que nós já vemos aqui é o seguinte, nós temos a nossa availability zone aqui hard. E quando nós trabalhamos com subnets, geralmente nós queremos uma subnet em cada availability zone, em cada AZ. E uma forma que nós podemos deixar isso aqui customizável, randômico, é utilizando um data source. Esse data source aqui, que é o data source AWS availability zones. Nós estamos chamando de available, esse nome depende de você você pode colocar o nome que você quiser e que o State é Available então nós queremos pegar simplesmente as A's disponíveis para a nossa região e agora basta nós referenciarmos esse Data Source aqui então nós teremos Data. aí o próprio VS Code já nos ajuda Available e nós vamos referenciar utilizando o nosso count, tá? count.index. Então nós teremos aqui uma referência randômica para as nossas zonas de disponibilidade. Na verdade nós precisamos do nome, tá? Do nome da nossa availability zone. Então nós temos aqui available.names e dessa forma nós referenciamos a zona de disponibilidade. Porém nós temos um problema aqui que é o seguinte, nós podemos criar vários subnets dentro da nossa VPC. Nós poderíamos criar, por exemplo, 10 subnets. O problema é que nós não temos 10 AZs para cada região. Eu acho que nós não temos nenhuma região que possua 10 AZs. Então região. Eu acho que nós não temos nenhuma região que possua 10 AZs. Então, como nós podemos resolver esse problema? Como nós garantimos que nós vamos distribuir essas subnets de forma igualitária entre todas essas AZs? E é bem simples. Nós podemos utilizar aqui a operação de modulo. Então, nós vamos pegar o resto da divisão entre count index e a quantidade de availability zones que nós temos. Nós teremos aqui length, beleza? E aqui nós vamos passar a quantidade de zonas de disponibilidade. Beleza? Espero que você tenha entendido essa parte aqui. Então, vamos para um exemplo. Imagina que nós tenhamos aqui cinco subnets, mas que na nossa região nós tenhamos simplesmente três zonas de disponibilidade disponíveis, com estado aqui available. Nós teremos, então, um recurso sendo criado com índice zero, e aí nós teremos o seguinte, o resto da divisão entre zero e três, que é a quantidade de az's, é igual a 0. E depois nós teremos o resto da divisão entre 1 e 3 é igual a 1, depois nós teremos o resto da divisão entre 2 e 3 é igual a 2, e por fim nós teremos que o resto da divisão entre 3 e 3 é igual a 2. E por fim nós teremos que o resto da divisão entre 3 e 3 é igual a 0. Então nós teremos sempre um valor entre 0 e 2. E dessa forma nós não iremos acessar nenhum valor indisponível. Nós não tentaremos fazer nenhum acesso indisponível nesse array. Beleza? Então nós já temos aqui agora as nossas subnets. Temos uma lista de subnets aqui, e nós vamos criar também uma tag, vamos criar uma tag, e nós vamos passar aqui name, vamos passar name, e nós vamos colocar agora algo interessante, vamos criar uma outra variável, variable, que será prefix. Prefix, e aqui nós teremos type do tipo string. E aqui para o nome, para a tag que representa o nome da nossa subnet, nós teremos var.prefix, e aqui nós teremos subnet, e aqui nós vamos ter o índice dessa subnet. Então nós vamos acessar aqui de novo, count.index. Por que é importante nós termos esse prefixo aqui? Quando nós utilizamos a tag name, nós vamos mostrar ali no console da AWS o campo name. Nós vamos mostrar essa informação no campo name. Nós fazemos isso utilizando a tag name. no campo name, nós fazemos isso utilizando a tag name. A questão é que, se nós formos reutilizar este módulo, o que é a ideia entre vários projetos, se nós não utilizarmos aqui um prefixo, nós teremos sempre o mesmo nome, então nós vamos confundir, vai ser um pouco difícil de gerenciar. Tendo um prefixo e cada projeto utilizando um prefixo diferente, fica mais fácil de nós administrarmos esse recurso e de nós acessarmos esse recurso lá no console da AWS. Certo? Então temos aqui agora as nossas subnets, temos aqui o nosso Internet Gateway referenciando, tudo certo, VPC, a nossa Route Table aqui também tudo certo, temos uma associação entre a nossa subnet e a nossa Route Table, mas agora nós não temos uma única subnet, nós temos várias subnets, então nós precisamos utilizar aqui o count novamente, utilizar length e aqui referenciar a subnet cider blocks e agora nós vamos aqui fazer esse acesso, count.index novamente, beleza? beleza temos aqui então a nossa associação vamos associar essa route table com cada uma das nossas subnets deixa eu verificar se nós temos mais alguma outra coisa aqui para nós ajustarmos eu acho que nós podemos colocar também uma tag aqui na nossa vpc vamos colocar aqui tags, beleza, vamos só mudar aqui de subnet para VPC, aqui nós não precisamos desse index, tá, nós não temos na verdade nem esse index aqui disponível, beleza, acho que nós podemos colocar essa tag na maioria dos nossos recursos, tá, internet gateway, acho que vou deixar sem nome mesmo, belezaleza? Aqui agora no nosso security group, aqui já é importante nós colocarmos aqui um prefixo. Então, deixa eu ajustar o nome desse security group para o seguinte nome. Beleza? Nós vamos colocar aqui var prefixo barra allow ssh. Vamos colocar aqui também na tag, tá? Esse recurso aqui particularmente ele tem um nome, mas nós precisamos setar também a tag name beleza, aqui temos uma associação agora do nosso security group com as nossas regras, na verdade nós estamos criando as nossas regras para o security groups perfeito, eu acho que aqui no arquivo main.tf nós já temos tudo o que nós precisávamos agora nós vamos aqui dar uma olhada em Outputs, onde nós estamos agora expondo a nossa subnet ID. Mas a ideia aqui agora é que nós possamos expor uma lista de subnets. Então nós vamos colocar aqui Value e nós vamos fazer o seguinte, nós vamos colocar essa anotação aqui, subnets. Dessa forma, nós vamos expor uma lista dos IDs das subnets. Então, quando nós queremos fazer uma projeção de um determinado campo de uma lista, nós utilizamos essa sintaxe, tá? Nós colocamos asterisco aqui e depois projetamos o campo que nós queremos projetar, ou o atributo que nós queremos projetar, né? Security group, tudo certo. Agora nós vamos fechar aqui, vamos voltar no nosso arquivo main aqui do módulo raiz, e agora nós já temos um erro, tá? Por quê? Porque nós precisamos de passar variáveis aqui para o nosso módulo. E a primeira variável que nós teremos é a nossa VPC CiderBlock, tá?, nós vamos definir aqui o nosso CIDER BLOCK. Vamos colocar o mesmo, né? Dessa forma, 16, ok. Agora, nós precisamos definir as nossas subnets, beleza? É uma lista de string aqui. Nós vamos colocar da seguinte forma. Vamos definir essa daqui, barra 24, e vamos definir também uma outra barra 24. Perfeito, vamos colocar agorara 24. Perfeito. Vamos colocar agora aqui 1.024. Já temos também as nossas subnets. Nós precisamos do nosso prefixo, né? Então vamos colocar aqui prefixo full-size. E beleza. Eu acho que nós já não temos mais nenhum erro aqui, tá? Mas é claro que nós vamos descobrir se tudo está certo mesmo quando nós rodarmos o nosso Terraform Plane. Vamos esperar aqui que seja executado, nós estamos referenciando um recurso que não está declarado assim, nós esquecemos de colocar subnets aqui, então deixa eu voltar aqui no nosso módulo de rede, beleza, main aqui na parte de route route association, né, isso, nós precisamos colocar aqui subnets ao invés de subnets somente, deixa eu verificar se eu tenho algum outro lugar onde eu estou utilizando somente subnet bom, vamos executar de novo aqui, nós veremos se nós teremos algum outro problema, né terraform plane, temos aqui assim nós estamos agora associando com subnet id se nós teremos algum outro problema, né? Terraform plane, temos aqui, assim, nós estamos agora associando com subnet ID, vamos voltar então no nosso módulo principal, no nosso main.tf, onde nós precisamos aqui na nossa instância agora, associar na verdade, subnet ID, deixa eu verificar qual é o nome certinho aqui, output, subnet ID, acho que seria melhor subnet, subnet ids, isso, colocar dessa forma aqui, que fica um pouquinho melhor, e aqui nós vamos colocar nesse primeiro momento, simplesmente na primeira subnet, vamos referenciar aqui, hardcode, o índice 0, beleza, agora voltando aqui, vamos lá no Terraform Play, novamente nós temos um erro aqui, que Module Network is an Object, então nós não temos um atributo nomeado Subnet IDs, vamos verificar aqui por que, vamos voltar aqui no nosso output novamente, nós temos a AWS, vamos verificar aqui de novo no main aqui, bom, depois de alguns segundos eu consegui encontrar o problema, que foi que eu não salvei os arquivos, então depois de salvar os dois arquivos aqui, arquivo de output, o nosso arquivo main.tf, agora sim, nós já não temos mais nenhum erro, a forma de associar aqui está correta, então se nós botarmos aqui Terraform Play novamente, nós teremos o nosso plano sendo executado com sucesso. E agora, eu vou rodar Terraform, na verdade, antes de eu rodar Terraform Apply, vamos dar uma analisada no nosso plano, né? Para verificar se tudo está funcionando como nós previmos anteriormente, beleza? Agora nós temos vários recursos aqui. Vamos dar uma olhada primeiro na nossa instância. Aqui não tem muito que nós precisamos conferir na parte da instância. Temos o nosso Internet Gateway, a nossa Route Table. Aqui nós temos uma associação, então aqui nós já temos algo importante. Nós temos um recurso que possui um índice. Nós temos uma associação 0 e temos uma associação 1. Então aqui nós já podemos ver como nós podemos criar vários recursos utilizando aquele count. Perfeito, temos esses dois recursos criados, ok, SG. Agora nós estamos criando a nossa subnet, subnet 0. Aqui estamos utilizando o CIDER block 10.0.0.0-24 E temos a outra subnet utilizando agora 10.0.1.0-24 Então parece que tudo está ok A nossa VPC utilizando esse bloco CIDER 10.0.0.0-16 Ok, e eu acho que tudo está certo Para a gente conferir, vamos só dar aqui o nosso terraform apply já vou dar um auto approve e nós iremos verificar se tudo está funcionando, é claro que nós podemos, ao invés de deixar os valores hardcode no nosso arquivo main .tf, nós podemos criar um arquivo de variáveis especificamente para o arquivo para o nosso root module para o nosso root module, para o nosso módulo raiz. Então nós faremos o seguinte, nós teremos aqui variables.tf, onde nós teremos primeiro a nossa variable. Nós podemos inclusive copiar aqui do nosso módulo network. Vamos aqui fazer isso, copiando, e aqui eu vou colar dentro de variables.tf. Essas variáveis aqui agora elas se referem ao nosso módulo raiz. Teremos prefix, teremos o nosso CIDER block, tanto para subnet quanto para VPC. E agora, aqui basta nós fazermos a referência, né? Ao invés de nós termos hardcode aqui no nosso bootmodule, teremos var prefix var subnet slider blocks na verdade aqui é vpc e aqui que é o prefixo beleza, var prefix e agora o nosso arquivo deixa eu verificar aqui nós não temos um arquivo de variáveis então vamos criar um arquivo de variáveis vamos criar aqui o terraform .tfvars arquivo de arquivo de variáveis, então vamos criar um arquivo de variáveis vamos criar aqui o terraform.tfparts o arquivo de definição de variáveis, onde agora o nosso prefixo será fullcycle vamos colocar aqui fullcycle, vamos definir agora a nossa VPC Cider Block, novamente vai ser o mesmo bloco barra 16, e agora teremos a nossa lista de subnetsIDER blocks. Beleza? Deixa eu copiar aqui. Deixa eu remover esse cara. E agora nós teremos aqui 0024 e 1024. O nome aqui da variável está incorreto, deixa eu colocar aqui, subnet, ciderblocks, e agora sim, agora eu acho que temos refatorado certinho, provavelmente se nós executarmos aqui terraform plan, nós não teremos nenhuma alteração. Vamos rodar aqui, terraform plan, está verificando, dando um refresh no estado. Vamos aguardar alguns segundos e não tem nenhuma alteração. Então a nossa infatoração foi concluída com sucesso. Agora deixa eu dar uma olhada. Nós podemos dar uma olhada lá no nosso console. Deixa eu abrir aqui uma outra aba. Uma outra aba do meu navegador. Só um momento. Beleza. Deixa eu colocar ela aqui à frente e deixa eu redimensionar ela para Já estou logado, já tenho a minha sessão aqui. Se nós observarmos aqui esse 2, nós temos a nossa instância rodando. Beleza. Nós vamos agora dar uma olhada aqui em VPC. Inc depois nós vamos colocar um nome para a nossa instância, nós vamos colocar a tag name para nós conseguimos identificar um pouco melhor. VPCs agora nós teremos a nossa full cycle VPC, ok, e subnets, nós temos duas subnets, a subnet full cycle subnet 0 e a full cycle subnet 1, e nós podemos observar aqui o slider block dessas duas subnets. Então agora a nossa infraestrutura está ok, nós já estamos utilizando o módulo, nós já verificamos como nós podemos passar informações para esses módulos, como podemos customizar esses módulos utilizando variáveis. E vimos também como fazer o binding de variáveis lá no root module, no módulo raiz. Certo? Mas nós continuaremos criando mais módulos a partir da próxima aula. Eu espero que você esteja gostando. Vejo você lá!