diff --git a/.terraform-docs.yaml b/.terraform-docs.yaml new file mode 100644 index 0000000..95cc671 --- /dev/null +++ b/.terraform-docs.yaml @@ -0,0 +1,69 @@ +formatter: "markdown" +header-from: main.tf + +sort: + enabled: true + by: required + +content: |- + {{ .Header }} + +   + + > 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: |- + + {{ .Content }} + diff --git a/README.md b/README.md index 6cb8a29..7ae09d1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ + + +   > A Terraform module for creating Amazon [ECS Task Definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html) @@ -31,155 +34,147 @@ The purpose of this module is to generate a valid Amazon [ECS Task Definition](h - [Terraform](https://www.terraform.io/downloads.html) - [Go](https://golang.org/dl/) (for testing) - ## Usage -This module uses the same parameters as the [`ContainerDefinition`](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html) object. Given the following Terraform configuration: - -```hcl -provider "aws" {} - -module "mongo-task-definition" { - source = "github.com/mongodb/terraform-aws-ecs-task-definition" - - family = "mongo" - image = "mongo:3.6" - memory = 512 - name = "mongo" - - portMappings = [ - { - containerPort = 27017 - }, - ] -} -``` - -Invoking the commands defined below creates an ECS task definition with the following [`containerDefinitions`](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_RegisterTaskDefinition.html#ECS-RegisterTaskDefinition-request-containerDefinitions): - - $ terraform init - $ terraform apply - -```json -[ - { - "command": null, - "cpu": null, - "disableNetworking": false, - "dnsSearchDomains": null, - "dnsServers": null, - "dockerLabels": null, - "dockerSecurityOptions": null, - "entryPoint": null, - "environment": null, - "essential": true, - "extraHosts": null, - "healthCheck": null, - "hostname": null, - "image": "mongo:3.6", - "interactive": false, - "links": null, - "linuxParameters": null, - "logConfiguration": null, - "memory": 512, - "memoryReservation": null, - "mountPoints": null, - "name": "mongo", - "portMappings": [{"containerPort":27017}], - "privileged": false, - "pseudoTerminal": false, - "readonlyRootFilesystem": false, - "repositoryCredentials": null, - "resourceRequirements": null, - "secrets": null, - "systemControls": null, - "ulimits": null, - "user": null, - "volumesFrom": null, - "workingDirectory": null - } -] -``` - -### Multiple Container Definitions - -By default, this module creates a task definition with a single container definition. To create a task definition with multiple container definitions, refer to the documentation of the [`merge`](modules/merge) module. - - ## Providers | Name | Version | |------|---------| -| aws | n/a | -| template | n/a | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:-----:| -| command | The command that is passed to the container | `list(string)` | `[]` | no | -| cpu | The number of cpu units reserved for the container | `number` | `0` | no | -| disableNetworking | When this parameter is true, networking is disabled within the container | `bool` | `false` | no | -| dnsSearchDomains | A list of DNS search domains that are presented to the container | `list(string)` | `[]` | no | -| dnsServers | A list of DNS servers that are presented to the container | `list(string)` | `[]` | no | -| dockerLabels | A key/value map of labels to add to the container | `map(string)` | `{}` | no | -| dockerSecurityOptions | A list of strings to provide custom labels for SELinux and AppArmor multi-level security systems | `list(string)` | `[]` | no | -| entryPoint | The entry point that is passed to the container | `list(string)` | `[]` | no | -| environment | The environment variables to pass to a container | `list(map(string))` | `[]` | no | -| essential | If the essential parameter of a container is marked as true, and that container fails or stops for any reason, all other containers that are part of the task are stopped | `bool` | `true` | no | -| execution\_role\_arn | The Amazon Resource Name (ARN) of the task execution role that the Amazon ECS container agent and the Docker daemon can assume | `string` | `""` | no | -| extraHosts | A list of hostnames and IP address mappings to append to the /etc/hosts file on the container | `list(string)` | `[]` | no | -| family | You must specify a family for a task definition, which allows you to track multiple versions of the same task definition | `any` | n/a | yes | -| healthCheck | The health check command and associated configuration parameters for the container | `any` | `{}` | no | -| hostname | The hostname to use for your container | `string` | `""` | no | -| image | The image used to start a container | `string` | `""` | no | -| interactive | When this parameter is true, this allows you to deploy containerized applications that require stdin or a tty to be allocated | `bool` | `false` | no | -| ipc\_mode | The IPC resource namespace to use for the containers in the task | `string` | `"host"` | no | -| links | The link parameter allows containers to communicate with each other without the need for port mappings | `list(string)` | `[]` | no | -| linuxParameters | Linux-specific modifications that are applied to the container, such as Linux KernelCapabilities | `any` | `{}` | no | -| logConfiguration | The log configuration specification for the container | `any` | `{}` | no | -| memory | The hard limit (in MiB) of memory to present to the container | `number` | `0` | no | -| memoryReservation | The soft limit (in MiB) of memory to reserve for the container | `number` | `0` | no | -| mountPoints | The mount points for data volumes in your container | `list(any)` | `[]` | no | -| name | The name of a container | `string` | `""` | no | -| network\_mode | The Docker networking mode to use for the containers in the task | `string` | `"bridge"` | no | -| pid\_mode | The process namespace to use for the containers in the task | `string` | `"host"` | no | -| placement\_constraints | An array of placement constraint objects to use for the task | `list(string)` | `[]` | no | -| portMappings | The list of port mappings for the container | `list(any)` | `[]` | no | -| privileged | When this parameter is true, the container is given elevated privileges on the host container instance (similar to the root user) | `bool` | `false` | no | -| pseudoTerminal | When this parameter is true, a TTY is allocated | `bool` | `false` | no | -| readonlyRootFilesystem | When this parameter is true, the container is given read-only access to its root file system | `bool` | `false` | no | -| register\_task\_definition | Registers a new task definition from the supplied family and containerDefinitions | `bool` | `true` | no | -| repositoryCredentials | The private repository authentication credentials to use | `map(string)` | `{}` | no | -| requires\_compatibilities | The launch type required by the task | `list(string)` | `[]` | no | -| resourceRequirements | The type and amount of a resource to assign to a container | `list(string)` | `[]` | no | -| secrets | The secrets to pass to the container | `list(map(string))` | `[]` | no | -| systemControls | A list of namespaced kernel parameters to set in the container | `list(string)` | `[]` | no | -| tags | The metadata that you apply to the task definition to help you categorize and organize them | `map(string)` | `{}` | no | -| task\_role\_arn | The short name or full Amazon Resource Name (ARN) of the IAM role that containers in this task can assume | `string` | `""` | no | -| ulimits | A list of ulimits to set in the container | `list(any)` | `[]` | no | -| user | The user name to use inside the container | `string` | `""` | no | -| volumes | A list of volume definitions in JSON format that containers in your task may use | `list(any)` | `[]` | no | -| volumesFrom | Data volumes to mount from another container | `list(object)` | `[]` | no | -| workingDirectory | The working directory in which to run commands inside the container | `string` | `""` | no | +| [aws](#provider\_aws) | n/a | ## Outputs | Name | Description | |------|-------------| -| arn | The full Amazon Resource Name (ARN) of the task definition | -| container\_definitions | A list of container definitions in JSON format that describe the different containers that make up your task | -| family | The family of your task definition, used as the definition name | -| revision | The revision of the task in a particular family | - - +| [arn](#output\_arn) | The full Amazon Resource Name (ARN) of the task definition | +| [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | The name of the CloudWatch log group created if enable\_cloudwatch is true | +| [container\_definitions](#output\_container\_definitions) | A list of container definitions in JSON format that describe the different containers that make up your task | +| [ecr\_repo\_name](#output\_ecr\_repo\_name) | The name of the ECR repository created if ecr\_create\_repo is true | +| [family](#output\_family) | The family of your task definition, used as the definition name | +| [revision](#output\_revision) | The revision of the task in a particular family | -## Testing +## available tfvar inputs -This module uses [Terratest](https://github.com/gruntwork-io/terratest), a Go library maintained by [Gruntwork](https://gruntwork.io/), to write automated tests for your infrastructure code. To invoke tests, run the following commands: - - $ go test -v ./... +```hcl +# null are required inputs, +# others are optional default values + +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 = "" +``` -## License +## Inputs -[Apache License 2.0](LICENSE) +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [family](#input\_family) | You must specify a family for a task definition, which allows you to track multiple versions of the same task definition | `any` | n/a | yes | +| [cloudwatch\_log\_group\_prefix](#input\_cloudwatch\_log\_group\_prefix) | The prefix for the CloudWatch log group name eg: /project/environment/app | `string` | `""` | no | +| [cloudwatch\_log\_retention\_in\_days](#input\_cloudwatch\_log\_retention\_in\_days) | The number of days to retain the CloudWatch log group | `number` | `30` | no | +| [command](#input\_command) | The command that is passed to the container | `list(string)` | `[]` | no | +| [cpu](#input\_cpu) | The number of cpu units reserved for the container | `number` | `256` | no | +| [disableNetworking](#input\_disableNetworking) | When this parameter is true, networking is disabled within the container | `bool` | `false` | no | +| [dnsSearchDomains](#input\_dnsSearchDomains) | A list of DNS search domains that are presented to the container | `list(string)` | `[]` | no | +| [dnsServers](#input\_dnsServers) | A list of DNS servers that are presented to the container | `list(string)` | `[]` | no | +| [dockerLabels](#input\_dockerLabels) | A key/value map of labels to add to the container | `map(string)` | `{}` | no | +| [dockerSecurityOptions](#input\_dockerSecurityOptions) | A list of strings to provide custom labels for SELinux and AppArmor multi-level security systems | `list(string)` | `[]` | no | +| [ecr\_config](#input\_ecr\_config) | ECR repository configuration |
object({| `null` | no | +| [ecr\_create\_repo](#input\_ecr\_create\_repo) | Enable ECR repository creation | `bool` | `false` | no | +| [enable\_cloudwatch](#input\_enable\_cloudwatch) | Whether to enable CloudWatch logging if false, the value of variable `logConfiguration` will be used | `bool` | `false` | no | +| [entryPoint](#input\_entryPoint) | The entry point that is passed to the container | `list(string)` | `[]` | no | +| [environment](#input\_environment) | The environment variables to pass to a container | `map(string)` | `{}` | no | +| [essential](#input\_essential) | If the essential parameter of a container is marked as true, and that container fails or stops for any reason, all other containers that are part of the task are stopped | `bool` | `true` | no | +| [execution\_role\_arn](#input\_execution\_role\_arn) | The Amazon Resource Name (ARN) of the task execution role that the Amazon ECS container agent and the Docker daemon can assume | `string` | `""` | no | +| [extraHosts](#input\_extraHosts) | A list of hostnames and IP address mappings to append to the /etc/hosts file on the container |
repo_name = optional(string, "")
task_definition_tag = optional(string, "latest")
repo_remove_untagged_days = optional(number, 7)
scan_on_push = optional(bool, false)
repo_max_images = optional(number, 10)
})
list(object({| `[]` | no | +| [healthCheck](#input\_healthCheck) | The health check command and associated configuration parameters for the container | `any` | `{}` | no | +| [hostname](#input\_hostname) | The hostname to use for your container | `string` | `""` | no | +| [image](#input\_image) | The image used to start a container | `string` | `"null"` | no | +| [interactive](#input\_interactive) | When this parameter is true, this allows you to deploy containerized applications that require stdin or a tty to be allocated | `bool` | `false` | no | +| [ipc\_mode](#input\_ipc\_mode) | The IPC resource namespace to use for the containers in the task | `any` | `null` | no | +| [links](#input\_links) | The link parameter allows containers to communicate with each other without the need for port mappings | `list(string)` | `[]` | no | +| [linuxParameters](#input\_linuxParameters) | Linux-specific modifications that are applied to the container, such as Linux KernelCapabilities | `any` | `{}` | no | +| [logConfiguration](#input\_logConfiguration) | The log configuration specification for the container | `any` | `{}` | no | +| [memory](#input\_memory) | The hard limit (in MiB) of memory to present to the container | `number` | `512` | no | +| [memoryReservation](#input\_memoryReservation) | The soft limit (in MiB) of memory to reserve for the container | `number` | `0` | no | +| [mountPoints](#input\_mountPoints) | The mount points for data volumes in your container | `list(any)` | `[]` | no | +| [name](#input\_name) | The name of a container | `string` | `""` | no | +| [network\_mode](#input\_network\_mode) | The Docker networking mode to use for the containers in the task | `string` | `"awsvpc"` | no | +| [pid\_mode](#input\_pid\_mode) | The process namespace to use for the containers in the task | `any` | `null` | no | +| [placement\_constraints](#input\_placement\_constraints) | An array of placement constraint objects to use for the task |
ipAddress = string
hostname = string
}))
list(object({| `[]` | no | +| [portMappings](#input\_portMappings) | The list of port mappings for the container | `list(any)` |
type = string
expression = string
}))
[| no | +| [privileged](#input\_privileged) | When this parameter is true, the container is given elevated privileges on the host container instance (similar to the root user) | `bool` | `false` | no | +| [pseudoTerminal](#input\_pseudoTerminal) | When this parameter is true, a TTY is allocated | `bool` | `false` | no | +| [readonlyRootFilesystem](#input\_readonlyRootFilesystem) | When this parameter is true, the container is given read-only access to its root file system | `bool` | `false` | no | +| [register\_task\_definition](#input\_register\_task\_definition) | Registers a new task definition from the supplied family and containerDefinitions | `bool` | `true` | no | +| [repositoryCredentials](#input\_repositoryCredentials) | The private repository authentication credentials to use | `map(string)` | `{}` | no | +| [requires\_compatibilities](#input\_requires\_compatibilities) | The launch type required by the task (FARGATE, FARGATE\_SPOT, EC2) | `list(string)` |
{
"containerPort": 80
}
]
[| no | +| [resourceRequirements](#input\_resourceRequirements) | The type and amount of a resource to assign to a container | `list(string)` | `[]` | no | +| [runtime\_platform](#input\_runtime\_platform) | The runtime platform |
"FARGATE"
]
object({|
cpu_architecture = string
operating_system_family = string
})
{| no | +| [secrets](#input\_secrets) | The secrets to pass to the container | `list(map(string))` | `[]` | no | +| [systemControls](#input\_systemControls) | A list of namespaced kernel parameters to set in the container | `list(string)` | `[]` | no | +| [tags](#input\_tags) | The metadata that you apply to the task definition to help you categorize and organize them | `map(string)` | `{}` | no | +| [task\_role\_arn](#input\_task\_role\_arn) | The short name or full Amazon Resource Name (ARN) of the IAM role that containers in this task can assume | `string` | `""` | no | +| [track\_latest](#input\_track\_latest) | Whether should track latest ACTIVE task definition on AWS or the one created with the resource stored in state. Default is false. Useful in the event the task definition is modified outside of this resource. | `bool` | `false` | no | +| [ulimits](#input\_ulimits) | A list of ulimits to set in the container | `list(any)` | `[]` | no | +| [user](#input\_user) | The user name to use inside the container | `string` | `""` | no | +| [volumes](#input\_volumes) | A list of volume definitions in JSON format that containers in your task may use | `list(any)` | `[]` | no | +| [volumesFrom](#input\_volumesFrom) | Data volumes to mount from another container |
"cpu_architecture": "X86_64",
"operating_system_family": "LINUX"
}
list(object({| `[]` | no | +| [workingDirectory](#input\_workingDirectory) | The working directory in which to run commands inside the container | `string` | `""` | no | + +--- +README.md created by: `terraform-docs` + \ No newline at end of file diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..f8c3200 --- /dev/null +++ b/Taskfile.yml @@ -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 diff --git a/ecr.tf b/ecr.tf new file mode 100644 index 0000000..8b2091f --- /dev/null +++ b/ecr.tf @@ -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 = <
readOnly = bool
sourceContainer = string
}))