Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tech debt: Migrate cloudwatch resources to AWS SDK for Go v2 #35569

Merged
merged 14 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/35569.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_cloudwatch_metric_stream: Add plan-time validation of `output_format`
```
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/cleanrooms v1.8.6
github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.15.7
github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.36.0
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.32.2
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.31.0
github.com/aws/aws-sdk-go-v2/service/codeartifact v1.23.6
github.com/aws/aws-sdk-go-v2/service/codebuild v1.28.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.15.7 h1:8sBfx7QkDZ6dgfUNXWH
github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.15.7/go.mod h1:P1EMD13hrBE2KUw030w482Eyk2NmOFIvGqmgNi4XRDc=
github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.36.0 h1:tRzTDe5E/dgGwJRR1cltjV9NPG9J5L7HK01+p2B4gCM=
github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.36.0/go.mod h1:ZyywmYcQbdJcIh8YMwqkw18mkA6nuQ+Uj1ouT2rXTYQ=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.32.2 h1:vQfCIHSDouEvbE4EuDrlCGKcrtABEqF3cMt61nGEV4g=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.32.2/go.mod h1:3ToKMEhVj+Q+HzZ8Hqin6LdAKtsi3zVXVNUPpQMd+Xk=
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.31.0 h1:Rk+Ft0Mu/eiNt2iJ2oS8Gf1h5m6q5crwS8cmlTylnvM=
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.31.0/go.mod h1:jZNaJEtn9TLi3pfxycLz79HVkKxP8ZdYm92iaNFgBsA=
github.com/aws/aws-sdk-go-v2/service/codeartifact v1.23.6 h1:QuI+Nh9lQ9EgCMhLzIDEp95cLnNd1vFHyODD0he0oQs=
Expand Down
6 changes: 3 additions & 3 deletions internal/conns/awsclient_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

126 changes: 59 additions & 67 deletions internal/service/cloudwatch/composite_alarm.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import (
"context"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch"
"github.com/aws/aws-sdk-go-v2/service/cloudwatch/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/errs"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
Expand All @@ -26,7 +26,7 @@ import (

// @SDKResource("aws_cloudwatch_composite_alarm", name="Composite Alarm")
// @Tags(identifierAttribute="arn")
func ResourceCompositeAlarm() *schema.Resource {
func resourceCompositeAlarm() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceCompositeAlarmCreate,
ReadWithoutTimeout: resourceCompositeAlarmRead,
Expand Down Expand Up @@ -68,7 +68,6 @@ func ResourceCompositeAlarm() *schema.Resource {
"alarm_actions": {
Type: schema.TypeSet,
Optional: true,
Set: schema.HashString,
MaxItems: 5,
Elem: &schema.Schema{
Type: schema.TypeString,
Expand Down Expand Up @@ -98,7 +97,6 @@ func ResourceCompositeAlarm() *schema.Resource {
"insufficient_data_actions": {
Type: schema.TypeSet,
Optional: true,
Set: schema.HashString,
MaxItems: 5,
Elem: &schema.Schema{
Type: schema.TypeString,
Expand All @@ -108,7 +106,6 @@ func ResourceCompositeAlarm() *schema.Resource {
"ok_actions": {
Type: schema.TypeSet,
Optional: true,
Set: schema.HashString,
MaxItems: 5,
Elem: &schema.Schema{
Type: schema.TypeString,
Expand All @@ -125,19 +122,18 @@ func ResourceCompositeAlarm() *schema.Resource {

func resourceCompositeAlarmCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics

conn := meta.(*conns.AWSClient).CloudWatchConn(ctx)
conn := meta.(*conns.AWSClient).CloudWatchClient(ctx)

name := d.Get("alarm_name").(string)
input := expandPutCompositeAlarmInput(ctx, d)

_, err := conn.PutCompositeAlarmWithContext(ctx, input)
_, err := conn.PutCompositeAlarm(ctx, input)

// Some partitions (e.g. ISO) may not support tag-on-create.
if input.Tags != nil && errs.IsUnsupportedOperationInPartitionError(conn.PartitionID, err) {
if input.Tags != nil && errs.IsUnsupportedOperationInPartitionError(meta.(*conns.AWSClient).Partition, err) {
input.Tags = nil

_, err = conn.PutCompositeAlarmWithContext(ctx, input)
_, err = conn.PutCompositeAlarm(ctx, input)
}

if err != nil {
Expand All @@ -148,16 +144,16 @@ func resourceCompositeAlarmCreate(ctx context.Context, d *schema.ResourceData, m

// For partitions not supporting tag-on-create, attempt tag after create.
if tags := getTagsIn(ctx); input.Tags == nil && len(tags) > 0 {
alarm, err := FindCompositeAlarmByName(ctx, conn, d.Id())
alarm, err := findCompositeAlarmByName(ctx, conn, d.Id())

if err != nil {
return sdkdiag.AppendErrorf(diags, "reading CloudWatch Composite Alarm (%s): %s", d.Id(), err)
}

err = createTags(ctx, conn, aws.StringValue(alarm.AlarmArn), tags)
err = createTags(ctx, conn, aws.ToString(alarm.AlarmArn), tags)

// If default tags only, continue. Otherwise, error.
if v, ok := d.GetOk(names.AttrTags); (!ok || len(v.(map[string]interface{})) == 0) && errs.IsUnsupportedOperationInPartitionError(conn.PartitionID, err) {
if v, ok := d.GetOk(names.AttrTags); (!ok || len(v.(map[string]interface{})) == 0) && errs.IsUnsupportedOperationInPartitionError(meta.(*conns.AWSClient).Partition, err) {
return append(diags, resourceCompositeAlarmRead(ctx, d, meta)...)
}

Expand All @@ -171,10 +167,9 @@ func resourceCompositeAlarmCreate(ctx context.Context, d *schema.ResourceData, m

func resourceCompositeAlarmRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).CloudWatchClient(ctx)

conn := meta.(*conns.AWSClient).CloudWatchConn(ctx)

alarm, err := FindCompositeAlarmByName(ctx, conn, d.Id())
alarm, err := findCompositeAlarmByName(ctx, conn, d.Id())

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] CloudWatch Composite Alarm %s not found, removing from state", d.Id())
Expand All @@ -194,26 +189,25 @@ func resourceCompositeAlarmRead(ctx context.Context, d *schema.ResourceData, met
} else {
d.Set("actions_suppressor", nil)
}
d.Set("alarm_actions", aws.StringValueSlice(alarm.AlarmActions))
d.Set("alarm_actions", alarm.AlarmActions)
d.Set("alarm_description", alarm.AlarmDescription)
d.Set("alarm_name", alarm.AlarmName)
d.Set("alarm_rule", alarm.AlarmRule)
d.Set("arn", alarm.AlarmArn)
d.Set("insufficient_data_actions", aws.StringValueSlice(alarm.InsufficientDataActions))
d.Set("ok_actions", aws.StringValueSlice(alarm.OKActions))
d.Set("insufficient_data_actions", alarm.InsufficientDataActions)
d.Set("ok_actions", alarm.OKActions)

return diags
}

func resourceCompositeAlarmUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics

conn := meta.(*conns.AWSClient).CloudWatchConn(ctx)
conn := meta.(*conns.AWSClient).CloudWatchClient(ctx)

if d.HasChangesExcept("tags", "tags_all") {
input := expandPutCompositeAlarmInput(ctx, d)

_, err := conn.PutCompositeAlarmWithContext(ctx, input)
_, err := conn.PutCompositeAlarm(ctx, input)

if err != nil {
return sdkdiag.AppendErrorf(diags, "updating CloudWatch Composite Alarm (%s): %s", d.Id(), err)
Expand All @@ -225,15 +219,14 @@ func resourceCompositeAlarmUpdate(ctx context.Context, d *schema.ResourceData, m

func resourceCompositeAlarmDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics

conn := meta.(*conns.AWSClient).CloudWatchConn(ctx)
conn := meta.(*conns.AWSClient).CloudWatchClient(ctx)

log.Printf("[INFO] Deleting CloudWatch Composite Alarm: %s", d.Id())
_, err := conn.DeleteAlarmsWithContext(ctx, &cloudwatch.DeleteAlarmsInput{
AlarmNames: aws.StringSlice([]string{d.Id()}),
_, err := conn.DeleteAlarms(ctx, &cloudwatch.DeleteAlarmsInput{
AlarmNames: tfslices.Of(d.Id()),
})

if tfawserr.ErrCodeEquals(err, cloudwatch.ErrCodeResourceNotFound) {
if errs.IsA[*types.ResourceNotFoundException](err) {
return diags
}

Expand All @@ -244,20 +237,13 @@ func resourceCompositeAlarmDelete(ctx context.Context, d *schema.ResourceData, m
return diags
}

func FindCompositeAlarmByName(ctx context.Context, conn *cloudwatch.CloudWatch, name string) (*cloudwatch.CompositeAlarm, error) {
func findCompositeAlarmByName(ctx context.Context, conn *cloudwatch.Client, name string) (*types.CompositeAlarm, error) {
input := &cloudwatch.DescribeAlarmsInput{
AlarmNames: aws.StringSlice([]string{name}),
AlarmTypes: aws.StringSlice([]string{cloudwatch.AlarmTypeCompositeAlarm}),
AlarmNames: tfslices.Of(name),
AlarmTypes: tfslices.Of(types.AlarmTypeCompositeAlarm),
}

output, err := conn.DescribeAlarmsWithContext(ctx, input)

if tfawserr.ErrCodeEquals(err, cloudwatch.ErrCodeResourceNotFound) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}
output, err := conn.DescribeAlarms(ctx, input)

if err != nil {
return nil, err
Expand All @@ -267,7 +253,7 @@ func FindCompositeAlarmByName(ctx context.Context, conn *cloudwatch.CloudWatch,
return nil, tfresource.NewEmptyResultError(input)
}

return tfresource.AssertSinglePtrResult(output.CompositeAlarms)
return tfresource.AssertSingleValueResult(output.CompositeAlarms)
}

func expandPutCompositeAlarmInput(ctx context.Context, d *schema.ResourceData) *cloudwatch.PutCompositeAlarmInput {
Expand All @@ -276,12 +262,12 @@ func expandPutCompositeAlarmInput(ctx context.Context, d *schema.ResourceData) *
Tags: getTagsIn(ctx),
}

if v, ok := d.GetOk("alarm_actions"); ok {
apiObject.AlarmActions = flex.ExpandStringSet(v.(*schema.Set))
if v, ok := d.GetOk("alarm_actions"); ok && v.(*schema.Set).Len() > 0 {
apiObject.AlarmActions = flex.ExpandStringValueSet(v.(*schema.Set))
}

if v, ok := d.GetOk("actions_suppressor"); ok && v != nil && len(v.([]interface{})) > 0 {
alarm := expandActionsSuppressor(v.([]interface{}))
if v, ok := d.GetOk("actions_suppressor"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
alarm := expandActionsSuppressor(v.([]interface{})[0].(map[string]interface{}))
apiObject.ActionsSuppressor = alarm.ActionsSuppressor
apiObject.ActionsSuppressorExtensionPeriod = alarm.ActionsSuppressorExtensionPeriod
apiObject.ActionsSuppressorWaitPeriod = alarm.ActionsSuppressorWaitPeriod
Expand All @@ -299,43 +285,49 @@ func expandPutCompositeAlarmInput(ctx context.Context, d *schema.ResourceData) *
apiObject.AlarmRule = aws.String(v.(string))
}

if v, ok := d.GetOk("insufficient_data_actions"); ok {
apiObject.InsufficientDataActions = flex.ExpandStringSet(v.(*schema.Set))
if v, ok := d.GetOk("insufficient_data_actions"); ok && v.(*schema.Set).Len() > 0 {
apiObject.InsufficientDataActions = flex.ExpandStringValueSet(v.(*schema.Set))
}

if v, ok := d.GetOk("ok_actions"); ok {
apiObject.OKActions = flex.ExpandStringSet(v.(*schema.Set))
if v, ok := d.GetOk("ok_actions"); ok && v.(*schema.Set).Len() > 0 {
apiObject.OKActions = flex.ExpandStringValueSet(v.(*schema.Set))
}

return apiObject
}

func flattenActionsSuppressor(alarm *cloudwatch.CompositeAlarm) map[string]interface{} {
actionsSuppressor := map[string]interface{}{
"alarm": aws.StringValue(alarm.ActionsSuppressor),
"extension_period": aws.Int64Value(alarm.ActionsSuppressorExtensionPeriod),
"wait_period": aws.Int64Value(alarm.ActionsSuppressorWaitPeriod),
func flattenActionsSuppressor(apiObject *types.CompositeAlarm) map[string]interface{} {
if apiObject == nil || apiObject.ActionsSuppressor == nil {
return nil
}

tfMap := map[string]interface{}{
"alarm": aws.ToString(apiObject.ActionsSuppressor),
"extension_period": aws.ToInt32(apiObject.ActionsSuppressorExtensionPeriod),
"wait_period": aws.ToInt32(apiObject.ActionsSuppressorWaitPeriod),
}
return actionsSuppressor

return tfMap
}

func expandActionsSuppressor(v []interface{}) *cloudwatch.CompositeAlarm {
if v[0] == nil {
func expandActionsSuppressor(tfMap map[string]interface{}) *types.CompositeAlarm {
if tfMap == nil {
return nil
}

alarmResource := v[0].(map[string]interface{})
alarm := cloudwatch.CompositeAlarm{}
apiObject := &types.CompositeAlarm{}

if v, ok := alarmResource["alarm"]; ok && v.(string) != "" {
alarm.ActionsSuppressor = aws.String(v.(string))
if v, ok := tfMap["alarm"]; ok && v.(string) != "" {
apiObject.ActionsSuppressor = aws.String(v.(string))
}
if v, ok := alarmResource["extension_period"]; ok {
alarm.ActionsSuppressorExtensionPeriod = aws.Int64(int64(v.(int)))

if v, ok := tfMap["extension_period"]; ok {
apiObject.ActionsSuppressorExtensionPeriod = aws.Int32(int32(v.(int)))
}
if v, ok := alarmResource["wait_period"]; ok {
alarm.ActionsSuppressorWaitPeriod = aws.Int64(int64(v.(int)))

if v, ok := tfMap["wait_period"]; ok {
apiObject.ActionsSuppressorWaitPeriod = aws.Int32(int32(v.(int)))
}

return &alarm
return apiObject
}
Loading
Loading