From 686a8b249ba42a4b3b95831b330ee12361be1879 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 21 Jun 2024 11:46:46 -0400 Subject: [PATCH 01/14] aws_controltower_control: add parameters attribute --- internal/service/controltower/control.go | 149 +++++++++++++++++++++-- 1 file changed, 140 insertions(+), 9 deletions(-) diff --git a/internal/service/controltower/control.go b/internal/service/controltower/control.go index 53004e4e24c..299394749d5 100644 --- a/internal/service/controltower/control.go +++ b/internal/service/controltower/control.go @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/controltower" + "github.com/aws/aws-sdk-go-v2/service/controltower/document" "github.com/aws/aws-sdk-go-v2/service/controltower/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" @@ -23,6 +24,7 @@ import ( tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" + "github.com/hashicorp/terraform-provider-aws/names" ) // @SDKResource("aws_controltower_control", name="Control") @@ -33,7 +35,24 @@ func resourceControl() *schema.Resource { DeleteWithoutTimeout: resourceControlDelete, Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, + StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + conn := meta.(*conns.AWSClient).ControlTowerClient(ctx) + + parts, err := flex.ExpandResourceId(d.Id(), controlResourceIDPartCount, false) + if err != nil { + return nil, err + } + + targetIdentifier, controlIdentifier := parts[0], parts[1] + output, err := findEnabledControlByTwoPartKey(ctx, conn, targetIdentifier, controlIdentifier) + if err != nil { + return nil, err + } + + d.Set(names.AttrARN, output.Arn) + + return []*schema.ResourceData{d}, nil + }, }, Timeouts: &schema.ResourceTimeout{ @@ -42,12 +61,33 @@ func resourceControl() *schema.Resource { }, Schema: map[string]*schema.Schema{ + names.AttrARN: { + Type: schema.TypeString, + Computed: true, + }, "control_identifier": { Type: schema.TypeString, Required: true, ForceNew: true, ValidateFunc: verify.ValidARN, }, + "parameters": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, "target_identifier": { Type: schema.TypeString, Required: true, @@ -71,6 +111,10 @@ func resourceControlCreate(ctx context.Context, d *schema.ResourceData, meta int TargetIdentifier: aws.String(targetIdentifier), } + if v, ok := d.GetOk("parameters"); ok && v.(*schema.Set).Len() > 0 { + input.Parameters = expandControlParameters(v.(*schema.Set).List()) + } + output, err := conn.EnableControl(ctx, input) if err != nil { @@ -78,6 +122,7 @@ func resourceControlCreate(ctx context.Context, d *schema.ResourceData, meta int } d.SetId(id) + d.Set(names.AttrARN, output.Arn) if _, err := waitOperationSucceeded(ctx, conn, aws.ToString(output.OperationIdentifier), d.Timeout(schema.TimeoutCreate)); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for ControlTower Control (%s) create: %s", d.Id(), err) @@ -91,13 +136,7 @@ func resourceControlRead(ctx context.Context, d *schema.ResourceData, meta inter conn := meta.(*conns.AWSClient).ControlTowerClient(ctx) - parts, err := flex.ExpandResourceId(d.Id(), controlResourceIDPartCount, false) - if err != nil { - return sdkdiag.AppendFromErr(diags, err) - } - - targetIdentifier, controlIdentifier := parts[0], parts[1] - output, err := findEnabledControlByTwoPartKey(ctx, conn, targetIdentifier, controlIdentifier) + output, err := findEnabledControlByARN(ctx, conn, d.Get(names.AttrARN).(string)) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] ControlTower Control %s not found, removing from state", d.Id()) @@ -110,7 +149,14 @@ func resourceControlRead(ctx context.Context, d *schema.ResourceData, meta inter } d.Set("control_identifier", output.ControlIdentifier) - d.Set("target_identifier", targetIdentifier) + + parameters, err := flattenControlParameters(output.Parameters) + if err != nil { + return sdkdiag.AppendErrorf(diags, "flattening ControlTower Control (%s) parameters: %s", d.Id(), err) + } + + d.Set("parameters", parameters) + d.Set("target_identifier", output.TargetIdentifier) return diags } @@ -148,6 +194,67 @@ const ( controlResourceIDPartCount = 2 ) +func expandControlParameters(input []any) []types.EnabledControlParameter { + if len(input) == 0 { + return nil + } + + var output []types.EnabledControlParameter + + for _, v := range input { + val := v.(map[string]any) + e := types.EnabledControlParameter{ + Key: aws.String(val["key"].(string)), + Value: document.NewLazyDocument(val["value"].(*schema.Set).List()), + } + + output = append(output, e) + } + + return output +} + +func flattenControlParameters(input []types.EnabledControlParameterSummary) (*schema.Set, error) { + if len(input) == 0 { + return nil, nil + } + + res := &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } + + var output []any + + for _, v := range input { + val := map[string]any{ + "key": aws.ToString(v.Key), + } + + var va []any + err := v.Value.UnmarshalSmithyDocument(&va) + + if err != nil { + log.Printf("[WARN] Error unmarshalling control parameter value: %s", err) + return nil, err + } + + val["value"] = schema.NewSet(schema.HashString, va) + output = append(output, val) + } + + return schema.NewSet(schema.HashResource(res), output), nil +} + func findEnabledControlByTwoPartKey(ctx context.Context, conn *controltower.Client, targetIdentifier, controlIdentifier string) (*types.EnabledControlSummary, error) { input := &controltower.ListEnabledControlsInput{ TargetIdentifier: aws.String(targetIdentifier), @@ -197,6 +304,30 @@ func findEnabledControls(ctx context.Context, conn *controltower.Client, input * return output, nil } +func findEnabledControlByARN(ctx context.Context, conn *controltower.Client, arn string) (*types.EnabledControlDetails, error) { + input := &controltower.GetEnabledControlInput{ + EnabledControlIdentifier: aws.String(arn), + } + + output, err := conn.GetEnabledControl(ctx, input) + + if errs.IsA[*types.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || output.EnabledControlDetails == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.EnabledControlDetails, nil +} func findControlOperationByID(ctx context.Context, conn *controltower.Client, id string) (*types.ControlOperation, error) { input := &controltower.GetControlOperationInput{ OperationIdentifier: aws.String(id), From bd1bef6003387241e39ff74146374f2bb4b54db8 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 21 Jun 2024 11:48:13 -0400 Subject: [PATCH 02/14] fix semgrep errors --- internal/service/controltower/control.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/service/controltower/control.go b/internal/service/controltower/control.go index 299394749d5..e6547efd683 100644 --- a/internal/service/controltower/control.go +++ b/internal/service/controltower/control.go @@ -71,16 +71,16 @@ func resourceControl() *schema.Resource { ForceNew: true, ValidateFunc: verify.ValidARN, }, - "parameters": { + names.AttrParameters: { Type: schema.TypeSet, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "key": { + names.AttrKey: { Type: schema.TypeString, Required: true, }, - "value": { + names.AttrValue: { Type: schema.TypeSet, Required: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -111,7 +111,7 @@ func resourceControlCreate(ctx context.Context, d *schema.ResourceData, meta int TargetIdentifier: aws.String(targetIdentifier), } - if v, ok := d.GetOk("parameters"); ok && v.(*schema.Set).Len() > 0 { + if v, ok := d.GetOk(names.AttrParameters); ok && v.(*schema.Set).Len() > 0 { input.Parameters = expandControlParameters(v.(*schema.Set).List()) } @@ -155,7 +155,7 @@ func resourceControlRead(ctx context.Context, d *schema.ResourceData, meta inter return sdkdiag.AppendErrorf(diags, "flattening ControlTower Control (%s) parameters: %s", d.Id(), err) } - d.Set("parameters", parameters) + d.Set(names.AttrParameters, parameters) d.Set("target_identifier", output.TargetIdentifier) return diags @@ -204,8 +204,8 @@ func expandControlParameters(input []any) []types.EnabledControlParameter { for _, v := range input { val := v.(map[string]any) e := types.EnabledControlParameter{ - Key: aws.String(val["key"].(string)), - Value: document.NewLazyDocument(val["value"].(*schema.Set).List()), + Key: aws.String(val[names.AttrKey].(string)), + Value: document.NewLazyDocument(val[names.AttrValue].(*schema.Set).List()), } output = append(output, e) @@ -221,11 +221,11 @@ func flattenControlParameters(input []types.EnabledControlParameterSummary) (*sc res := &schema.Resource{ Schema: map[string]*schema.Schema{ - "key": { + names.AttrKey: { Type: schema.TypeString, Required: true, }, - "value": { + names.AttrValue: { Type: schema.TypeSet, Required: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -237,7 +237,7 @@ func flattenControlParameters(input []types.EnabledControlParameterSummary) (*sc for _, v := range input { val := map[string]any{ - "key": aws.ToString(v.Key), + names.AttrKey: aws.ToString(v.Key), } var va []any @@ -248,7 +248,7 @@ func flattenControlParameters(input []types.EnabledControlParameterSummary) (*sc return nil, err } - val["value"] = schema.NewSet(schema.HashString, va) + val[names.AttrValue] = schema.NewSet(schema.HashString, va) output = append(output, val) } From d8e901a1e00b09772ce8e3fdab4e54de5bed2de3 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 21 Jun 2024 12:44:40 -0400 Subject: [PATCH 03/14] update documentation --- .../docs/r/controltower_control.html.markdown | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/website/docs/r/controltower_control.html.markdown b/website/docs/r/controltower_control.html.markdown index 786a962a715..9fb120c8900 100644 --- a/website/docs/r/controltower_control.html.markdown +++ b/website/docs/r/controltower_control.html.markdown @@ -28,20 +28,35 @@ resource "aws_controltower_control" "example" { for x in data.aws_organizations_organizational_units.example.children : x.arn if x.name == "Infrastructure" ][0] + + parameters { + key = "AllowedRegions" + value = ["us-east-1"] + } } ``` ## Argument Reference -This resource supports the following arguments: +This following arguments are required: * `control_identifier` - (Required) The ARN of the control. Only Strongly recommended and Elective controls are permitted, with the exception of the Region deny guardrail. * `target_identifier` - (Required) The ARN of the organizational unit. +The following arguments are optional: + +* `parameters` - (Optional) Parameter values which are specified to configure the control when you enable it. See [Parameters](#parameters) for more details. + +### Parameters + +* `key` - (Required) The name of the parameter. +* `value` - (Required) The value of the parameter. + ## Attribute Reference This resource exports the following attributes in addition to the arguments above: +* `arn` - The ARN of the EnabledControl resource. * `id` - The ARN of the organizational unit. ## Import From f84a91c0bfb69cf4db224831e504fe42d0c5dd39 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 21 Jun 2024 12:52:41 -0400 Subject: [PATCH 04/14] fmt docs --- website/docs/r/controltower_control.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/controltower_control.html.markdown b/website/docs/r/controltower_control.html.markdown index 9fb120c8900..b8313d4c457 100644 --- a/website/docs/r/controltower_control.html.markdown +++ b/website/docs/r/controltower_control.html.markdown @@ -28,7 +28,7 @@ resource "aws_controltower_control" "example" { for x in data.aws_organizations_organizational_units.example.children : x.arn if x.name == "Infrastructure" ][0] - + parameters { key = "AllowedRegions" value = ["us-east-1"] From 6fa25937ad30bb3e8affd31e175b0e8a05c62609 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 21 Jun 2024 13:19:28 -0400 Subject: [PATCH 05/14] aws_controltower_control: add update handler --- internal/service/controltower/control.go | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/internal/service/controltower/control.go b/internal/service/controltower/control.go index e6547efd683..30b9ab225ef 100644 --- a/internal/service/controltower/control.go +++ b/internal/service/controltower/control.go @@ -32,6 +32,7 @@ func resourceControl() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceControlCreate, ReadWithoutTimeout: resourceControlRead, + UpdateWithoutTimeout: resourceControlUpdate, DeleteWithoutTimeout: resourceControlDelete, Importer: &schema.ResourceImporter{ @@ -57,6 +58,7 @@ func resourceControl() *schema.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(60 * time.Minute), + Update: schema.DefaultTimeout(60 * time.Minute), Delete: schema.DefaultTimeout(60 * time.Minute), }, @@ -161,6 +163,31 @@ func resourceControlRead(ctx context.Context, d *schema.ResourceData, meta inter return diags } +func resourceControlUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + + conn := meta.(*conns.AWSClient).ControlTowerClient(ctx) + + if d.HasChange(names.AttrParameters) { + input := &controltower.UpdateEnabledControlInput{ + EnabledControlIdentifier: aws.String(d.Get(names.AttrARN).(string)), + Parameters: expandControlParameters(d.Get(names.AttrParameters).(*schema.Set).List()), + } + + output, err := conn.UpdateEnabledControl(ctx, input) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating ControlTower Control (%s): %s", d.Id(), err) + } + + if _, err := waitOperationSucceeded(ctx, conn, aws.ToString(output.OperationIdentifier), d.Timeout(schema.TimeoutUpdate)); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for ControlTower Control (%s) delete: %s", d.Id(), err) + } + } + + return append(diags, resourceControlRead(ctx, d, meta)...) +} + func resourceControlDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics From b57e381d11d5c3fc0cd6b15d28c716f6c48b4621 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 24 Jun 2024 09:11:35 -0500 Subject: [PATCH 06/14] aws_controltower_control: chage paramters value to json string --- internal/service/controltower/control.go | 36 ++++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/internal/service/controltower/control.go b/internal/service/controltower/control.go index 30b9ab225ef..3406df284c0 100644 --- a/internal/service/controltower/control.go +++ b/internal/service/controltower/control.go @@ -5,6 +5,7 @@ package controltower import ( "context" + "encoding/json" "errors" "log" "time" @@ -83,9 +84,9 @@ func resourceControl() *schema.Resource { Required: true, }, names.AttrValue: { - Type: schema.TypeSet, + Type: schema.TypeString, Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, + // ValidateFunc: verify.ValidStringIsJSONOrYAML, }, }, }, @@ -114,7 +115,12 @@ func resourceControlCreate(ctx context.Context, d *schema.ResourceData, meta int } if v, ok := d.GetOk(names.AttrParameters); ok && v.(*schema.Set).Len() > 0 { - input.Parameters = expandControlParameters(v.(*schema.Set).List()) + p, err := expandControlParameters(v.(*schema.Set).List()) + if err != nil { + return sdkdiag.AppendErrorf(diags, "creating ControlTower Control (%s): %s", id, err) + } + + input.Parameters = p } output, err := conn.EnableControl(ctx, input) @@ -171,9 +177,15 @@ func resourceControlUpdate(ctx context.Context, d *schema.ResourceData, meta int if d.HasChange(names.AttrParameters) { input := &controltower.UpdateEnabledControlInput{ EnabledControlIdentifier: aws.String(d.Get(names.AttrARN).(string)), - Parameters: expandControlParameters(d.Get(names.AttrParameters).(*schema.Set).List()), } + p, err := expandControlParameters(d.Get(names.AttrParameters).(*schema.Set).List()) + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating ControlTower Control (%s): %s", d.Id(), err) + } + + input.Parameters = p + output, err := conn.UpdateEnabledControl(ctx, input) if err != nil { @@ -221,9 +233,9 @@ const ( controlResourceIDPartCount = 2 ) -func expandControlParameters(input []any) []types.EnabledControlParameter { +func expandControlParameters(input []any) ([]types.EnabledControlParameter, error) { if len(input) == 0 { - return nil + return nil, nil } var output []types.EnabledControlParameter @@ -231,14 +243,20 @@ func expandControlParameters(input []any) []types.EnabledControlParameter { for _, v := range input { val := v.(map[string]any) e := types.EnabledControlParameter{ - Key: aws.String(val[names.AttrKey].(string)), - Value: document.NewLazyDocument(val[names.AttrValue].(*schema.Set).List()), + Key: aws.String(val[names.AttrKey].(string)), } + var out any + err := json.Unmarshal([]byte(val[names.AttrValue].(string)), &out) + if err != nil { + return nil, err + } + + e.Value = document.NewLazyDocument(out) output = append(output, e) } - return output + return output, nil } func flattenControlParameters(input []types.EnabledControlParameterSummary) (*schema.Set, error) { From 65fe8cebfd4b17616977f7f3db2cfad113492eb3 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 24 Jun 2024 10:52:56 -0500 Subject: [PATCH 07/14] use string for values in flatten --- internal/service/controltower/control.go | 18 +++++++++++------- .../docs/r/controltower_control.html.markdown | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/internal/service/controltower/control.go b/internal/service/controltower/control.go index 3406df284c0..bcd6f1caa89 100644 --- a/internal/service/controltower/control.go +++ b/internal/service/controltower/control.go @@ -84,9 +84,9 @@ func resourceControl() *schema.Resource { Required: true, }, names.AttrValue: { - Type: schema.TypeString, - Required: true, - // ValidateFunc: verify.ValidStringIsJSONOrYAML, + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidStringIsJSONOrYAML, }, }, }, @@ -271,9 +271,8 @@ func flattenControlParameters(input []types.EnabledControlParameterSummary) (*sc Required: true, }, names.AttrValue: { - Type: schema.TypeSet, + Type: schema.TypeString, Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, }, }, } @@ -285,7 +284,7 @@ func flattenControlParameters(input []types.EnabledControlParameterSummary) (*sc names.AttrKey: aws.ToString(v.Key), } - var va []any + var va any err := v.Value.UnmarshalSmithyDocument(&va) if err != nil { @@ -293,7 +292,12 @@ func flattenControlParameters(input []types.EnabledControlParameterSummary) (*sc return nil, err } - val[names.AttrValue] = schema.NewSet(schema.HashString, va) + out, err := json.Marshal(va) + if err != nil { + return nil, err + } + + val[names.AttrValue] = string(out) output = append(output, val) } diff --git a/website/docs/r/controltower_control.html.markdown b/website/docs/r/controltower_control.html.markdown index b8313d4c457..22d1a1d2502 100644 --- a/website/docs/r/controltower_control.html.markdown +++ b/website/docs/r/controltower_control.html.markdown @@ -31,7 +31,7 @@ resource "aws_controltower_control" "example" { parameters { key = "AllowedRegions" - value = ["us-east-1"] + value = jsonencode(["us-east-1"]) } } ``` From d28eca16ee79ab30715c0d31d73fcfe45f0390b8 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 24 Jun 2024 11:47:17 -0500 Subject: [PATCH 08/14] add CHANGELOG entry --- .changelog/38071.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/38071.txt diff --git a/.changelog/38071.txt b/.changelog/38071.txt new file mode 100644 index 00000000000..54271b48bb0 --- /dev/null +++ b/.changelog/38071.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_controltower_control: Add `parameters` attribute +``` \ No newline at end of file From f998df6debd238c0586376798efee6b8e184d6fe Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 24 Jun 2024 14:05:02 -0500 Subject: [PATCH 09/14] Update CHANGELOG Co-authored-by: Dirk Avery <31492422+YakDriver@users.noreply.github.com> --- .changelog/38071.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changelog/38071.txt b/.changelog/38071.txt index 54271b48bb0..d1b631727d9 100644 --- a/.changelog/38071.txt +++ b/.changelog/38071.txt @@ -1,3 +1,3 @@ ```release-note:enhancement -resource/aws_controltower_control: Add `parameters` attribute +resource/aws_controltower_control: Add `parameters` argument and `arn` attribute ``` \ No newline at end of file From de8b9c85346c0bd117ff58e0e4cc193e6a55ca5b Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 24 Jun 2024 14:09:58 -0500 Subject: [PATCH 10/14] aws_controltower_control: add parameters argument in testing --- internal/service/controltower/control_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/service/controltower/control_test.go b/internal/service/controltower/control_test.go index a0ed871d402..2ebb486153b 100644 --- a/internal/service/controltower/control_test.go +++ b/internal/service/controltower/control_test.go @@ -153,6 +153,11 @@ resource "aws_controltower_control" "test" { for x in data.aws_organizations_organizational_units.test.children : x.arn if x.name == "%[2]s" ][0] + + parameters { + key = "AllowedRegions" + value = jsonencode(["us-east-1"]) + } } `, controlName, ouName) } From 16617d6e8745b476c794b6feb75e8428c026f07c Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 24 Jun 2024 14:26:03 -0500 Subject: [PATCH 11/14] aws_controltower_control: only query by ARN if it is set --- internal/service/controltower/control.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/internal/service/controltower/control.go b/internal/service/controltower/control.go index bcd6f1caa89..a30cabe39b9 100644 --- a/internal/service/controltower/control.go +++ b/internal/service/controltower/control.go @@ -144,7 +144,25 @@ func resourceControlRead(ctx context.Context, d *schema.ResourceData, meta inter conn := meta.(*conns.AWSClient).ControlTowerClient(ctx) - output, err := findEnabledControlByARN(ctx, conn, d.Get(names.AttrARN).(string)) + var output *types.EnabledControlDetails + var err error + if v, ok := d.GetOk(names.AttrARN); ok && v.(string) != "" { + output, err = findEnabledControlByARN(ctx, conn, d.Get(names.AttrARN).(string)) + } else { + // backwards compatibility if ARN is not set from existing state + parts, err := flex.ExpandResourceId(d.Id(), controlResourceIDPartCount, false) + if err != nil { + return sdkdiag.AppendFromErr(diags, err) + } + + targetIdentifier, controlIdentifier := parts[0], parts[1] + out, err := findEnabledControlByTwoPartKey(ctx, conn, targetIdentifier, controlIdentifier) + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading ControlTower Control (%s): %s", d.Id(), err) + } + + output, err = findEnabledControlByARN(ctx, conn, aws.ToString(out.Arn)) + } if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] ControlTower Control %s not found, removing from state", d.Id()) @@ -156,6 +174,7 @@ func resourceControlRead(ctx context.Context, d *schema.ResourceData, meta inter return sdkdiag.AppendErrorf(diags, "reading ControlTower Control (%s): %s", d.Id(), err) } + d.Set(names.AttrARN, output.Arn) d.Set("control_identifier", output.ControlIdentifier) parameters, err := flattenControlParameters(output.Parameters) From 2ff855c1d12fd0e76998190fe8b4453897a4f2ca Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 24 Jun 2024 14:29:26 -0500 Subject: [PATCH 12/14] aws_controltower_control: linter error for hard coded regions --- internal/service/controltower/control_test.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/internal/service/controltower/control_test.go b/internal/service/controltower/control_test.go index 2ebb486153b..4531c115f5f 100644 --- a/internal/service/controltower/control_test.go +++ b/internal/service/controltower/control_test.go @@ -37,6 +37,7 @@ func testAccControl_basic(t *testing.T) { resourceName := "aws_controltower_control.test" controlName := "AWS-GR_EC2_VOLUME_INUSE_CHECK" ouName := "Security" + region := "us-west-2" //lintignore:AWSAT003 resource.Test(t, resource.TestCase{ PreCheck: func() { @@ -49,7 +50,7 @@ func testAccControl_basic(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccControlConfig_basic(controlName, ouName), + Config: testAccControlConfig_basic(controlName, ouName, region), Check: resource.ComposeTestCheckFunc( testAccCheckControlExists(ctx, resourceName, &control), resource.TestCheckResourceAttrSet(resourceName, "control_identifier"), @@ -65,6 +66,7 @@ func testAccControl_disappears(t *testing.T) { resourceName := "aws_controltower_control.test" controlName := "AWS-GR_EC2_VOLUME_INUSE_CHECK" ouName := "Security" + region := "us-west-2" //lintignore:AWSAT003 resource.Test(t, resource.TestCase{ PreCheck: func() { @@ -77,7 +79,7 @@ func testAccControl_disappears(t *testing.T) { CheckDestroy: testAccCheckControlDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccControlConfig_basic(controlName, ouName), + Config: testAccControlConfig_basic(controlName, ouName, region), Check: resource.ComposeTestCheckFunc( testAccCheckControlExists(ctx, resourceName, &control), acctest.CheckResourceDisappears(ctx, acctest.Provider, tfcontroltower.ResourceControl(), resourceName), @@ -135,7 +137,7 @@ func testAccCheckControlDestroy(ctx context.Context) resource.TestCheckFunc { } } -func testAccControlConfig_basic(controlName string, ouName string) string { +func testAccControlConfig_basic(controlName, ouName, region string) string { return fmt.Sprintf(` data "aws_region" "current" {} @@ -156,8 +158,8 @@ resource "aws_controltower_control" "test" { parameters { key = "AllowedRegions" - value = jsonencode(["us-east-1"]) + value = jsonencode([%[3]q]) } } -`, controlName, ouName) +`, controlName, ouName, region) } From 413025b92b84640ae491014bafae5b3cf3b94dbe Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 24 Jun 2024 14:41:48 -0500 Subject: [PATCH 13/14] aws_controltower_control: only query by ARN if it is set --- internal/service/controltower/control.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/controltower/control.go b/internal/service/controltower/control.go index a30cabe39b9..b68feeeadb8 100644 --- a/internal/service/controltower/control.go +++ b/internal/service/controltower/control.go @@ -146,8 +146,8 @@ func resourceControlRead(ctx context.Context, d *schema.ResourceData, meta inter var output *types.EnabledControlDetails var err error - if v, ok := d.GetOk(names.AttrARN); ok && v.(string) != "" { - output, err = findEnabledControlByARN(ctx, conn, d.Get(names.AttrARN).(string)) + if v, ok := d.GetOk(names.AttrARN); ok { + output, err = findEnabledControlByARN(ctx, conn, v.(string)) } else { // backwards compatibility if ARN is not set from existing state parts, err := flex.ExpandResourceId(d.Id(), controlResourceIDPartCount, false) From a856ac75bd9ced3cc8b000e26a74d28912e78d1a Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 24 Jun 2024 14:52:57 -0500 Subject: [PATCH 14/14] chore: liters --- internal/service/controltower/control.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/service/controltower/control.go b/internal/service/controltower/control.go index b68feeeadb8..fda5478d26c 100644 --- a/internal/service/controltower/control.go +++ b/internal/service/controltower/control.go @@ -150,14 +150,14 @@ func resourceControlRead(ctx context.Context, d *schema.ResourceData, meta inter output, err = findEnabledControlByARN(ctx, conn, v.(string)) } else { // backwards compatibility if ARN is not set from existing state - parts, err := flex.ExpandResourceId(d.Id(), controlResourceIDPartCount, false) - if err != nil { + parts, internalErr := flex.ExpandResourceId(d.Id(), controlResourceIDPartCount, false) + if internalErr != nil { return sdkdiag.AppendFromErr(diags, err) } targetIdentifier, controlIdentifier := parts[0], parts[1] - out, err := findEnabledControlByTwoPartKey(ctx, conn, targetIdentifier, controlIdentifier) - if err != nil { + out, internalErr := findEnabledControlByTwoPartKey(ctx, conn, targetIdentifier, controlIdentifier) + if internalErr != nil { return sdkdiag.AppendErrorf(diags, "reading ControlTower Control (%s): %s", d.Id(), err) }