From 60ac73eed9eef06f42306e643ad4e4bb54432feb Mon Sep 17 00:00:00 2001 From: Matthew Riley Date: Wed, 21 Feb 2018 12:46:20 -0800 Subject: [PATCH 1/2] Fix inconsistent spacing between fields --- aws/resource_aws_ecs_service.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aws/resource_aws_ecs_service.go b/aws/resource_aws_ecs_service.go index 22f8eb94550..8cf1d1ec55d 100644 --- a/aws/resource_aws_ecs_service.go +++ b/aws/resource_aws_ecs_service.go @@ -115,6 +115,7 @@ func resourceAwsEcsService() *schema.Resource { }, Set: resourceAwsEcsLoadBalancerHash, }, + "network_configuration": { Type: schema.TypeList, Optional: true, @@ -136,6 +137,7 @@ func resourceAwsEcsService() *schema.Resource { }, }, }, + "placement_strategy": { Type: schema.TypeSet, Optional: true, From 47d33edbb49dfb815967b9eb3d190f296f487b67 Mon Sep 17 00:00:00 2001 From: Matthew Riley Date: Wed, 21 Feb 2018 14:53:51 -0800 Subject: [PATCH 2/2] Add wait_for_steady_state attribute to ECS service If true, creates and updates will only complete once the service has reached a steady state. --- aws/resource_aws_ecs_service.go | 64 ++++++++++++++++++++++++ website/docs/r/ecs_service.html.markdown | 1 + 2 files changed, 65 insertions(+) diff --git a/aws/resource_aws_ecs_service.go b/aws/resource_aws_ecs_service.go index 8cf1d1ec55d..bb79b8d60d4 100644 --- a/aws/resource_aws_ecs_service.go +++ b/aws/resource_aws_ecs_service.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "regexp" + "strconv" "strings" "time" @@ -199,6 +200,12 @@ func resourceAwsEcsService() *schema.Resource { }, }, }, + + "wait_for_steady_state": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -525,6 +532,22 @@ func resourceAwsEcsServiceUpdate(d *schema.ResourceData, meta interface{}) error return err } + if d.Get("wait_for_steady_state").(bool) { + log.Println("[INFO] Waiting for service to reach a steady state") + + steadyStateConf := &resource.StateChangeConf{ + Pending: []string{"false"}, + Target: []string{"true"}, + Refresh: resourceAwsEcsServiceIsSteadyStateFunc(d, meta), + Timeout: 10 * time.Minute, + MinTimeout: 1 * time.Second, + } + + if _, err := steadyStateConf.WaitForState(); err != nil { + return err + } + } + return resourceAwsEcsServiceRead(d, meta) } @@ -670,3 +693,44 @@ func validateAwsEcsServiceHealthCheckGracePeriodSeconds(v interface{}, k string) } return } + +// Returns a StateRefreshFunc for a given service. That function will return "true" if the service is in a +// steady state, "false" if the service is running but not in a steady state, and an error otherwise. +func resourceAwsEcsServiceIsSteadyStateFunc(d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + conn := meta.(*AWSClient).ecsconn + in := &ecs.DescribeServicesInput{ + Services: []*string{aws.String(d.Id())}, + Cluster: aws.String(d.Get("cluster").(string)), + } + + out, err := conn.DescribeServices(in) + if err != nil { + return nil, "", err + } + + if len(out.Services) < 1 { + return nil, "", fmt.Errorf( + "Service %v disappeared while waiting for it to reach a steady state", + d.Id()) + } + + service := out.Services[0] + + // A service is in a steady state if: + // 1. It is not INACTIVE or DRAINING + // 2. There is only one deployment, which will be PRIMARY + // 3. The count of running tasks matches the desired count + // ref: https://github.com/boto/botocore/blob/3ac0dd53/botocore/data/ecs/2014-11-13/waiters-2.json#L42-L72 + if *service.Status == "INACTIVE" || *service.Status == "DRAINING" { + return nil, "", fmt.Errorf( + "Service %v can't reach steady state because its status is %v", + d.Id(), *service.Status) + } + + isSteadyState := len(service.Deployments) == 1 && + *service.RunningCount == *service.DesiredCount + + return service, strconv.FormatBool(isSteadyState), nil + } +} diff --git a/website/docs/r/ecs_service.html.markdown b/website/docs/r/ecs_service.html.markdown index 3a4cbe07dc4..fc9ffe9d991 100644 --- a/website/docs/r/ecs_service.html.markdown +++ b/website/docs/r/ecs_service.html.markdown @@ -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. +* `wait_for_steady_state` - (Optional) If `true`, Terraform will wait for the service to reach a steady state (like [`aws ecs wait services-stable`](https://docs.aws.amazon.com/cli/latest/reference/ecs/wait/services-stable.html)) before continuing. Default `false`. -> **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).