Skip to content

Commit

Permalink
Merge pull request #3906 from atsushi-ishibashi/ecs_service_registry
Browse files Browse the repository at this point in the history
resource/ecs_service: Support ServiceRegistries
  • Loading branch information
bflad authored Apr 12, 2018
2 parents 9edd15f + 3f41ea6 commit 4ff21b9
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 1 deletion.
60 changes: 60 additions & 0 deletions aws/resource_aws_ecs_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)

var taskDefinitionRE = regexp.MustCompile("^([a-zA-Z0-9_-]+):([0-9]+)$")
Expand Down Expand Up @@ -205,6 +206,27 @@ func resourceAwsEcsService() *schema.Resource {
},
},
},

"service_registries": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"port": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(0, 65536),
},
"registry_arn": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateArn,
},
},
},
},
},
}
}
Expand Down Expand Up @@ -306,6 +328,23 @@ func resourceAwsEcsServiceCreate(d *schema.ResourceData, meta interface{}) error
input.PlacementConstraints = pc
}

serviceRegistries := d.Get("service_registries").(*schema.Set).List()
if len(serviceRegistries) > 0 {
srs := make([]*ecs.ServiceRegistry, 0, len(serviceRegistries))
for _, v := range serviceRegistries {
raw := v.(map[string]interface{})
sr := &ecs.ServiceRegistry{
RegistryArn: aws.String(raw["registry_arn"].(string)),
}
if port, ok := raw["port"].(int); ok && port != 0 {
sr.Port = aws.Int64(int64(port))
}

srs = append(srs, sr)
}
input.ServiceRegistries = srs
}

log.Printf("[DEBUG] Creating ECS service: %s", input)

// Retry due to AWS IAM & ECS eventual consistency
Expand Down Expand Up @@ -446,6 +485,10 @@ func resourceAwsEcsServiceRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("[ERR] Error setting network_configuration for (%s): %s", d.Id(), err)
}

if err := d.Set("service_registries", flattenServiceRegistries(service.ServiceRegistries)); err != nil {
return fmt.Errorf("[ERR] Error setting service_registries for (%s): %s", d.Id(), err)
}

return nil
}

Expand Down Expand Up @@ -522,6 +565,23 @@ func flattenPlacementStrategy(pss []*ecs.PlacementStrategy) []map[string]interfa
return results
}

func flattenServiceRegistries(srs []*ecs.ServiceRegistry) []map[string]interface{} {
if len(srs) == 0 {
return nil
}
results := make([]map[string]interface{}, 0)
for _, sr := range srs {
c := map[string]interface{}{
"registry_arn": aws.StringValue(sr.RegistryArn),
}
if sr.Port != nil {
c["port"] = int(aws.Int64Value(sr.Port))
}
results = append(results, c)
}
return results
}

func resourceAwsEcsServiceUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ecsconn

Expand Down
107 changes: 107 additions & 0 deletions aws/resource_aws_ecs_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,15 @@ func TestAccAWSEcsService_withARN(t *testing.T) {
Config: testAccAWSEcsService(clusterName, tdName, svcName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo", &service),
resource.TestCheckResourceAttr("aws_ecs_service.mongo", "service_registries.#", "0"),
),
},

{
Config: testAccAWSEcsServiceModified(clusterName, tdName, svcName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsServiceExists("aws_ecs_service.mongo", &service),
resource.TestCheckResourceAttr("aws_ecs_service.mongo", "service_registries.#", "0"),
),
},
},
Expand Down Expand Up @@ -611,6 +613,30 @@ func TestAccAWSEcsService_withLaunchTypeEC2AndNetworkConfiguration(t *testing.T)
})
}

func TestAccAWSEcsService_withServiceRegistries(t *testing.T) {
var service ecs.Service
rString := acctest.RandString(8)

clusterName := fmt.Sprintf("tf-acc-cluster-svc-w-ups-%s", rString)
tdName := fmt.Sprintf("tf-acc-td-svc-w-ups-%s", rString)
svcName := fmt.Sprintf("tf-acc-svc-w-ups-%s", rString)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEcsServiceDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEcsService_withServiceRegistries(rString, clusterName, tdName, svcName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSEcsServiceExists("aws_ecs_service.test", &service),
resource.TestCheckResourceAttr("aws_ecs_service.test", "service_registries.#", "1"),
),
},
},
})
}

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

Expand Down Expand Up @@ -1688,3 +1714,84 @@ resource "aws_ecs_service" "main" {
}
`, sg1Name, sg2Name, clusterName, tdName, svcName, securityGroups)
}

func testAccAWSEcsService_withServiceRegistries(rName, clusterName, tdName, svcName string) string {
return fmt.Sprintf(`
data "aws_availability_zones" "test" {}
resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "test" {
count = 2
cidr_block = "${cidrsubnet(aws_vpc.test.cidr_block, 8, count.index)}"
availability_zone = "${data.aws_availability_zones.test.names[count.index]}"
vpc_id = "${aws_vpc.test.id}"
}
resource "aws_security_group" "test" {
name = "tf-acc-sg-%s"
vpc_id = "${aws_vpc.test.id}"
ingress {
protocol = "-1"
from_port = 0
to_port = 0
cidr_blocks = ["${aws_vpc.test.cidr_block}"]
}
}
resource "aws_service_discovery_private_dns_namespace" "test" {
name = "tf-acc-sd-%s.terraform.local"
description = "test"
vpc = "${aws_vpc.test.id}"
}
resource "aws_service_discovery_service" "test" {
name = "tf-acc-sd-%s"
dns_config {
namespace_id = "${aws_service_discovery_private_dns_namespace.test.id}"
dns_records {
ttl = 5
type = "SRV"
}
}
}
resource "aws_ecs_cluster" "test" {
name = "%s"
}
resource "aws_ecs_task_definition" "test" {
family = "%s"
network_mode = "awsvpc"
container_definitions = <<DEFINITION
[
{
"cpu": 128,
"essential": true,
"image": "mongo:latest",
"memory": 128,
"name": "mongodb"
}
]
DEFINITION
}
resource "aws_ecs_service" "test" {
name = "%s"
cluster = "${aws_ecs_cluster.test.id}"
task_definition = "${aws_ecs_task_definition.test.arn}"
desired_count = 1
service_registries {
port = 34567
registry_arn = "${aws_service_discovery_service.test.arn}"
}
network_configuration {
security_groups = ["${aws_security_group.test.id}"]
subnets = ["${aws_subnet.test.*.id}"]
}
}
`, rName, rName, rName, clusterName, tdName, svcName)
}
10 changes: 9 additions & 1 deletion website/docs/r/ecs_service.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ into consideration during task placement. The maximum number of
* `placement_constraints` - (Optional) rules that are taken into consideration during task placement. Maximum number of
`placement_constraints` is `10`. Defined below.
* `network_configuration` - (Optional) The network configuration for the service. This parameter is required for task definitions that use the awsvpc network mode to receive their own Elastic Network Interface, and it is not supported for other network modes.
* `service_registries` - (Optional) The service discovery registries for the service. The maximum number of `service_registries` blocks is `1`.

-> **Note:** As a result of an AWS limitation, a single `load_balancer` can be attached to the ECS service at most. See [related docs](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html#load-balancing-concepts).

Expand Down Expand Up @@ -106,6 +107,13 @@ Guide](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-query

For more information, see [Task Networking](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-networking.html)

## service_registries

`service_registries` support the following:

* `registry_arn` - (Required) The ARN of the Service Registry. The currently supported service registry is Amazon Route 53 Auto Naming Service(`aws_service_discovery_service`). For more information, see [Service](https://docs.aws.amazon.com/Route53/latest/APIReference/API_autonaming_Service.html)
* `port` - (Optional) The port value used if your Service Discovery service specified an SRV record.

## Attributes Reference

The following attributes are exported:
Expand All @@ -122,4 +130,4 @@ ECS services can be imported using the `name` together with ecs cluster `name`,

```
$ terraform import aws_ecs_service.imported cluster-name/service-name
```
```

0 comments on commit 4ff21b9

Please sign in to comment.