Skip to content

Commit b489493

Browse files
authored
Merge pull request #44289 from djglaser/f-hook-details
Add hook_details as an attribute of lifecycle_hook
2 parents d9bcf27 + cd8f89e commit b489493

File tree

4 files changed

+57
-8
lines changed

4 files changed

+57
-8
lines changed

.changelog/44289.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
resource/aws_ecs_service: Add `deployment_configuration.lifecycle_hook.hook_details` argument
3+
```

internal/service/ecs/service.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package ecs
55

66
import (
77
"context"
8+
"encoding/json"
89
"errors"
910
"fmt"
1011
"log"
@@ -19,6 +20,7 @@ import (
1920
"github.com/aws/aws-sdk-go-v2/aws"
2021
"github.com/aws/aws-sdk-go-v2/aws/arn"
2122
"github.com/aws/aws-sdk-go-v2/service/ecs"
23+
"github.com/aws/aws-sdk-go-v2/service/ecs/document"
2224
awstypes "github.com/aws/aws-sdk-go-v2/service/ecs/types"
2325
"github.com/hashicorp/aws-sdk-go-base/v2/tfawserr"
2426
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -34,6 +36,7 @@ import (
3436
"github.com/hashicorp/terraform-provider-aws/internal/flex"
3537
"github.com/hashicorp/terraform-provider-aws/internal/sdkv2"
3638
"github.com/hashicorp/terraform-provider-aws/internal/sdkv2/types/nullable"
39+
"github.com/hashicorp/terraform-provider-aws/internal/smithy"
3740
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
3841
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
3942
"github.com/hashicorp/terraform-provider-aws/internal/verify"
@@ -649,6 +652,12 @@ func resourceService() *schema.Resource {
649652
Required: true,
650653
ValidateFunc: verify.ValidARN,
651654
},
655+
"hook_details": {
656+
Type: schema.TypeString,
657+
Optional: true,
658+
DiffSuppressFunc: verify.SuppressEquivalentJSONDiffs,
659+
ValidateFunc: verify.ValidStringIsJSONOrYAML,
660+
},
652661
},
653662
},
654663
},
@@ -1799,7 +1808,6 @@ func resourceServiceUpdate(ctx context.Context, d *schema.ResourceData, meta any
17991808
return false, err
18001809
},
18011810
)
1802-
18031811
if err != nil {
18041812
return sdkdiag.AppendErrorf(diags, "updating ECS Service (%s): %s", d.Id(), err)
18051813
}
@@ -1847,7 +1855,6 @@ func resourceServiceDelete(ctx context.Context, d *schema.ResourceData, meta any
18471855
}
18481856

18491857
_, err := conn.UpdateService(ctx, input)
1850-
18511858
if err != nil {
18521859
return sdkdiag.AppendErrorf(diags, "draining ECS Service (%s): %s", d.Id(), err)
18531860
}
@@ -1874,7 +1881,6 @@ func resourceServiceDelete(ctx context.Context, d *schema.ResourceData, meta any
18741881
return false, err
18751882
},
18761883
)
1877-
18781884
if err != nil {
18791885
return sdkdiag.AppendErrorf(diags, "deleting ECS Service (%s): %s", d.Id(), err)
18801886
}
@@ -1948,7 +1954,6 @@ func retryServiceCreate(ctx context.Context, conn *ecs.Client, input *ecs.Create
19481954
return false, err
19491955
},
19501956
)
1951-
19521957
if err != nil {
19531958
return nil, err
19541959
}
@@ -1958,7 +1963,6 @@ func retryServiceCreate(ctx context.Context, conn *ecs.Client, input *ecs.Create
19581963

19591964
func findService(ctx context.Context, conn *ecs.Client, input *ecs.DescribeServicesInput) (*awstypes.Service, error) {
19601965
output, err := findServices(ctx, conn, input)
1961-
19621966
if err != nil {
19631967
return nil, err
19641968
}
@@ -2121,7 +2125,6 @@ func statusServiceWaitForStable(ctx context.Context, conn *ecs.Client, serviceNa
21212125

21222126
return func() (any, string, error) {
21232127
outputRaw, serviceStatus, err := statusService(ctx, conn, serviceName, clusterNameOrARN)()
2124-
21252128
if err != nil {
21262129
return nil, "", err
21272130
}
@@ -2597,6 +2600,12 @@ func flattenLifecycleHooks(apiObjects []awstypes.DeploymentLifecycleHook) []any
25972600
tfMap["lifecycle_stages"] = stages
25982601
}
25992602

2603+
if v := apiObject.HookDetails; v != nil {
2604+
if jsonString, err := smithy.DocumentToJSONString(v); err == nil {
2605+
tfMap["hook_details"] = jsonString
2606+
}
2607+
}
2608+
26002609
tfList = append(tfList, tfMap)
26012610
}
26022611

@@ -2633,6 +2642,13 @@ func expandLifecycleHooks(tfList []any) []awstypes.DeploymentLifecycleHook {
26332642
hook.LifecycleStages = stages
26342643
}
26352644

2645+
if v, ok := tfMap["hook_details"].(string); ok && v != "" {
2646+
var jsonValue any
2647+
if err := json.Unmarshal([]byte(v), &jsonValue); err == nil {
2648+
hook.HookDetails = document.NewLazyDocument(jsonValue)
2649+
}
2650+
}
2651+
26362652
apiObject = append(apiObject, hook)
26372653
}
26382654

internal/service/ecs/service_test.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,14 @@ func TestAccECSService_BlueGreenDeployment_basic(t *testing.T) {
10131013
resource.TestCheckTypeSetElemAttrPair(resourceName, "deployment_configuration.0.lifecycle_hook.*.role_arn", "aws_iam_role.global", names.AttrARN),
10141014
resource.TestCheckTypeSetElemAttr(resourceName, "deployment_configuration.0.lifecycle_hook.*.lifecycle_stages.*", "POST_SCALE_UP"),
10151015
resource.TestCheckTypeSetElemAttr(resourceName, "deployment_configuration.0.lifecycle_hook.*.lifecycle_stages.*", "POST_TEST_TRAFFIC_SHIFT"),
1016+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "deployment_configuration.0.lifecycle_hook.*", map[string]string{
1017+
"hook_details": "[1,\"2\",true]",
1018+
"lifecycle_stages.0": "POST_SCALE_UP",
1019+
}),
1020+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "deployment_configuration.0.lifecycle_hook.*", map[string]string{
1021+
"hook_details": "3.14",
1022+
"lifecycle_stages.0": "TEST_TRAFFIC_SHIFT",
1023+
}),
10161024
// Load balancer advanced configuration checks
10171025
resource.TestCheckResourceAttr(resourceName, "load_balancer.0.advanced_configuration.#", "1"),
10181026
resource.TestCheckResourceAttrSet(resourceName, "load_balancer.0.advanced_configuration.0.alternate_target_group_arn"),
@@ -1036,6 +1044,10 @@ func TestAccECSService_BlueGreenDeployment_basic(t *testing.T) {
10361044
// Lifecycle hooks configuration checks
10371045
resource.TestCheckResourceAttr(resourceName, "deployment_configuration.0.lifecycle_hook.#", "1"),
10381046
resource.TestCheckTypeSetElemAttr(resourceName, "deployment_configuration.0.lifecycle_hook.*.lifecycle_stages.*", "PRE_SCALE_UP"),
1047+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "deployment_configuration.0.lifecycle_hook.*", map[string]string{
1048+
"hook_details": "{\"bool_key\":true,\"int_key\":10,\"list_key\":[1,\"2\",true],\"object_key\":{\"bool_key\":true,\"int_key\":10,\"list_key\":[1,\"2\",true],\"string_key\":\"string_val\"},\"string_key\":\"string_val\"}",
1049+
"lifecycle_stages.0": "PRE_SCALE_UP",
1050+
}),
10391051
// Service Connect test traffic rules checks
10401052
resource.TestCheckResourceAttr(resourceName, "service_connect_configuration.0.service.0.client_alias.0.test_traffic_rules.0.header.0.name", "x-test-header-2"),
10411053
resource.TestCheckResourceAttr(resourceName, "service_connect_configuration.0.service.0.client_alias.0.test_traffic_rules.0.header.0.value.0.exact", "test-value-2"),
@@ -1188,6 +1200,14 @@ func TestAccECSService_BlueGreenDeployment_changeStrategy(t *testing.T) {
11881200
Check: resource.ComposeTestCheckFunc(
11891201
testAccCheckServiceExists(ctx, resourceName, &service),
11901202
resource.TestCheckResourceAttr(resourceName, "deployment_configuration.0.strategy", "BLUE_GREEN"),
1203+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "deployment_configuration.0.lifecycle_hook.*", map[string]string{
1204+
"hook_details": acctest.CtTrue,
1205+
"lifecycle_stages.0": "POST_SCALE_UP",
1206+
}),
1207+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "deployment_configuration.0.lifecycle_hook.*", map[string]string{
1208+
"hook_details": "\"Test string\"",
1209+
"lifecycle_stages.0": "TEST_TRAFFIC_SHIFT",
1210+
}),
11911211
),
11921212
},
11931213
{
@@ -1281,7 +1301,7 @@ func TestAccECSService_BlueGreenDeployment_waitServiceActive(t *testing.T) {
12811301
CheckDestroy: testAccCheckServiceDestroy(ctx),
12821302
Steps: []resource.TestStep{
12831303
{
1284-
Config: testAccServiceConfig_blueGreenDeployment_basic(rName, true),
1304+
Config: testAccServiceConfig_blueGreenDeployment_basic(rName, false),
12851305
Check: resource.ComposeTestCheckFunc(
12861306
testAccCheckServiceExists(ctx, resourceName, &service),
12871307
resource.TestCheckResourceAttr(resourceName, "deployment_configuration.0.strategy", "BLUE_GREEN"),
@@ -2782,7 +2802,6 @@ func testAccCheckServiceExists(ctx context.Context, name string, service *awstyp
27822802

27832803
return nil
27842804
})
2785-
27862805
if err != nil {
27872806
return err
27882807
}
@@ -3482,12 +3501,14 @@ resource "aws_ecs_service" "test" {
34823501
hook_target_arn = aws_lambda_function.hook_success.arn
34833502
role_arn = aws_iam_role.global.arn
34843503
lifecycle_stages = ["POST_SCALE_UP", "POST_TEST_TRAFFIC_SHIFT"]
3504+
hook_details = jsonencode([1, "2", true])
34853505
}
34863506
34873507
lifecycle_hook {
34883508
hook_target_arn = aws_lambda_function.hook_success.arn
34893509
role_arn = aws_iam_role.global.arn
34903510
lifecycle_stages = ["TEST_TRAFFIC_SHIFT", "POST_PRODUCTION_TRAFFIC_SHIFT"]
3511+
hook_details = "3.14"
34913512
}
34923513
}
34933514
@@ -3723,6 +3744,12 @@ resource "aws_ecs_service" "test" {
37233744
hook_target_arn = %[2]s
37243745
role_arn = aws_iam_role.global.arn
37253746
lifecycle_stages = ["PRE_SCALE_UP"]
3747+
hook_details = jsonencode({ "bool_key" : true, "string_key" : "string_val", "int_key" : 10, "list_key" : [1, "2", true], "object_key" : {
3748+
"bool_key" : true,
3749+
"string_key" : "string_val",
3750+
"int_key" : 10,
3751+
"list_key" : [1, "2", true]
3752+
} })
37263753
}
37273754
}
37283755
@@ -3862,12 +3889,14 @@ resource "aws_ecs_service" "test" {
38623889
hook_target_arn = aws_lambda_function.hook_success.arn
38633890
role_arn = aws_iam_role.global.arn
38643891
lifecycle_stages = ["POST_SCALE_UP", "POST_TEST_TRAFFIC_SHIFT"]
3892+
hook_details = "true"
38653893
}
38663894
38673895
lifecycle_hook {
38683896
hook_target_arn = aws_lambda_function.hook_success.arn
38693897
role_arn = aws_iam_role.global.arn
38703898
lifecycle_stages = ["TEST_TRAFFIC_SHIFT", "POST_PRODUCTION_TRAFFIC_SHIFT"]
3899+
hook_details = jsonencode("Test string")
38713900
}
38723901
}
38733902

website/docs/r/ecs_service.html.markdown

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ The `lifecycle_hook` configuration block supports the following:
241241
* `hook_target_arn` - (Required) ARN of the Lambda function to invoke for the lifecycle hook.
242242
* `role_arn` - (Required) ARN of the IAM role that grants the service permission to invoke the Lambda function.
243243
* `lifecycle_stages` - (Required) Stages during the deployment when the hook should be invoked. Valid values: `RECONCILE_SERVICE`, `PRE_SCALE_UP`, `POST_SCALE_UP`, `TEST_TRAFFIC_SHIFT`, `POST_TEST_TRAFFIC_SHIFT`, `PRODUCTION_TRAFFIC_SHIFT`, `POST_PRODUCTION_TRAFFIC_SHIFT`.
244+
* `hook_details` - (Optional) Custom parameters that Amazon ECS will pass to the hook target invocations (such as a Lambda function).
244245

245246
### deployment_circuit_breaker
246247

0 commit comments

Comments
 (0)