Skip to content

Commit

Permalink
add example with terraform
Browse files Browse the repository at this point in the history
  • Loading branch information
fujiwara committed May 7, 2023
1 parent 7e116c8 commit 854996c
Show file tree
Hide file tree
Showing 13 changed files with 471 additions and 0 deletions.
2 changes: 2 additions & 0 deletions tests/terraform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
terraform.tfstate*
.terraform
35 changes: 35 additions & 0 deletions tests/terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## An example of ecspresso deployment with terraform

This example shows how to deploy an ECS service by ecspresso with terraform.

### Prerequisites

- [Terraform](https://www.terraform.io/) >= v1.0.0
- [ecspresso](https://github.com/kayac/ecspresso) >= v2.0.0

#### Environment variables

- `AWS_REGION` for AWS region. (e.g. `ap-northeast-1`)
- `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`, or `AWS_PROFILE` for AWS credentials.
- `AWS_SDK_LOAD_CONFIG=true` may be required if you use `AWS_PROFILE` and `~/.aws/config`.

### Usage

```console
$ terraform init
$ terraform apply
$ ecspresso deploy
```

After completing the deployment, you can access the service via ALB.

```console
$ curl -s "http://$(terraform output -raw alb_dns_name)/"
```

### Cleanup

```console
$ ecspresso delete --terminate
$ terraform destroy
```
58 changes: 58 additions & 0 deletions tests/terraform/alb.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
resource "aws_lb" "main" {
name = var.project
internal = false
load_balancer_type = "application"
security_groups = [
aws_security_group.alb.id,
aws_security_group.default.id,
]
subnets = [
aws_subnet.public-a.id,
aws_subnet.public-c.id,
aws_subnet.public-d.id,
]
tags = {
Name = var.project
}
}

resource "aws_lb_target_group" "http" {
name = "${var.project}-http"
port = 80
target_type = "ip"
vpc_id = aws_vpc.main.id
protocol = "HTTP"
deregistration_delay = 5

health_check {
path = "/"
port = "traffic-port"
protocol = "HTTP"
healthy_threshold = 2
unhealthy_threshold = 10
timeout = 5
interval = 6
}
tags = {
Name = "${var.project}-http"
}
}

resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.main.arn
port = 80
protocol = "HTTP"

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.http.arn
}

tags = {
Name = "${var.project}-http"
}
}

output "alb_dns_name" {
value = aws_lb.main.dns_name
}
27 changes: 27 additions & 0 deletions tests/terraform/config.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
variable "project" {
type = string
default = "ecspresso"
}

provider "aws" {
region = "ap-northeast-1"
default_tags {
tags = {
"env" = "${var.project}"
}
}
}

terraform {
required_version = ">= 1.4.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.65.0"
}
}
}

data "aws_caller_identity" "current" {
}
48 changes: 48 additions & 0 deletions tests/terraform/ecs-service-def.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
deploymentConfiguration: {
deploymentCircuitBreaker: {
enable: false,
rollback: false,
},
maximumPercent: 200,
minimumHealthyPercent: 100,
},
deploymentController: {
type: 'ECS',
},
desiredCount: 1,
enableECSManagedTags: false,
enableExecuteCommand: true,
healthCheckGracePeriodSeconds: 0,
launchType: 'FARGATE',
loadBalancers: [
{
containerName: 'nginx',
containerPort: 80,
targetGroupArn: '{{or (env `TARGET_GROUP_ARN` ``) (tfstate `aws_lb_target_group.http.arn`) }}',
},
],
networkConfiguration: {
awsvpcConfiguration: {
assignPublicIp: 'ENABLED',
securityGroups: [
'{{or (env `SECURITY_GROUP_ID` ``) (tfstate `aws_security_group.default.id`) }}',
],
subnets: [
'{{or (env `SUBNET_ID_AZ_A` ``) (tfstate `aws_subnet.public-a.id`) }}',
'{{or (env `SUBNET_ID_AZ_C` ``) (tfstate `aws_subnet.public-c.id`) }}',
'{{or (env `SUBNET_ID_AZ_D` ``) (tfstate `aws_subnet.public-d.id`) }}',
],
},
},
platformFamily: 'Linux',
platformVersion: 'LATEST',
propagateTags: 'SERVICE',
schedulingStrategy: 'REPLICA',
tags: [
{
key: 'env',
value: 'ecspresso',
},
],
}
79 changes: 79 additions & 0 deletions tests/terraform/ecs-task-def.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
containerDefinitions: [
{
cpu: 0,
essential: true,
image: 'nginx:latest',
logConfiguration: {
logDriver: 'awslogs',
options: {
'awslogs-create-group': 'true',
'awslogs-group': '{{tfstate `aws_cloudwatch_log_group.main.name`}}',
'awslogs-region': '{{ must_env `AWS_REGION` }}',
'awslogs-stream-prefix': 'nginx',
},
},
name: 'nginx',
portMappings: [
{
appProtocol: '',
containerPort: 80,
hostPort: 80,
protocol: 'tcp',
},
],
},
{
command: [
'tail',
'-f',
'/dev/null',
],
cpu: 0,
essential: true,
image: 'debian:bullseye-slim',
logConfiguration: {
logDriver: 'awslogs',
options: {
'awslogs-create-group': 'true',
'awslogs-group': '{{tfstate `aws_cloudwatch_log_group.main.name`}}',
'awslogs-region': '{{ must_env `AWS_REGION` }}',
'awslogs-stream-prefix': 'bash',
},
},
name: 'bash',
secrets: [
{
name: 'FOO',
valueFrom: '{{tfstate `aws_ssm_parameter.foo.name`}}'
},
{
name: 'BAR',
valueFrom: '{{tfstate `aws_secretsmanager_secret.bar.arn`}}'
},
{
name: 'JSON_KEY',
valueFrom: '{{tfstate `aws_secretsmanager_secret.json.arn`}}:key::'
},
],
},
],
cpu: '256',
ephemeralStorage: {
sizeInGiB: 30,
},
executionRoleArn: '{{tfstate `aws_iam_role.ecs-task.arn`}}',
family: 'ecspresso',
memory: '512',
networkMode: 'awsvpc',
requiresCompatibilities: [
'FARGATE',
],
tags: [
{
key: 'env',
value: 'ecspresso',
},
],
taskRoleArn: '{{tfstate `aws_iam_role.ecs-task.arn`}}',
}
6 changes: 6 additions & 0 deletions tests/terraform/ecs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
resource "aws_ecs_cluster" "main" {
name = var.project
tags = {
Name = var.project
}
}
16 changes: 16 additions & 0 deletions tests/terraform/ecspresso.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
region: '{{ must_env `AWS_REGION` }}',
cluster: 'ecspresso',
service: 'ecspresso',
service_definition: 'ecs-service-def.jsonnet',
task_definition: 'ecs-task-def.jsonnet',
timeout: '10m0s',
plugins: [
{
name: 'tfstate',
config: {
path: 'terraform.tfstate',
},
}
],
}
71 changes: 71 additions & 0 deletions tests/terraform/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
resource "aws_iam_role" "ecs-task" {
name = "${var.project}-ecs-task"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Principal = {
Service = "ecs-tasks.amazonaws.com"
}
Effect = "Allow"
Sid = ""
}
]
})
}

resource "aws_iam_policy" "ecs-task" {
name = var.project
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"logs:CreateLogStream",
"logs:PutLogEvents",
"ssm:GetParameter",
"ssm:GetParameters",
"secretsmanager:GetSecretValue",
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel",
]
Effect = "Allow"
Resource = "*"
}
]
})
}

resource "aws_iam_role_policy_attachment" "ecs-task" {
role = aws_iam_role.ecs-task.name
policy_arn = aws_iam_policy.ecs-task.arn
}

resource "aws_iam_role" "ecs-task-execution" {
name = "${var.project}-ecs-task-execution"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Principal = {
Service = "ecs-tasks.amazonaws.com"
}
Effect = "Allow"
Sid = ""
}
]
})
}

data "aws_iam_policy" "ecs-task-exection" {
arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

resource "aws_iam_role_policy_attachment" "ecs-task-execution" {
role = aws_iam_role.ecs-task-execution.name
policy_arn = data.aws_iam_policy.ecs-task-exection.arn
}
4 changes: 4 additions & 0 deletions tests/terraform/logs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resource "aws_cloudwatch_log_group" "main" {
name = var.project
retention_in_days = 7
}
26 changes: 26 additions & 0 deletions tests/terraform/secrets.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

resource "aws_ssm_parameter" "foo" {
name = "/${var.project}/foo"
type = "SecureString"
value = "FOO"
}

resource "aws_secretsmanager_secret" "bar" {
name = "${var.project}-bar"
}

resource "aws_secretsmanager_secret_version" "bar" {
secret_id = aws_secretsmanager_secret.bar.id
secret_string = "BAR"
}

resource "aws_secretsmanager_secret" "json" {
name = "${var.project}-json"
}

resource "aws_secretsmanager_secret_version" "json" {
secret_id = aws_secretsmanager_secret.json.id
secret_string = jsonencode({
key = "value"
})
}
Loading

0 comments on commit 854996c

Please sign in to comment.