Skip to content

Commit f2a934a

Browse files
committed
Add initial module configuration
1 parent 9d4e4e0 commit f2a934a

File tree

10 files changed

+506
-0
lines changed

10 files changed

+506
-0
lines changed

.pre-commit-config.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v2.5.0
4+
hooks:
5+
- id: check-added-large-files
6+
args: ['--maxkb=500']
7+
- id: check-executables-have-shebangs
8+
- id: pretty-format-json
9+
args: ['--autofix', '--no-sort-keys', '--indent=2']
10+
- id: check-byte-order-marker
11+
- id: check-case-conflict
12+
- id: check-executables-have-shebangs
13+
- id: check-merge-conflict
14+
- id: check-symlinks
15+
- id: detect-private-key
16+
- id: check-merge-conflict
17+
- id: detect-aws-credentials
18+
args: ['--allow-missing-credentials']
19+
- id: trailing-whitespace
20+
- repo: git://github.com/antonbabenko/pre-commit-terraform
21+
rev: v1.27.0
22+
hooks:
23+
- id: terraform_fmt
24+
- id: terraform_docs
25+
- id: terraform_tflint

LICENSE

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Licensed under the Apache License, Version 2.0 (the "License");
2+
you may not use this file except in compliance with the License.
3+
You may obtain a copy of the License at
4+
5+
http://www.apache.org/licenses/LICENSE-2.0
6+
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.

Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
ifneq (,)
2+
.error This Makefile requires GNU Make.
3+
endif
4+
5+
.PHONY: hooks validate
6+
7+
help:
8+
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
9+
10+
hooks: ## Commit hooks setup
11+
@pre-commit install
12+
@pre-commit gc
13+
@pre-commit autoupdate
14+
15+
validate: ## Validate files with pre-commit hooks
16+
@pre-commit run --all-files

README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,87 @@
11
# terraform-aws-ecs-fargate-task-definition
22
Terraform module to create AWS ECS Fargate Task Definition
3+
4+
## Terraform versions
5+
6+
Terraform 0.12. Pin module version to `~> v1.0`. Submit pull-requests to `master` branch.
7+
8+
## Usage
9+
10+
```hcl
11+
module "ecs-task-definition" {
12+
...
13+
}
14+
```
15+
16+
## Assumptions
17+
18+
Module is to be used with Terraform > 0.12.
19+
20+
## Examples
21+
22+
* [Example]()
23+
24+
## Authors
25+
26+
Module managed by [Marcin Cuber](https://github.com/marcincuber) [LinkedIn](https://www.linkedin.com/in/marcincuber/).
27+
28+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
29+
## Inputs
30+
31+
| Name | Description | Type | Default | Required |
32+
|------|-------------|:----:|:-----:|:-----:|
33+
| cloudwatch\_log\_group\_name | CloudWatch log group name required to enabled logDriver in container definitions for ecs task. | map(string) | n/a | yes |
34+
| container\_name | Optional name for the container to be used instead of name\_prefix. | string | `""` | no |
35+
| name\_prefix | A prefix used for naming resources. | string | n/a | yes |
36+
| placement\_constraints | \(Optional\) A set of placement constraints rules that are taken into consideration during task placement. Maximum number of placement\_constraints is 10. This is a list of maps, where each map should contain "type" and "expression" | list | `[]` | no |
37+
| proxy\_configuration | \(Optional\) The proxy configuration details for the App Mesh proxy. This is a list of maps, where each map should contain "container\_name", "properties" and "type" | list | `[]` | no |
38+
| repository\_credentials | name or ARN of a secrets manager secret \(arn:aws:secretsmanager:region:aws\_account\_id:secret:secret\_name\) | string | `""` | no |
39+
| repository\_credentials\_kms\_key | key id, key ARN, alias name or alias ARN of the key that encrypted the repository credentials | string | `"alias/aws/secretsmanager"` | no |
40+
| tags | A map of tags \(key-value pairs\) passed to resources. | map(string) | `{}` | no |
41+
| task\_container\_command | The command that is passed to the container. | list(string) | `[]` | no |
42+
| task\_container\_environment | The environment variables to pass to a container. | map(string) | `{}` | no |
43+
| task\_container\_image | The image used to start a container. | string | n/a | yes |
44+
| task\_container\_port | The port number on the container that is bound to the user-specified or automatically assigned host port | number | n/a | yes |
45+
| task\_definition\_cpu | Amount of CPU to reserve for the task. | number | `"256"` | no |
46+
| task\_definition\_memory | The soft limit \(in MiB\) of memory to reserve for the container. | number | `"512"` | no |
47+
| task\_host\_port | The port number on the container instance to reserve for your container. | number | `"0"` | no |
48+
| volume | \(Optional\) A set of volume blocks that containers in your task may use. This is a list of maps, where each map should contain "name", "host\_path" and "docker\_volume\_configuration". Full set of options can be found at https://www.terraform.io/docs/providers/aws/r/ecs\_task\_definition.html | list | `[]` | no |
49+
50+
## Outputs
51+
52+
| Name | Description |
53+
|------|-------------|
54+
| container\_port | Port on which the container is listening. |
55+
| execution\_role\_arn | The Amazon Resource Name \(ARN\) of execution role. |
56+
| execution\_role\_create\_date | The creation date of the IAM role. |
57+
| execution\_role\_id | The ID of the execution role. |
58+
| execution\_role\_name | The name of the execution service role. |
59+
| execution\_role\_unique\_id | The stable and unique string identifying the role. |
60+
| task\_definition\_arn | Full ARN of the Task Definition \(including both family and revision\). |
61+
| task\_definition\_family | The family of the Task Definition. |
62+
| task\_definition\_td\_revision | The revision of the task in a particular family. |
63+
| task\_role\_arn | The Amazon Resource Name \(ARN\) specifying the ECS service role. |
64+
| task\_role\_create\_date | The creation date of the IAM role. |
65+
| task\_role\_id | The ID of the role. |
66+
| task\_role\_name | The name of the Fargate task service role. |
67+
| task\_role\_unique\_id | The stable and unique string identifying the role. |
68+
69+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
70+
71+
## License
72+
73+
See LICENSE for full details.
74+
75+
## Pre-commit hooks
76+
77+
### Install dependencies
78+
79+
* [`pre-commit`](https://pre-commit.com/#install)
80+
* [`terraform-docs`](https://github.com/segmentio/terraform-docs) required for `terraform_docs` hooks.
81+
* [`TFLint`](https://github.com/terraform-linters/tflint) required for `terraform_tflint` hook.
82+
83+
#### MacOS
84+
85+
```bash
86+
brew install pre-commit terraform-docs tflint
87+
```

data.tf

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
data "aws_region" "current" {}
2+
3+
data "aws_iam_policy_document" "assume_role_policy" {
4+
statement {
5+
effect = "Allow"
6+
actions = ["sts:AssumeRole"]
7+
8+
principals {
9+
type = "Service"
10+
identifiers = ["ecs-tasks.amazonaws.com"]
11+
}
12+
}
13+
}
14+
15+
data "aws_iam_policy_document" "task_permissions" {
16+
statement {
17+
effect = "Allow"
18+
19+
resources = ["*"]
20+
21+
actions = [
22+
"logs:CreateLogStream",
23+
"logs:PutLogEvents"
24+
]
25+
}
26+
}
27+
28+
data "aws_kms_key" "secretsmanager_key" {
29+
key_id = var.repository_credentials_kms_key
30+
}
31+
32+
data "aws_iam_policy_document" "read_repository_credentials" {
33+
statement {
34+
effect = "Allow"
35+
36+
resources = [
37+
var.repository_credentials,
38+
data.aws_kms_key.secretsmanager_key.arn,
39+
]
40+
41+
actions = [
42+
"secretsmanager:GetSecretValue",
43+
"kms:Decrypt",
44+
]
45+
}
46+
}

examples/core/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
## Example deployment flow
3+
4+
```bash
5+
terraform init
6+
terraform validate
7+
terraform plan
8+
terraform apply --auto-approve
9+
```

examples/core/main.tf

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
provider "aws" {
2+
region = "eu-west-1"
3+
}
4+
5+
#####
6+
# VPC and subnets
7+
#####
8+
module "vpc" {
9+
source = "terraform-aws-modules/vpc/aws"
10+
version = "~> 2.21"
11+
12+
name = "simple-vpc"
13+
14+
cidr = "10.0.0.0/16"
15+
16+
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
17+
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
18+
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
19+
20+
enable_nat_gateway = false
21+
}

main.tf

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#####
2+
# Execution IAM Role
3+
#####
4+
resource "aws_iam_role" "execution" {
5+
name = "${var.name_prefix}-execution-role"
6+
assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
7+
8+
tags = var.tags
9+
}
10+
11+
resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy_attach" {
12+
role = aws_iam_role.execution.name
13+
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
14+
}
15+
16+
resource "aws_iam_role_policy" "read_repository_credentials" {
17+
count = length(var.repository_credentials) != 0 ? 1 : 0
18+
19+
name = "${var.name_prefix}-read-repository-credentials"
20+
role = aws_iam_role.execution.id
21+
policy = data.aws_iam_policy_document.read_repository_credentials.json
22+
}
23+
24+
#####
25+
# IAM - Task role, basic. Append policies to this role for S3, DynamoDB etc.
26+
#####
27+
resource "aws_iam_role" "task" {
28+
name = "${var.name_prefix}-task-role"
29+
assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
30+
31+
tags = var.tags
32+
}
33+
34+
resource "aws_iam_role_policy" "log_agent" {
35+
name = "${var.name_prefix}-log-permissions"
36+
role = aws_iam_role.task.id
37+
policy = data.aws_iam_policy_document.task_permissions.json
38+
}
39+
40+
#####
41+
# ECS task definition
42+
#####
43+
44+
locals {
45+
task_environment = [
46+
for k, v in var.task_container_environment : {
47+
name = k
48+
value = v
49+
}
50+
]
51+
}
52+
53+
resource "aws_ecs_task_definition" "task" {
54+
family = var.name_prefix
55+
execution_role_arn = aws_iam_role.execution.arn
56+
network_mode = "awsvpc"
57+
requires_compatibilities = ["FARGATE"]
58+
cpu = var.task_definition_cpu
59+
memory = var.task_definition_memory
60+
task_role_arn = aws_iam_role.task.arn
61+
62+
container_definitions = <<EOF
63+
[{
64+
"name": "${var.container_name != "" ? var.container_name : var.name_prefix}",
65+
"image": "${var.task_container_image}",
66+
%{if var.repository_credentials != ""~}
67+
"repositoryCredentials": {
68+
"credentialsParameter": "${var.repository_credentials}"
69+
},
70+
%{~endif}
71+
"essential": true,
72+
"portMappings": [
73+
{
74+
"containerPort": ${var.task_container_port},
75+
%{if var.task_host_port != 0~}
76+
"hostPort": ${var.task_host_port},
77+
%{~endif}
78+
"protocol":"tcp"
79+
}
80+
],
81+
%{if var.cloudwatch_log_group_name != ""~}
82+
"logConfiguration": {
83+
"logDriver": "awslogs",
84+
"options": {
85+
"awslogs-group": "${var.cloudwatch_log_group_name}",
86+
"awslogs-region": "${data.aws_region.current.name}",
87+
"awslogs-stream-prefix": "container"
88+
}
89+
},
90+
%{~endif}
91+
"command": ${jsonencode(var.task_container_command)},
92+
"environment": ${jsonencode(local.task_environment)}
93+
}]
94+
EOF
95+
96+
dynamic "placement_constraints" {
97+
for_each = var.placement_constraints
98+
content {
99+
expression = lookup(placement_constraints.value, "expression", null)
100+
type = placement_constraints.value.type
101+
}
102+
}
103+
104+
dynamic "proxy_configuration" {
105+
for_each = var.proxy_configuration
106+
content {
107+
container_name = proxy_configuration.value.container_name
108+
properties = lookup(proxy_configuration.value, "properties", null)
109+
type = lookup(proxy_configuration.value, "type", null)
110+
}
111+
}
112+
113+
dynamic "volume" {
114+
for_each = var.volume
115+
content {
116+
name = volume.value.name
117+
host_path = lookup(volume.value, "host_path", null)
118+
docker_volume_configuration = lookup(volume.value, "docker_volume_configuration", null)
119+
}
120+
}
121+
122+
123+
tags = merge(
124+
var.tags,
125+
{
126+
Name = var.container_name != "" ? var.container_name : var.name_prefix
127+
},
128+
)
129+
}
130+

0 commit comments

Comments
 (0)