"
+
+ }
+ }
+ }]
+}
+
+output "load_balancer_dns_name" {
+ value = "http://${module.ecs_mentoria.loadbalance_dns_name}"
+}
+
+```
+
+### Provisionando Cluster ECS
+Após preencher os valores requiridos utilize os comandos abaixo para provisonar cluster e suas aplicação.
+
+```shell
+terraform init
+terraform fmt
+terraform validate
+terraform plan
+terraform apply
+```
+
+### Descrição dos comandos:
+Segue uma breve descrição dos comandos listados acima.
+>**terraform init**: Execute o terraform init para baixar todos os plugins necessários.
+
+>**terraform fmt**: O comando é usado para reescrever os arquivos de configuração do Terraform para um formato e estilo canônicos.
+
+>**terraform validate**: Comando valida sintaticamente os arquivos de configuração em um diretório.
+
+>**terraform plan**: Executar um plano de terraform e colocá-lo em um arquivo chamado plano.
+
+>**terraform apply**: Usa plano para aplicar as alterações na AWS.
diff --git a/autoscaling.tf b/autoscaling.tf
new file mode 100644
index 0000000..17f3708
--- /dev/null
+++ b/autoscaling.tf
@@ -0,0 +1,42 @@
+resource "aws_appautoscaling_target" "ecs_target" {
+ count = local.cluster_count
+ max_capacity = 2
+ min_capacity = 1
+ resource_id = "service/${aws_ecs_cluster.cluster_iac[0].name}/${aws_ecs_service.service_cluster[0].name}"
+ scalable_dimension = "ecs:service:DesiredCount"
+ service_namespace = "ecs"
+}
+
+resource "aws_appautoscaling_policy" "memory" {
+ count = local.cluster_count
+ name = "memory"
+ policy_type = "TargetTrackingScaling"
+ resource_id = aws_appautoscaling_target.ecs_target[0].resource_id
+ scalable_dimension = aws_appautoscaling_target.ecs_target[0].scalable_dimension
+ service_namespace = aws_appautoscaling_target.ecs_target[0].service_namespace
+
+ target_tracking_scaling_policy_configuration {
+ predefined_metric_specification {
+ predefined_metric_type = "ECSServiceAverageMemoryUtilization"
+ }
+
+ target_value = 80
+ }
+}
+
+resource "aws_appautoscaling_policy" "cpu" {
+ count = local.cluster_count
+ name = "cpu"
+ policy_type = "TargetTrackingScaling"
+ resource_id = aws_appautoscaling_target.ecs_target[0].resource_id
+ scalable_dimension = aws_appautoscaling_target.ecs_target[0].scalable_dimension
+ service_namespace = aws_appautoscaling_target.ecs_target[0].service_namespace
+
+ target_tracking_scaling_policy_configuration {
+ predefined_metric_specification {
+ predefined_metric_type = "ECSServiceAverageCPUUtilization"
+ }
+
+ target_value = 80
+ }
+}
diff --git a/cloudwatch.tf b/cloudwatch.tf
new file mode 100644
index 0000000..dd0f3de
--- /dev/null
+++ b/cloudwatch.tf
@@ -0,0 +1,7 @@
+resource "aws_cloudwatch_log_group" "main" {
+ name = "${var.service_name}-log"
+ retention_in_days = "7"
+ kms_key_id = null #tfsec:ignore:AWS089
+
+ tags = var.tags
+}
diff --git a/cluster.tf b/cluster.tf
new file mode 100644
index 0000000..5ad5153
--- /dev/null
+++ b/cluster.tf
@@ -0,0 +1,11 @@
+resource "aws_ecs_cluster" "cluster_iac" {
+ count = local.cluster_count
+ name = var.cluster_name
+
+ setting {
+ name = "containerInsights"
+ value = var.container_insights ? "enabled" : "disabled"
+ }
+
+ tags = var.tags
+}
diff --git a/how-to-use-this-module/README.md b/how-to-use-this-module/README.md
index 5d519e9..688ef4d 100644
--- a/how-to-use-this-module/README.md
+++ b/how-to-use-this-module/README.md
@@ -1,132 +1,81 @@
# Template de módulo Terraform
-## Dependências
-
-Para realizar os testes localmente é necessário:
-
-| Ferramentas | Versão | Instalação |
-| ----------- | ------ | ---------- |
-| Terraform | >= 1.0.0 | [Acesse](https://learn.hashicorp.com/tutorials/terraform/install-cli) |
-| Docker | >= 20.10 | [Acesse](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04-pt) |
-| Shipyard.run | >= 0.3.36 | [Acesse](https://shipyard.run/docs/install) |
-| Git | >= 2.30.2 | [Acesse](https://git-scm.com/downloads) |
-
-# Criando o ambiente para a API do Hashicups
-
-Instalação do Shipyard.run
-
-```
-
-curl https://shipyard.run/install | bash
-
-```
-
-Clone o repositório e acesse a pasta blueprint
-
-```
-
-git clone https://github.com/hashicorp-demoapp/product-api-go
-cd product-api-go/blueprint/
-
-```
-
-Inicie a aplicação executando o comando a baixo
-
-```
-
-shipyard run
-
-```
-
-Saída Esperada
-
-```bash
-
-The API can be accessed at
-[http://localhost:19090/coffees](http://localhost:19090/coffees)
-
-```
-
-Crie um usuário para a aplicação
-
-```
-
-curl -X POST localhost:19090/signup -d '{"username":"mentoriaiac", "password":"2021@mentoria"}'
-
-```
-
-# Utilizando o módulo
-
-### Primeiro Passo:
-
-Acesse o repósitorio do módulo :
-
-
-
-├── product-api-go
-│ ├── blueprint
-│ ├── client
-│ ├── config
-│ ├── data
-│ │ └── model
-│ ├── database
-│ ├── docker_compose
-│ ├── functional_tests
-│ │ └── features
-│ ├── handlers
-│ └── telemetry
-└── template-modulo-terraform
- └── how-to-use-this-module
-
-
-
-Depois acesse a pasta how-to-use-this-module
-
-```
-
-cd ./how-to-use-this-module/
-
-```
-
-Inicialize o Terraform
-
-```
-
-terraform init
-
-```
-
-### Segundo Passo:
-
-Personalize o `terrafile.tf`:
-
-```
- order = {
- Terraspresso = 4,
- Nomadicano = 10,
- "Vagrante espresso" = 4,
- Packer Spiced Latte = 6,
- Vaulatte = 8,
- Connectaccino = 2
- }
-
-```
-
-Tente criar o primeiro plan:
-```
-
+### Pré-Requisitos
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.0.0 |
+
+### Criar `terrafile.tf`
+Crie um arquivo `terraform.tf` com o seguinte conteúdo. E altere os valores das variáveis.
+
+```hcl
+module "ecs_mentoria" {
+ source = "git@github.com:mentoriaiac/iac-modulo-aws-ecs.git?ref=v1.0"
+ cria_cluster = true
+ app_port = 80
+ app_count = 1
+ fargate_cpu = 256
+ fargate_memory = 512
+ subnet_ids = ["", ""]
+ vpc_id = ""
+ protocol = "HTTP"
+ family_name = ""
+ service_name = ""
+ cluster_name = ""
+ template_container = [{
+ name = ""
+ image = ""
+ cpu = 128
+ memory = 256
+ essential = true
+ portMappings = [{
+ containerPort = 80
+ hostPort = 80
+ }]
+ logConfiguration = {
+ logDriver = "awslogs"
+ options = {
+ awslogs-group = ""
+ awslogs-region = "us-east-1"
+ awslogs-stream-prefix = ""
+
+ }
+ }
+ }]
+ tags = {
+ key = "value"
+ key = "value"
+ key = "value"
+ key = "value"
+ }
+}
+
+output "load_balancer_dns_name" {
+ value = "http://${module.ecs_mentoria.loadbalance_dns_name}"
+}
+
+```
+
+### Provisionando Cluster ECS
+Após preencher os valores requiridos utilize os comandos abaixo para provisonar cluster e suas aplicação.
+
+```shell
+terraform init
+terraform fmt
+terraform validate
terraform plan
-
+terraform apply
```
-Obs.: Caso retorne erro 401, verifique o usuário e a senha.
-
-### Terceiro Passo:
+### Descrição dos comandos:
+Segue uma breve descrição dos comandos listados acima.
+>**terraform init**: Execute o terraform init para baixar todos os plugins necessários.
-Aplique suas mudanças:
+>**terraform fmt**: O comando é usado para reescrever os arquivos de configuração do Terraform para um formato e estilo canônicos.
-```
+>**terraform validate**: Comando valida sintaticamente os arquivos de configuração em um diretório.
-terraform apply
+>**terraform plan**: Executar um plano de terraform e colocá-lo em um arquivo chamado plano.
-```
\ No newline at end of file
+>**terraform apply**: Usa plano para aplicar as alterações na AWS.
diff --git a/how-to-use-this-module/container_definitions.json b/how-to-use-this-module/container_definitions.json
new file mode 100644
index 0000000..33e9f8f
--- /dev/null
+++ b/how-to-use-this-module/container_definitions.json
@@ -0,0 +1,29 @@
+[
+ {
+ "cpu": 256,
+ "image": "chnacib/mariaquiteria:latest",
+ "memory": 512,
+ "name": "api",
+ "networkMode": "awsvpc",
+ "portMappings": [
+ {
+ "containerPort": 8000,
+ "hostPort": 8000
+ }
+ ],
+ "environment": [
+ {
+ "name": "AWESOME_ENV_VAR",
+ "value": "/mariaquiteria/aws_s3_region"
+ }
+ ],
+ "logConfiguration": {
+ "logDriver": "awslogs",
+ "options": {
+ "awslogs-group": "mentoria-log",
+ "awslogs-region": "us-east-1",
+ "awslogs-stream-prefix": "myawesomeapp"
+ }
+ }
+ }
+ ]
\ No newline at end of file
diff --git a/how-to-use-this-module/terrafile.tf b/how-to-use-this-module/terrafile.tf
index b8dec3b..5929eba 100644
--- a/how-to-use-this-module/terrafile.tf
+++ b/how-to-use-this-module/terrafile.tf
@@ -1,16 +1,42 @@
-provider "hashicups" {
- username = "mentoriaiac"
- password = "2021@mentoria"
+
+provider "aws" {
+ region = "us-east-1"
+}
+
+data "template_file" "container_definitions" {
+ template = file("./container_definitions.json")
}
-module "hashicups_order" {
- source = "../"
- order = {
- Terraspresso = 4,
- Nomadicano = 10
- }
+module "ecs_mentoria" {
+ source = "../"
+ create_cluster = true
+ app_count = 1
+ fargate_cpu = 256
+ fargate_memory = 512
+ subnet_ids = ["subnet-08e28abe0bb8c94cc", "subnet-0f22a250f019b5e1d"]
+ vpc_id = "vpc-0bf0d67ed0acdbd2a"
+ protocol = "HTTP"
+ family_name = "mentoria"
+ service_name = "mentoria"
+ cluster_name = "mentoria"
+ container1_name = "api"
+ container1_port = 8000
+ container_definitions = data.template_file.container_definitions.rendered
+
+ tags = {
+ Env = "production"
+ Team = "tematico-terraform"
+ System = "api-tika"
+ CreationWith = "terraform"
+ Repository = "https://github.com/mentoriaiac/iac-modulo-aws-ecs"
+ }
}
-output "hashicups_order_id" {
- value = module.hashicups_order.order_id
+output "load_balancer_dns_name" {
+ value = "http://${module.ecs_mentoria.loadbalance_dns_name}"
}
+
+output "security_group_id" {
+ value = module.ecs_mentoria.security_group_id
+}
+
diff --git a/iamrole.tf b/iamrole.tf
new file mode 100644
index 0000000..0e55839
--- /dev/null
+++ b/iamrole.tf
@@ -0,0 +1,73 @@
+resource "aws_iam_role" "ecs_task_execution_role" {
+ name = "allow_execution_svc_log"
+ assume_role_policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Sid = ""
+ Principal = {
+ Service = [
+ "ecs-tasks.amazonaws.com",
+ ]
+ }
+ },
+ ]
+ })
+ tags = var.tags
+}
+
+resource "aws_iam_role_policy_attachment" "ecs_task_execution_role" {
+ role = aws_iam_role.ecs_task_execution_role.name
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
+}
+
+resource "aws_iam_policy" "ecs_task_ssm_policy" {
+ name = "allow_ssm_parameter"
+ policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Action = [
+ "ssm:GetParameters",
+ "secretsmanager:GetResourcePolicy",
+ "secretsmanager:GetSecretValue",
+ "secretsmanager:DescribeSecret",
+ "secretsmanager:ListSecretVersionIds",
+ "secretsmanager:ListSecrets"
+ ]
+ Effect = "Allow"
+ Resource = "*"
+ },
+ ]
+ })
+ tags = var.tags
+}
+
+resource "aws_iam_policy" "ecs_task_s3_policy" {
+ name = "s3_access"
+ policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Action = ["s3:*"]
+ Effect = "Allow"
+ Resource = "*"
+ },
+ ]
+ })
+ tags = var.tags
+
+}
+
+
+resource "aws_iam_role_policy_attachment" "ecs_task_ssm_attach" {
+ role = aws_iam_role.ecs_task_execution_role.name
+ policy_arn = aws_iam_policy.ecs_task_ssm_policy.arn
+}
+
+resource "aws_iam_role_policy_attachment" "ecs_task_s3_attach" {
+ role = aws_iam_role.ecs_task_execution_role.name
+ policy_arn = aws_iam_policy.ecs_task_s3_policy.arn
+}
\ No newline at end of file
diff --git a/img/ecs-mentoria.png b/img/ecs-mentoria.png
new file mode 100644
index 0000000..6607a6c
Binary files /dev/null and b/img/ecs-mentoria.png differ
diff --git a/loadbalance.tf b/loadbalance.tf
new file mode 100644
index 0000000..10da6f0
--- /dev/null
+++ b/loadbalance.tf
@@ -0,0 +1,33 @@
+resource "aws_lb" "iac_lb" {
+ name = "load-balance-${var.cluster_name}"
+ internal = false #tfsec:ignore:AWS005
+ load_balancer_type = "application"
+ security_groups = aws_security_group.allow_access[*].id
+ subnets = var.subnet_ids
+ drop_invalid_header_fields = true
+
+ enable_deletion_protection = var.delete_protection
+
+ tags = var.tags
+}
+
+resource "aws_lb_target_group" "iac_tg" {
+ name = "target-group-${var.cluster_name}"
+ port = var.container1_port
+ protocol = var.protocol
+ vpc_id = var.vpc_id
+ target_type = "ip"
+}
+
+resource "aws_lb_listener" "iac_listener" {
+ load_balancer_arn = aws_lb.iac_lb.arn
+ port = 80
+ protocol = var.protocol #tfsec:ignore:AWS004
+ ssl_policy = var.policy_ssl
+ certificate_arn = var.certificate_arn
+
+ default_action {
+ type = "forward"
+ target_group_arn = aws_lb_target_group.iac_tg.arn
+ }
+}
diff --git a/local.tf b/local.tf
new file mode 100644
index 0000000..16ec69b
--- /dev/null
+++ b/local.tf
@@ -0,0 +1,3 @@
+locals {
+ cluster_count = var.create_cluster ? 1 : 0
+}
diff --git a/main.tf b/main.tf
deleted file mode 100644
index 7f5a61b..0000000
--- a/main.tf
+++ /dev/null
@@ -1,18 +0,0 @@
-data "hashicups_coffees" "all" {}
-
-locals {
- coffee_name_id_map = { for coffee in data.hashicups_coffees.all.coffees : coffee.name => coffee.id }
-}
-
-resource "hashicups_order" "order" {
- dynamic "items" {
- for_each = var.order
- content {
- coffee {
- id = local.coffee_name_id_map[items.key]
- }
- quantity = items.value
- }
- }
-}
-
diff --git a/output.tf b/output.tf
new file mode 100644
index 0000000..dd46b7c
--- /dev/null
+++ b/output.tf
@@ -0,0 +1,7 @@
+output "loadbalance_dns_name" {
+ value = aws_lb.iac_lb.dns_name
+}
+
+output "security_group_id" {
+ value = aws_security_group.allow_access.id
+}
diff --git a/outputs.tf b/outputs.tf
deleted file mode 100644
index cba5e7b..0000000
--- a/outputs.tf
+++ /dev/null
@@ -1,3 +0,0 @@
-output "order_id" {
- value = resource.hashicups_order.order.id
-}
diff --git a/service.tf b/service.tf
new file mode 100644
index 0000000..d840e9c
--- /dev/null
+++ b/service.tf
@@ -0,0 +1,24 @@
+resource "aws_ecs_service" "service_cluster" {
+ count = local.cluster_count
+ name = var.service_name
+ cluster = aws_ecs_cluster.cluster_iac[0].arn
+ task_definition = aws_ecs_task_definition.task_cluster.arn
+ launch_type = "FARGATE"
+ desired_count = var.app_count
+
+ network_configuration {
+ subnets = var.subnet_ids
+ assign_public_ip = true
+ security_groups = aws_security_group.allow_access[*].id
+ }
+
+ load_balancer {
+ target_group_arn = aws_lb_target_group.iac_tg.id
+ container_name = var.container1_name
+ container_port = var.container1_port
+ }
+
+ tags = var.tags
+
+ depends_on = [aws_iam_role.ecs_task_execution_role]
+}
diff --git a/sg.tf b/sg.tf
new file mode 100644
index 0000000..dde4847
--- /dev/null
+++ b/sg.tf
@@ -0,0 +1,24 @@
+resource "aws_security_group" "allow_access" {
+ vpc_id = var.vpc_id
+ name = "${var.service_name}-sg"
+ description = "Permite acesso app ${var.family_name}"
+
+ ingress {
+ description = "allow app port"
+ from_port = 80
+ to_port = var.container1_port
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:AWS008
+ }
+
+ egress {
+ description = "allow app port"
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:AWS009
+ ipv6_cidr_blocks = ["::/0"] #tfsec:ignore:AWS009
+ }
+
+ tags = var.tags
+}
diff --git a/task-definition.tf b/task-definition.tf
new file mode 100644
index 0000000..575c645
--- /dev/null
+++ b/task-definition.tf
@@ -0,0 +1,12 @@
+resource "aws_ecs_task_definition" "task_cluster" {
+ family = var.family_name
+ requires_compatibilities = ["FARGATE"]
+ cpu = var.fargate_cpu
+ memory = var.fargate_memory
+ network_mode = "awsvpc"
+ task_role_arn = aws_iam_role.ecs_task_execution_role.arn
+ container_definitions = var.container_definitions
+ execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
+
+ tags = var.tags
+}
diff --git a/variables.tf b/variables.tf
index 8a49fe8..bc26830 100644
--- a/variables.tf
+++ b/variables.tf
@@ -1,4 +1,95 @@
-variable "order" {
- description = "Mapa de cafe e quantidade"
- type = map(number)
+variable "create_cluster" {
+ type = bool
+ default = true
+ description = "Define se cluster será criado"
+}
+
+variable "cluster_name" {
+ type = string
+ description = "Nome do cluster ecs"
+}
+
+variable "container_insights" {
+ type = bool
+ default = true
+ description = "Usado para habilitar CloudWatch Container Insights para o cluster"
+}
+
+variable "delete_protection" {
+ type = bool
+ default = false
+ description = "Impede que terraform exclua o load balance"
+}
+
+variable "service_name" {
+ type = string
+ description = "Nome do service cluster que será criado"
+}
+
+variable "app_count" {
+ type = number
+ description = "Números de tarefas em execução task definition"
+}
+
+
+variable "family_name" {
+ type = string
+ description = "Nome para task definition"
+}
+
+variable "fargate_cpu" {
+ type = number
+ description = "Número de CPUs usados na taskde finition"
+}
+
+variable "fargate_memory" {
+ type = number
+ description = "Quantidade de memória usada pela task definition"
+}
+
+variable "subnet_ids" {
+ type = list(string)
+ description = "Id da subnet"
+}
+
+variable "vpc_id" {
+ type = string
+ description = "Id da vpc"
+}
+
+variable "container1_port" {
+ type = number
+ description = "Porta que será utilizada pelo Container 1"
+}
+
+variable "container1_name" {
+ type = string
+ description = "Nome do Container 1"
+}
+
+variable "protocol" {
+ type = string
+ description = "Protocolo que será utilizado na aplicação "
+}
+
+variable "policy_ssl" {
+ type = string
+ default = null
+ description = "Nome da política SSL. Obrigatório se o protocolo for HTTPS ou TLS"
+}
+
+variable "certificate_arn" {
+ type = string
+ default = null
+ description = "ARN do certificado de servidor SSL padrão"
+}
+
+variable "tags" {
+ type = map(string)
+ description = "Tags para recursos"
+}
+
+variable "container_definitions" {
+ type = string
+ description = "Arquivo de definição do service do ECS"
}
diff --git a/versions.tf b/versions.tf
index a36aaeb..905b1f5 100644
--- a/versions.tf
+++ b/versions.tf
@@ -1,9 +1,7 @@
terraform {
- required_version = ">= 1.0.0"
required_providers {
- hashicups = {
- version = "~> 0.3.1"
+ aws = {
+ version = "~> 4.0"
}
}
}
-