Skip to content

Commit

Permalink
Merge pull request #28052 from meetreks/f-ecs_cluster_update_28043
Browse files Browse the repository at this point in the history
Amazon ECS Service Connect
  • Loading branch information
ewbankkit authored Nov 29, 2022
2 parents 0847f2a + ea909a6 commit cc81ee6
Show file tree
Hide file tree
Showing 11 changed files with 1,071 additions and 485 deletions.
11 changes: 11 additions & 0 deletions .changelog/28052.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```release-note:enhancement
resource/aws_ecs_cluster: Add `service_connect_defaults` argument
```

```release-note:enhancement
resource/aws_ecs_service: Add `service_connect_configuration` argument in support of [ECS Service Connect](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-connect.html)
```

```release-note:enhancement
data-source/aws_ecs_cluster: Add `service_connect_defaults` attribute
```
117 changes: 88 additions & 29 deletions internal/service/ecs/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
Expand All @@ -21,23 +22,18 @@ import (

func ResourceCluster() *schema.Resource {
return &schema.Resource{
Create: resourceClusterCreate,
Read: resourceClusterRead,
Update: resourceClusterUpdate,
Delete: resourceClusterDelete,
Create: resourceClusterCreate,
Read: resourceClusterRead,
UpdateWithoutTimeout: resourceClusterUpdate,
Delete: resourceClusterDelete,

Importer: &schema.ResourceImporter{
State: resourceClusterImport,
},

CustomizeDiff: verify.SetTagsDiff,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateClusterName,
},
"arn": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -81,14 +77,14 @@ func ResourceCluster() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"s3_bucket_name": {
Type: schema.TypeString,
Optional: true,
},
"s3_bucket_encryption_enabled": {
Type: schema.TypeBool,
Optional: true,
},
"s3_bucket_name": {
Type: schema.TypeString,
Optional: true,
},
"s3_key_prefix": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -119,12 +115,10 @@ func ResourceCluster() *schema.Resource {
Optional: true,
ValidateFunc: validation.IntBetween(0, 100000),
},

"capacity_provider": {
Type: schema.TypeString,
Required: true,
},

"weight": {
Type: schema.TypeInt,
Optional: true,
Expand All @@ -133,6 +127,26 @@ func ResourceCluster() *schema.Resource {
},
},
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateClusterName,
},
"service_connect_defaults": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"namespace": {
Type: schema.TypeString,
Required: true,
ValidateFunc: verify.ValidARN,
},
},
},
},
"setting": {
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -186,6 +200,10 @@ func resourceClusterCreate(d *schema.ResourceData, meta interface{}) error {
input.CapacityProviders = flex.ExpandStringSet(v.(*schema.Set))
}

if v, ok := d.GetOk("service_connect_defaults"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
input.ServiceConnectDefaults = expandClusterServiceConnectDefaultsRequest(v.([]interface{})[0].(map[string]interface{}))
}

if v, ok := d.GetOk("setting"); ok {
input.Settings = expandClusterSettings(v.(*schema.Set))
}
Expand Down Expand Up @@ -292,6 +310,14 @@ func resourceClusterRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("error setting default_capacity_provider_strategy: %w", err)
}

if cluster.ServiceConnectDefaults != nil {
if err := d.Set("service_connect_defaults", []interface{}{flattenClusterServiceConnectDefaults(cluster.ServiceConnectDefaults)}); err != nil {
return fmt.Errorf("error setting service_connect_defaults: %w", err)
}
} else {
d.Set("service_connect_defaults", nil)
}

if err := d.Set("setting", flattenClusterSettings(cluster.Settings)); err != nil {
return fmt.Errorf("error setting setting: %w", err)
}
Expand All @@ -316,11 +342,11 @@ func resourceClusterRead(d *schema.ResourceData, meta interface{}) error {
return nil
}

func resourceClusterUpdate(d *schema.ResourceData, meta interface{}) error {
func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).ECSConn

if d.HasChanges("setting", "configuration") {
input := ecs.UpdateClusterInput{
if d.HasChanges("setting", "configuration", "service_connect_defaults") {
input := &ecs.UpdateClusterInput{
Cluster: aws.String(d.Id()),
}

Expand All @@ -332,13 +358,18 @@ func resourceClusterUpdate(d *schema.ResourceData, meta interface{}) error {
input.Configuration = expandClusterConfiguration(v.([]interface{}))
}

_, err := conn.UpdateCluster(&input)
if v, ok := d.GetOk("service_connect_defaults"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
input.ServiceConnectDefaults = expandClusterServiceConnectDefaultsRequest(v.([]interface{})[0].(map[string]interface{}))
}

_, err := conn.UpdateClusterWithContext(ctx, input)

if err != nil {
return fmt.Errorf("error changing ECS cluster (%s): %w", d.Id(), err)
return diag.Errorf("updating ECS Cluster (%s): %s", d.Id(), err)
}

if _, err := waitClusterAvailable(context.Background(), conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for ECS Cluster (%s) to become Available while updating setting and configuration: %w", d.Id(), err)
if _, err := waitClusterAvailable(ctx, conn, d.Id()); err != nil {
return diag.Errorf("waiting for ECS Cluster (%s) update: %s", d.Id(), err)
}
}

Expand All @@ -349,21 +380,21 @@ func resourceClusterUpdate(d *schema.ResourceData, meta interface{}) error {
DefaultCapacityProviderStrategy: expandCapacityProviderStrategy(d.Get("default_capacity_provider_strategy").(*schema.Set)),
}

err := retryClusterCapacityProvidersPut(context.Background(), conn, &input)
err := retryClusterCapacityProvidersPut(ctx, conn, &input)

if err != nil {
return fmt.Errorf("error changing ECS cluster capacity provider settings (%s): %w", d.Id(), err)
return diag.Errorf("updating ECS Cluster (%s) capacity providers: %s", d.Id(), err)
}

if _, err := waitClusterAvailable(context.Background(), conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for ECS Cluster (%s) to become Available while updating capacity_providers, default_capacity_provider_strategy: %w", d.Id(), err)
if _, err := waitClusterAvailable(ctx, conn, d.Id()); err != nil {
return diag.Errorf("waiting for ECS Cluster (%s) capacity providers update: %s", d.Id(), err)
}
}

if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

err := UpdateTags(conn, d.Id(), o, n)
err := UpdateTagsWithContext(ctx, conn, d.Id(), o, n)

// Some partitions (i.e., ISO) may not support tagging, giving error
if verify.ErrorISOUnsupported(conn.PartitionID, err) {
Expand All @@ -372,7 +403,7 @@ func resourceClusterUpdate(d *schema.ResourceData, meta interface{}) error {
}

if err != nil {
return fmt.Errorf("ECS tagging failed updating tags for Cluster (%s): %w", d.Id(), err)
return diag.Errorf("updating ECS Cluster (%s) tags: %s", d.Id(), err)
}
}

Expand Down Expand Up @@ -473,6 +504,34 @@ func expandClusterSettings(configured *schema.Set) []*ecs.ClusterSetting {
return settings
}

func expandClusterServiceConnectDefaultsRequest(tfMap map[string]interface{}) *ecs.ClusterServiceConnectDefaultsRequest {
if tfMap == nil {
return nil
}

apiObject := &ecs.ClusterServiceConnectDefaultsRequest{}

if v, ok := tfMap["namespace"].(string); ok && v != "" {
apiObject.Namespace = aws.String(v)
}

return apiObject
}

func flattenClusterServiceConnectDefaults(apiObject *ecs.ClusterServiceConnectDefaults) map[string]interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{}

if v := apiObject.Namespace; v != nil {
tfMap["namespace"] = aws.StringValue(v)
}

return tfMap
}

func flattenClusterSettings(list []*ecs.ClusterSetting) []map[string]interface{} {
if len(list) == 0 {
return nil
Expand Down
56 changes: 35 additions & 21 deletions internal/service/ecs/cluster_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,50 @@ package ecs

import (
"context"
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
)

func DataSourceCluster() *schema.Resource {
return &schema.Resource{
Read: dataSourceClusterRead,
ReadWithoutTimeout: dataSourceClusterRead,

Schema: map[string]*schema.Schema{
"cluster_name": {
Type: schema.TypeString,
Required: true,
},

"arn": {
Type: schema.TypeString,
Computed: true,
},

"status": {
"cluster_name": {
Type: schema.TypeString,
Computed: true,
Required: true,
},

"pending_tasks_count": {
Type: schema.TypeInt,
Computed: true,
},

"running_tasks_count": {
"registered_container_instances_count": {
Type: schema.TypeInt,
Computed: true,
},

"registered_container_instances_count": {
"running_tasks_count": {
Type: schema.TypeInt,
Computed: true,
},

"service_connect_defaults": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"namespace": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"setting": {
Type: schema.TypeSet,
Computed: true,
Expand All @@ -60,29 +62,41 @@ func DataSourceCluster() *schema.Resource {
},
},
},
"status": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceClusterRead(d *schema.ResourceData, meta interface{}) error {
func dataSourceClusterRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).ECSConn

clusterName := d.Get("cluster_name").(string)
cluster, err := FindClusterByNameOrARN(context.Background(), conn, d.Get("cluster_name").(string))
cluster, err := FindClusterByNameOrARN(ctx, conn, d.Get("cluster_name").(string))

if err != nil {
return fmt.Errorf("error reading ECS Cluster (%s): %w", clusterName, err)
return diag.Errorf("reading ECS Cluster (%s): %s", clusterName, err)
}

d.SetId(aws.StringValue(cluster.ClusterArn))
d.Set("arn", cluster.ClusterArn)
d.Set("status", cluster.Status)
d.Set("pending_tasks_count", cluster.PendingTasksCount)
d.Set("running_tasks_count", cluster.RunningTasksCount)
d.Set("registered_container_instances_count", cluster.RegisteredContainerInstancesCount)
d.Set("status", cluster.Status)

if cluster.ServiceConnectDefaults != nil {
if err := d.Set("service_connect_defaults", []interface{}{flattenClusterServiceConnectDefaults(cluster.ServiceConnectDefaults)}); err != nil {
return diag.Errorf("setting service_connect_defaults: %s", err)
}
} else {
d.Set("service_connect_defaults", nil)
}

if err := d.Set("setting", flattenClusterSettings(cluster.Settings)); err != nil {
return fmt.Errorf("error setting setting: %w", err)
return diag.Errorf("setting setting: %s", err)
}

return nil
Expand Down
1 change: 1 addition & 0 deletions internal/service/ecs/cluster_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestAccECSClusterDataSource_ecsCluster(t *testing.T) {
resource.TestCheckResourceAttr(dataSourceName, "pending_tasks_count", "0"),
resource.TestCheckResourceAttr(dataSourceName, "registered_container_instances_count", "0"),
resource.TestCheckResourceAttr(dataSourceName, "running_tasks_count", "0"),
resource.TestCheckResourceAttrPair(dataSourceName, "service_connect_defaults.#", resourceName, "service_connect_defaults.#"),
resource.TestCheckResourceAttr(dataSourceName, "status", "ACTIVE"),
),
},
Expand Down
Loading

0 comments on commit cc81ee6

Please sign in to comment.