Skip to content

Shorter naming for environment variables #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .terraform-docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
formatter: "markdown"
header-from: main.tf

sort:
enabled: true
by: required

content: |-
{{ .Header }}

![GitHub release](https://img.shields.io/github/release/mongodb/terraform-aws-ecs-task-definition.svg?style=flat-square) ![GitHub](https://img.shields.io/github/license/mongodb/terraform-aws-ecs-task-definition.svg?style=flat-square)

> A Terraform module for creating Amazon [ECS Task Definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html)

## NOTICE

**THIS MODULE IS NOT COMPATIBLE WITH VERSIONS OF TERRAFORM LESS THAN v0.12.x. PLEASE REFER TO THE OFFICIAL [DOCUMENTATION](https://www.terraform.io/upgrade-guides/0-12.html) FOR UPGRADING TO THE LATEST VERSION OF TERRAFORM.**

## Contents

- [Motivation](#motivation)
- [Use Cases](#use-cases)
- [Requirements](#requirements)
- [Usage](#usage)
- [Multiple Container Definitions](#multiple-container-definitions)
- [Inputs](#inputs)
- [Outputs](#outputs)
- [Testing](#testing)
- [License](#license)

## Motivation

The purpose of this module is to generate a valid Amazon [ECS Task Definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html) dynamically. A task definition is required to run Docker containers in Amazon ECS. A task definition contains a list of [container definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definitions) received by the Docker daemon to create a container instance.

### Use Cases

- Have Terraform generate valid task definitions dynamically
- Update the ECS task definition and trigger new [service](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html) deployments automatically (see [examples/ecs_update_service.tf](examples/ecs_update_service.tf))

## Requirements

- [Terraform](https://www.terraform.io/downloads.html)
- [Go](https://golang.org/dl/) (for testing)
## Usage

{{ .Providers }}

{{ .Outputs }}

## available tfvar inputs

```hcl
# null are required inputs,
# others are optional default values

{{ include "example.tfvars" }}
```

{{ .Inputs }}

---
README.md created by: `terraform-docs`

output:
file: "./README.md"
template: |-
<!-- BEGIN_TF_DOCS -->
{{ .Content }}
<!-- END_TF_DOCS -->
269 changes: 132 additions & 137 deletions README.md

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: "3"

tasks:
docs:
dir: ./
desc: Generate documentation for all modules
cmds:
- tfvar . > example.tfvars
- terraform-docs markdown .
- terraform fmt -recursive
45 changes: 45 additions & 0 deletions ecr.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
resource "aws_ecr_repository" "service" {
count = var.ecr_create_repo ? 1 : 0
name = var.ecr_config.repo_name

image_scanning_configuration {
scan_on_push = var.ecr_config.scan_on_push
}
}

resource "aws_ecr_lifecycle_policy" "service" {
count = var.ecr_create_repo ? 1 : 0
repository = aws_ecr_repository.service[0].name

policy = <<EOF
{
"rules": [
{
"rulePriority": 1,
"description": "Expire images older than ${var.ecr_config.repo_remove_untagged_days} days",
"selection": {
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": ${var.ecr_config.repo_remove_untagged_days}
},
"action": {
"type": "expire"
}
},
{
"rulePriority": 2,
"description": "Maximum ${var.ecr_config.repo_max_images} images in the repository",
"selection": {
"tagStatus": "any",
"countType": "imageCountMoreThan",
"countNumber": ${var.ecr_config.repo_max_images}
},
"action": {
"type": "expire"
}
}
]
}
EOF
}
57 changes: 57 additions & 0 deletions example.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
cloudwatch_log_group_prefix = ""
cloudwatch_log_retention_in_days = 30
command = []
cpu = 256
disableNetworking = false
dnsSearchDomains = []
dnsServers = []
dockerLabels = {}
dockerSecurityOptions = []
ecr_config = null
ecr_create_repo = false
enable_cloudwatch = false
entryPoint = []
environment = {}
essential = true
execution_role_arn = ""
extraHosts = []
family = null
healthCheck = {}
hostname = ""
image = "null"
interactive = false
ipc_mode = null
links = []
linuxParameters = {}
logConfiguration = {}
memory = 512
memoryReservation = 0
mountPoints = []
name = ""
network_mode = "awsvpc"
pid_mode = null
placement_constraints = []
portMappings = [{
containerPort = 80
}]
privileged = false
pseudoTerminal = false
readonlyRootFilesystem = false
register_task_definition = true
repositoryCredentials = {}
requires_compatibilities = ["FARGATE"]
resourceRequirements = []
runtime_platform = {
cpu_architecture = "X86_64"
operating_system_family = "LINUX"
}
secrets = []
systemControls = []
tags = {}
task_role_arn = ""
track_latest = false
ulimits = []
user = ""
volumes = []
volumesFrom = []
workingDirectory = ""
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
output "container_definitions" {
value = "${module.merged.container_definitions}"
value = module.merged.container_definitions
}
113 changes: 71 additions & 42 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
# - 2. https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html
# - 3. https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_PortMapping.html
# - 4. https://github.com/hashicorp/terraform/issues/17033
data "aws_region" "current" {}

locals {
command = jsonencode(var.command)
Expand All @@ -36,9 +37,9 @@ locals {
dockerLabels = jsonencode(var.dockerLabels)
dockerSecurityOptions = jsonencode(var.dockerSecurityOptions)
entryPoint = jsonencode(var.entryPoint)
environment = jsonencode(var.environment)
extraHosts = jsonencode(var.extraHosts)

environment = jsonencode(var.environment != {} ? [for k, v in var.environment : { "name" : k, "value" : v }] : [])
healthCheck = replace(jsonencode(var.healthCheck), local.classes["digit"], "$1")

links = jsonencode(var.links)
Expand All @@ -53,7 +54,16 @@ locals {
"$1",
)

logConfiguration = jsonencode(var.logConfiguration)
cloudwatch_log_group_name = "/${var.cloudwatch_log_group_prefix}/ecs/${var.name}"

logConfiguration = var.enable_cloudwatch ? jsonencode({
logDriver = "awslogs"
options = {
awslogs-group = local.cloudwatch_log_group_name
awslogs-region = data.aws_region.current.region
awslogs-stream-prefix = "ecs"
}
}) : jsonencode(var.logConfiguration)

mountPoints = replace(
replace(jsonencode(var.mountPoints), "/\"1\"/", "true"),
Expand Down Expand Up @@ -82,50 +92,58 @@ locals {
digit = "/\"(-[[:digit:]]|[[:digit:]]+)\"/"
}

container_definition = var.register_task_definition ? format("[%s]", data.template_file.container_definition.rendered) : format("%s", data.template_file.container_definition.rendered)
image = var.ecr_create_repo ? "${aws_ecr_repository.service[0].repository_url}:${var.ecr_config.task_definition_tag}" : var.image

template_file = templatefile(
"${path.module}/templates/container-definition.json.tpl",
{
command = local.command == "[]" ? "null" : local.command
cpu = var.cpu == 0 ? "null" : var.cpu
disableNetworking = var.disableNetworking ? true : false
dnsSearchDomains = local.dnsSearchDomains == "[]" ? "null" : local.dnsSearchDomains
dnsServers = local.dnsServers == "[]" ? "null" : local.dnsServers
dockerLabels = local.dockerLabels == "{}" ? "null" : local.dockerLabels
dockerSecurityOptions = local.dockerSecurityOptions == "[]" ? "null" : local.dockerSecurityOptions
entryPoint = local.entryPoint == "[]" ? "null" : local.entryPoint
environment = local.environment == "[]" ? "null" : local.environment
essential = var.essential ? true : false
extraHosts = local.extraHosts == "[]" ? "null" : local.extraHosts
healthCheck = local.healthCheck == "{}" ? "null" : local.healthCheck
hostname = var.hostname == "" ? "null" : var.hostname
image = local.image
interactive = var.interactive ? true : false
links = local.links == "[]" ? "null" : local.links
linuxParameters = local.linuxParameters == "{}" ? "null" : local.linuxParameters
logConfiguration = local.logConfiguration == "{}" ? "null" : local.logConfiguration
memory = var.memory == 0 ? "null" : var.memory
memoryReservation = var.memoryReservation == 0 ? "null" : var.memoryReservation
mountPoints = local.mountPoints == "[]" ? "null" : local.mountPoints
name = var.name == "" ? "null" : var.name
portMappings = local.portMappings == "[]" ? "null" : local.portMappings
privileged = var.privileged ? true : false
pseudoTerminal = var.pseudoTerminal ? true : false
readonlyRootFilesystem = var.readonlyRootFilesystem ? true : false
repositoryCredentials = local.repositoryCredentials == "{}" ? "null" : local.repositoryCredentials
resourceRequirements = local.resourceRequirements == "[]" ? "null" : local.resourceRequirements
secrets = local.secrets == "[]" ? "null" : local.secrets
systemControls = local.systemControls == "[]" ? "null" : local.systemControls
ulimits = local.ulimits == "[]" ? "null" : local.ulimits
user = var.user == "" ? "null" : var.user
volumesFrom = local.volumesFrom == "[]" ? "null" : local.volumesFrom
workingDirectory = var.workingDirectory == "" ? "null" : var.workingDirectory
}
)

container_definition = var.register_task_definition ? format("[%s]", local.template_file) : format("%s", local.template_file)

container_definitions = replace(local.container_definition, "/\"(null)\"/", "$1")
}

data "template_file" "container_definition" {
template = file("${path.module}/templates/container-definition.json.tpl")

vars = {
command = local.command == "[]" ? "null" : local.command
cpu = var.cpu == 0 ? "null" : var.cpu
disableNetworking = var.disableNetworking ? true : false
dnsSearchDomains = local.dnsSearchDomains == "[]" ? "null" : local.dnsSearchDomains
dnsServers = local.dnsServers == "[]" ? "null" : local.dnsServers
dockerLabels = local.dockerLabels == "{}" ? "null" : local.dockerLabels
dockerSecurityOptions = local.dockerSecurityOptions == "[]" ? "null" : local.dockerSecurityOptions
entryPoint = local.entryPoint == "[]" ? "null" : local.entryPoint
environment = local.environment == "[]" ? "null" : local.environment
essential = var.essential ? true : false
extraHosts = local.extraHosts == "[]" ? "null" : local.extraHosts
healthCheck = local.healthCheck == "{}" ? "null" : local.healthCheck
hostname = var.hostname == "" ? "null" : var.hostname
image = var.image == "" ? "null" : var.image
interactive = var.interactive ? true : false
links = local.links == "[]" ? "null" : local.links
linuxParameters = local.linuxParameters == "{}" ? "null" : local.linuxParameters
logConfiguration = local.logConfiguration == "{}" ? "null" : local.logConfiguration
memory = var.memory == 0 ? "null" : var.memory
memoryReservation = var.memoryReservation == 0 ? "null" : var.memoryReservation
mountPoints = local.mountPoints == "[]" ? "null" : local.mountPoints
name = var.name == "" ? "null" : var.name
portMappings = local.portMappings == "[]" ? "null" : local.portMappings
privileged = var.privileged ? true : false
pseudoTerminal = var.pseudoTerminal ? true : false
readonlyRootFilesystem = var.readonlyRootFilesystem ? true : false
repositoryCredentials = local.repositoryCredentials == "{}" ? "null" : local.repositoryCredentials
resourceRequirements = local.resourceRequirements == "[]" ? "null" : local.resourceRequirements
secrets = local.secrets == "[]" ? "null" : local.secrets
systemControls = local.systemControls == "[]" ? "null" : local.systemControls
ulimits = local.ulimits == "[]" ? "null" : local.ulimits
user = var.user == "" ? "null" : var.user
volumesFrom = local.volumesFrom == "[]" ? "null" : local.volumesFrom
workingDirectory = var.workingDirectory == "" ? "null" : var.workingDirectory
}
resource "aws_cloudwatch_log_group" "ecs_task_definition" {
count = var.enable_cloudwatch == true ? 1 : 0

name = "/${var.cloudwatch_log_group_prefix}/ecs/${var.name}"
retention_in_days = var.cloudwatch_log_retention_in_days
}

resource "aws_ecs_task_definition" "ecs_task_definition" {
Expand All @@ -136,6 +154,8 @@ resource "aws_ecs_task_definition" "ecs_task_definition" {
network_mode = var.network_mode
pid_mode = var.pid_mode

track_latest = var.track_latest

# Fargate requires cpu and memory to be defined at the task level
cpu = var.cpu
memory = var.memory
Expand Down Expand Up @@ -184,6 +204,15 @@ resource "aws_ecs_task_definition" "ecs_task_definition" {
}
}
}

dynamic "runtime_platform" {
for_each = var.runtime_platform != null ? [var.runtime_platform] : []
content {
cpu_architecture = upper(runtime_platform.value.cpu_architecture)
operating_system_family = upper(runtime_platform.value.operating_system_family)
}
}

tags = var.tags

count = var.register_task_definition ? 1 : 0
Expand Down
9 changes: 9 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,12 @@ output "revision" {
value = join("", aws_ecs_task_definition.ecs_task_definition.*.revision)
}

output "ecr_repo_name" {
description = "The name of the ECR repository created if ecr_create_repo is true"
value = var.ecr_create_repo == true ? aws_ecr_repository.service[0].name : null
}

output "cloudwatch_log_group_name" {
description = "The name of the CloudWatch log group created if enable_cloudwatch is true"
value = var.enable_cloudwatch ? aws_cloudwatch_log_group.ecs_task_definition[0].name : null
}
Empty file added src/example.tfvars
Empty file.
9 changes: 3 additions & 6 deletions test/varfile.tfvars
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
environment = [
{
name = "AWS_DEFAULT_REGION"
value = "us-east-1"
},
]
environment = {
"AWS_DEFAULT_REGION" = "us-east-1"
}

family = "default"

Expand Down
Loading