Skip to content

Commit

Permalink
provider/aws: Add support for ECS svc - LB target group
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Aug 18, 2016
1 parent 0007346 commit 3a11311
Show file tree
Hide file tree
Showing 11 changed files with 657 additions and 6 deletions.
8 changes: 7 additions & 1 deletion builtin/providers/aws/resource_aws_ecs_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,13 @@ func resourceAwsEcsService() *schema.Resource {
Schema: map[string]*schema.Schema{
"elb_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Optional: true,
ForceNew: true,
},

"target_group_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},

Expand Down
141 changes: 141 additions & 0 deletions builtin/providers/aws/resource_aws_ecs_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,22 @@ func TestAccAWSEcsService_withEcsClusterName(t *testing.T) {
})
}

func TestAccAWSEcsService_withAlb(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSEcsServiceWithAlb,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsServiceExists("aws_ecs_service.with_alb"),
),
},
},
})
}

func testAccCheckAWSEcsServiceDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ecsconn

Expand Down Expand Up @@ -702,3 +718,128 @@ resource "aws_ecs_service" "jenkins" {
desired_count = 1
}
`

var testAccAWSEcsServiceWithAlb = `
data "aws_availability_zones" "available" {}
resource "aws_vpc" "main" {
cidr_block = "10.10.0.0/16"
}
resource "aws_subnet" "main" {
count = 2
cidr_block = "${cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)}"
availability_zone = "${data.aws_availability_zones.available.names[count.index]}"
vpc_id = "${aws_vpc.main.id}"
}
resource "aws_ecs_cluster" "main" {
name = "terraform_acc_test_ecs_15"
}
resource "aws_ecs_task_definition" "with_lb_changes" {
family = "tf_acc_test_ghost_lbd"
container_definitions = <<DEFINITION
[
{
"cpu": 256,
"essential": true,
"image": "ghost:latest",
"memory": 512,
"name": "ghost",
"portMappings": [
{
"containerPort": 2368,
"hostPort": 8080
}
]
}
]
DEFINITION
}
resource "aws_iam_role" "ecs_service" {
name = "tf_acc_test_15_role"
assume_role_policy = <<EOF
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_role_policy" "ecs_service" {
name = "tf_acc_test_15_policy"
role = "${aws_iam_role.ecs_service.name}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:DeregisterTargets",
"elasticloadbalancing:Describe*",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:RegisterTargets"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_alb_target_group" "test" {
name = "tf-acc-test-ecs-ghost"
port = 80
protocol = "HTTP"
vpc_id = "${aws_vpc.main.id}"
}
resource "aws_alb" "main" {
name = "tf-acc-test-test-alb-ecs"
subnets = ["${aws_subnet.main.*.id}"]
}
resource "aws_alb_listener" "front_end" {
load_balancer_arn = "${aws_alb.main.id}"
port = "80"
protocol = "HTTP"
default_action {
target_group_arn = "${aws_alb_target_group.test.id}"
type = "forward"
}
}
resource "aws_ecs_service" "with_alb" {
name = "tf-acc-test-ecs-ghost"
cluster = "${aws_ecs_cluster.main.id}"
task_definition = "${aws_ecs_task_definition.with_lb_changes.arn}"
desired_count = 1
iam_role = "${aws_iam_role.ecs_service.name}"
load_balancer {
target_group_arn = "${aws_alb_target_group.test.id}"
container_name = "ghost"
container_port = "2368"
}
depends_on = [
"aws_iam_role_policy.ecs_service",
"aws_alb_listener.front_end"
]
}
`
22 changes: 18 additions & 4 deletions builtin/providers/aws/structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,15 @@ func expandEcsLoadBalancers(configured []interface{}) []*ecs.LoadBalancer {
data := lRaw.(map[string]interface{})

l := &ecs.LoadBalancer{
ContainerName: aws.String(data["container_name"].(string)),
ContainerPort: aws.Int64(int64(data["container_port"].(int))),
LoadBalancerName: aws.String(data["elb_name"].(string)),
ContainerName: aws.String(data["container_name"].(string)),
ContainerPort: aws.Int64(int64(data["container_port"].(int))),
}

if v, ok := data["elb_name"]; ok && v.(string) != "" {
l.LoadBalancerName = aws.String(v.(string))
}
if v, ok := data["target_group_arn"]; ok && v.(string) != "" {
l.TargetGroupArn = aws.String(v.(string))
}

loadBalancers = append(loadBalancers, l)
Expand Down Expand Up @@ -553,10 +559,18 @@ func flattenEcsLoadBalancers(list []*ecs.LoadBalancer) []map[string]interface{}
result := make([]map[string]interface{}, 0, len(list))
for _, loadBalancer := range list {
l := map[string]interface{}{
"elb_name": *loadBalancer.LoadBalancerName,
"container_name": *loadBalancer.ContainerName,
"container_port": *loadBalancer.ContainerPort,
}

if loadBalancer.LoadBalancerName != nil {
l["elb_name"] = *loadBalancer.LoadBalancerName
}

if loadBalancer.TargetGroupArn != nil {
l["target_group_arn"] = *loadBalancer.TargetGroupArn
}

result = append(result, l)
}
return result
Expand Down
33 changes: 33 additions & 0 deletions examples/aws-ecs-alb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# ECS with ALB example

This example shows how to launch an ECS service fronted with Application Load Balancer.

The example uses latest CoreOS Stable AMIs.

To run, configure your AWS provider as described in https://www.terraform.io/docs/providers/aws/index.html

## Get up and running

Planning phase

```
terraform plan \
-var admin_cidr_ingress='"{your_ip_address}/32"' \
-var key_name={your_key_name}
```

Apply phase

```
terraform apply \
-var admin_cidr_ingress='"{your_ip_address}/32"' \
-var key_name={your_key_name}
```

Once the stack is created, wait for a few minutes and test the stack by launching a browser with the ALB url.

## Destroy :boom:

```
terraform destroy
```
43 changes: 43 additions & 0 deletions examples/aws-ecs-alb/cloud-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#cloud-config
coreos:
units:
- name: update-engine.service
command: stop
- name: amazon-ecs-agent.service
command: start
runtime: true
content: |
[Unit]
Description=AWS ECS Agent
Documentation=https://docs.aws.amazon.com/AmazonECS/latest/developerguide/
Requires=docker.socket
After=docker.socket
[Service]
Environment=ECS_CLUSTER=${ecs_cluster_name}
Environment=ECS_LOGLEVEL=${ecs_log_level}
Environment=ECS_VERSION=${ecs_agent_version}
Restart=on-failure
RestartSec=30
RestartPreventExitStatus=5
SyslogIdentifier=ecs-agent
ExecStartPre=-/bin/mkdir -p /var/log/ecs /var/ecs-data /etc/ecs
ExecStartPre=-/usr/bin/docker kill ecs-agent
ExecStartPre=-/usr/bin/docker rm ecs-agent
ExecStartPre=/usr/bin/docker pull amazon/amazon-ecs-agent:$${ECS_VERSION}
ExecStart=/usr/bin/docker run --name ecs-agent \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--volume=/var/log/ecs:/log \
--volume=/var/ecs-data:/data \
--volume=/sys/fs/cgroup:/sys/fs/cgroup:ro \
--volume=/run/docker/execdriver/native:/var/lib/docker/execdriver/native:ro \
--publish=127.0.0.1:51678:51678 \
--env=ECS_LOGFILE=/log/ecs-agent.log \
--env=ECS_LOGLEVEL=$${ECS_LOGLEVEL} \
--env=ECS_DATADIR=/data \
--env=ECS_CLUSTER=$${ECS_CLUSTER} \
--env=ECS_AVAILABLE_LOGGING_DRIVERS='["awslogs"]' \
--log-driver=awslogs \
--log-opt awslogs-region=${aws_region} \
--log-opt awslogs-group=${ecs_log_group_name} \
amazon/amazon-ecs-agent:$${ECS_VERSION}
31 changes: 31 additions & 0 deletions examples/aws-ecs-alb/instance-profile-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ecsInstanceRole",
"Effect": "Allow",
"Action": [
"ecs:DeregisterContainerInstance",
"ecs:DiscoverPollEndpoint",
"ecs:Poll",
"ecs:RegisterContainerInstance",
"ecs:Submit*"
],
"Resource": [
"*"
]
},
{
"Sid": "allowLoggingToCloudWatch",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"${app_log_group_arn}",
"${ecs_log_group_arn}"
]
}
]
}
Loading

0 comments on commit 3a11311

Please sign in to comment.