diff --git a/.changelog/32343.txt b/.changelog/32343.txt new file mode 100644 index 000000000000..15bda9ef7081 --- /dev/null +++ b/.changelog/32343.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_internetmonitor_monitor: Add `health_events_config` configuration block +``` \ No newline at end of file diff --git a/go.mod b/go.mod index 80deb0e78001..7b158123e3d1 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/healthlake v1.16.2 github.com/aws/aws-sdk-go-v2/service/identitystore v1.16.13 github.com/aws/aws-sdk-go-v2/service/inspector2 v1.15.0 + github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.3.0 github.com/aws/aws-sdk-go-v2/service/ivschat v1.4.7 github.com/aws/aws-sdk-go-v2/service/kendra v1.41.0 github.com/aws/aws-sdk-go-v2/service/keyspaces v1.3.2 diff --git a/go.sum b/go.sum index 914963fa7557..f27bae689969 100644 --- a/go.sum +++ b/go.sum @@ -82,6 +82,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 h1:bkRyG4a92 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28/go.mod h1:jj7znCIg05jXlaGBlFMGP8+7UN3VtCkRBG2spnmRQkU= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.3 h1:dBL3StFxHtpBzJJ/mNEsjXVgfO+7jR0dAIEwLqMapEA= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.3/go.mod h1:f1QyiAsvIv4B49DmCqrhlXqyaR+0IxMmyX+1P+AnzOM= +github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.3.0 h1:qy8Ko+RdwqmhmHmFdTX9BBGArWEbQV7iuIvFroxfy/g= +github.com/aws/aws-sdk-go-v2/service/internetmonitor v1.3.0/go.mod h1:dopruDWBqM3sxYZWprHj065umhsYqKfzTgpv21od6us= github.com/aws/aws-sdk-go-v2/service/ivschat v1.4.7 h1:pI950CQHVEFW2/+UklRO4TWzHdO83bedFO9s6vH1R3k= github.com/aws/aws-sdk-go-v2/service/ivschat v1.4.7/go.mod h1:oOLFrfP14cyQdTsc3I8VohdYb8g86I7xduoMALyKLj0= github.com/aws/aws-sdk-go-v2/service/kendra v1.41.0 h1:QZIaiIYfU8KCUuT4nCif9fifXryv+/pI/ounZMB4/0s= diff --git a/internal/conns/awsclient_gen.go b/internal/conns/awsclient_gen.go index c2b329ce4aaa..9e55e5017406 100644 --- a/internal/conns/awsclient_gen.go +++ b/internal/conns/awsclient_gen.go @@ -23,6 +23,7 @@ import ( healthlake_sdkv2 "github.com/aws/aws-sdk-go-v2/service/healthlake" identitystore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/identitystore" inspector2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/inspector2" + internetmonitor_sdkv2 "github.com/aws/aws-sdk-go-v2/service/internetmonitor" ivschat_sdkv2 "github.com/aws/aws-sdk-go-v2/service/ivschat" kendra_sdkv2 "github.com/aws/aws-sdk-go-v2/service/kendra" keyspaces_sdkv2 "github.com/aws/aws-sdk-go-v2/service/keyspaces" @@ -175,7 +176,6 @@ import ( iam_sdkv1 "github.com/aws/aws-sdk-go/service/iam" imagebuilder_sdkv1 "github.com/aws/aws-sdk-go/service/imagebuilder" inspector_sdkv1 "github.com/aws/aws-sdk-go/service/inspector" - internetmonitor_sdkv1 "github.com/aws/aws-sdk-go/service/internetmonitor" iot_sdkv1 "github.com/aws/aws-sdk-go/service/iot" iot1clickdevicesservice_sdkv1 "github.com/aws/aws-sdk-go/service/iot1clickdevicesservice" iot1clickprojects_sdkv1 "github.com/aws/aws-sdk-go/service/iot1clickprojects" @@ -904,8 +904,8 @@ func (c *AWSClient) Inspector2Client(ctx context.Context) *inspector2_sdkv2.Clie return errs.Must(client[*inspector2_sdkv2.Client](ctx, c, names.Inspector2)) } -func (c *AWSClient) InternetMonitorConn(ctx context.Context) *internetmonitor_sdkv1.InternetMonitor { - return errs.Must(conn[*internetmonitor_sdkv1.InternetMonitor](ctx, c, names.InternetMonitor)) +func (c *AWSClient) InternetMonitorClient(ctx context.Context) *internetmonitor_sdkv2.Client { + return errs.Must(client[*internetmonitor_sdkv2.Client](ctx, c, names.InternetMonitor)) } func (c *AWSClient) IoTConn(ctx context.Context) *iot_sdkv1.IoT { diff --git a/internal/service/internetmonitor/exports_test.go b/internal/service/internetmonitor/exports_test.go new file mode 100644 index 000000000000..22cb05eb66ce --- /dev/null +++ b/internal/service/internetmonitor/exports_test.go @@ -0,0 +1,8 @@ +package internetmonitor + +// Exports for use in tests only. +var ( + ResourceMonitor = resourceMonitor + + FindMonitorByName = findMonitorByName +) diff --git a/internal/service/internetmonitor/find.go b/internal/service/internetmonitor/find.go deleted file mode 100644 index acf379526a42..000000000000 --- a/internal/service/internetmonitor/find.go +++ /dev/null @@ -1,31 +0,0 @@ -package internetmonitor - -import ( - "context" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/internetmonitor" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" -) - -func FindMonitor(ctx context.Context, conn *internetmonitor.InternetMonitor, name string) (*internetmonitor.GetMonitorOutput, error) { - input := &internetmonitor.GetMonitorInput{ - MonitorName: aws.String(name), - } - - output, err := conn.GetMonitorWithContext(ctx, input) - - if tfawserr.ErrCodeEquals(err, internetmonitor.ErrCodeResourceNotFoundException) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: input, - } - } - - if err != nil { - return nil, err - } - - return output, nil -} diff --git a/internal/service/internetmonitor/generate.go b/internal/service/internetmonitor/generate.go index 143d8950d840..f6275608c321 100644 --- a/internal/service/internetmonitor/generate.go +++ b/internal/service/internetmonitor/generate.go @@ -1,4 +1,4 @@ -//go:generate go run ../../generate/tags/main.go -ListTags -ListTagsInIDElem=ResourceArn -ServiceTagsMap -TagInIDElem=ResourceArn -UpdateTags +//go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -ListTags -ListTagsInIDElem=ResourceArn -ServiceTagsMap -KVTValues -TagInIDElem=ResourceArn -UpdateTags -SkipTypesImp //go:generate go run ../../generate/servicepackage/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. diff --git a/internal/service/internetmonitor/monitor.go b/internal/service/internetmonitor/monitor.go index a6b3720807ff..deff29cc73c7 100644 --- a/internal/service/internetmonitor/monitor.go +++ b/internal/service/internetmonitor/monitor.go @@ -2,16 +2,21 @@ package internetmonitor import ( "context" + "errors" "log" + "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/internetmonitor" - "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/internetmonitor" + "github.com/aws/aws-sdk-go-v2/service/internetmonitor/types" + "github.com/hashicorp/aws-sdk-go-base/v2/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "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/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -22,12 +27,13 @@ import ( // @SDKResource("aws_internetmonitor_monitor", name="Monitor") // @Tags(identifierAttribute="arn") -func ResourceMonitor() *schema.Resource { +func resourceMonitor() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceMonitorCreate, ReadWithoutTimeout: resourceMonitorRead, UpdateWithoutTimeout: resourceMonitorUpdate, DeleteWithoutTimeout: resourceMonitorDelete, + Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, @@ -37,6 +43,25 @@ func ResourceMonitor() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "health_events_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "availability_score_threshold": { + Type: schema.TypeFloat, + Optional: true, + Default: 95.0, + }, + "performance_score_threshold": { + Type: schema.TypeFloat, + Optional: true, + Default: 95.0, + }, + }, + }, + }, "internet_measurements_log_delivery": { Type: schema.TypeList, Optional: true, @@ -59,10 +84,10 @@ func ResourceMonitor() *schema.Resource { Optional: true, }, "log_delivery_status": { - Type: schema.TypeString, - Optional: true, - Default: internetmonitor.LogDeliveryStatusEnabled, - ValidateFunc: validation.StringInSlice(internetmonitor.LogDeliveryStatus_Values(), false), + Type: schema.TypeString, + Optional: true, + Default: types.LogDeliveryStatusEnabled, + ValidateDiagFunc: enum.Validate[types.LogDeliveryStatus](), }, }, }, @@ -93,11 +118,11 @@ func ResourceMonitor() *schema.Resource { "status": { Type: schema.TypeString, Optional: true, - Default: internetmonitor.MonitorConfigStateActive, - ValidateFunc: validation.StringInSlice([]string{ - internetmonitor.MonitorConfigStateActive, - internetmonitor.MonitorConfigStateInactive, - }, false), + Default: types.MonitorConfigStateActive, + ValidateFunc: validation.StringInSlice(enum.Slice( + types.MonitorConfigStateActive, + types.MonitorConfigStateInactive, + ), false), }, names.AttrTags: tftags.TagsSchema(), names.AttrTagsAll: tftags.TagsSchemaComputed(), @@ -112,57 +137,70 @@ func ResourceMonitor() *schema.Resource { } } +const ( + errCodeResourceNotFoundException = "ResourceNotFoundException" +) + func resourceMonitorCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).InternetMonitorConn(ctx) + conn := meta.(*conns.AWSClient).InternetMonitorClient(ctx) - monitorName := d.Get("monitor_name").(string) + name := d.Get("monitor_name").(string) input := &internetmonitor.CreateMonitorInput{ ClientToken: aws.String(id.UniqueId()), - MonitorName: aws.String(monitorName), + MonitorName: aws.String(name), Tags: getTagsIn(ctx), } - if v, ok := d.GetOk("max_city_networks_to_monitor"); ok { - input.MaxCityNetworksToMonitor = aws.Int64(int64(v.(int))) - } - - if v, ok := d.GetOk("traffic_percentage_to_monitor"); ok { - input.TrafficPercentageToMonitor = aws.Int64(int64(v.(int))) + if v, ok := d.GetOk("health_events_config"); ok { + input.HealthEventsConfig = expandHealthEventsConfig(v.([]interface{})) } if v, ok := d.GetOk("internet_measurements_log_delivery"); ok { input.InternetMeasurementsLogDelivery = expandInternetMeasurementsLogDelivery(v.([]interface{})) } + if v, ok := d.GetOk("max_city_networks_to_monitor"); ok { + input.MaxCityNetworksToMonitor = int32(v.(int)) + } + if v, ok := d.GetOk("resources"); ok && v.(*schema.Set).Len() > 0 { - input.Resources = flex.ExpandStringSet(v.(*schema.Set)) + input.Resources = flex.ExpandStringValueSet(v.(*schema.Set)) } - log.Printf("[DEBUG] Creating Internet Monitor Monitor: %s", input) - _, err := conn.CreateMonitorWithContext(ctx, input) + if v, ok := d.GetOk("traffic_percentage_to_monitor"); ok { + input.TrafficPercentageToMonitor = int32(v.(int)) + } + + _, err := conn.CreateMonitor(ctx, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "creating Internet Monitor Monitor (%s): %s", monitorName, err) + return sdkdiag.AppendErrorf(diags, "creating Internet Monitor Monitor (%s): %s", name, err) } - d.SetId(monitorName) + d.SetId(name) - if err := waitMonitor(ctx, conn, monitorName, internetmonitor.MonitorConfigStateActive); err != nil { + if err := waitMonitor(ctx, conn, d.Id(), types.MonitorConfigStateActive); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for Internet Monitor Monitor (%s) create: %s", d.Id(), err) } - if v, ok := d.GetOk("status"); ok && v.(string) != internetmonitor.MonitorConfigStateActive { - input := &internetmonitor.UpdateMonitorInput{ - ClientToken: aws.String(id.UniqueId()), - MonitorName: aws.String(d.Id()), - Status: aws.String(v.(string)), - } + if v, ok := d.GetOk("status"); ok { + if v := types.MonitorConfigState(v.(string)); v != types.MonitorConfigStateActive { + input := &internetmonitor.UpdateMonitorInput{ + ClientToken: aws.String(id.UniqueId()), + MonitorName: aws.String(d.Id()), + Status: v, + } - _, err := conn.UpdateMonitorWithContext(ctx, input) + _, err := conn.UpdateMonitor(ctx, input) - if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Internet Monitor Monitor (%s) to inactive at creation: %s", d.Id(), err) + if err != nil { + return sdkdiag.AppendErrorf(diags, "updating Internet Monitor Monitor (%s): %s", d.Id(), err) + } + + if err := waitMonitor(ctx, conn, d.Id(), v); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Internet Monitor Monitor (%s) INACTIVE: %s", d.Id(), err) + } } } @@ -171,9 +209,9 @@ func resourceMonitorCreate(ctx context.Context, d *schema.ResourceData, meta int func resourceMonitorRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).InternetMonitorConn(ctx) + conn := meta.(*conns.AWSClient).InternetMonitorClient(ctx) - monitor, err := FindMonitor(ctx, conn, d.Id()) + monitor, err := findMonitorByName(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] Internet Monitor Monitor (%s) not found, removing from state", d.Id()) @@ -185,17 +223,18 @@ func resourceMonitorRead(ctx context.Context, d *schema.ResourceData, meta inter return sdkdiag.AppendErrorf(diags, "reading Internet Monitor Monitor (%s): %s", d.Id(), err) } - err = d.Set("internet_measurements_log_delivery", flattenInternetMeasurementsLogDelivery(monitor.InternetMeasurementsLogDelivery)) - if err != nil { + d.Set("arn", monitor.MonitorArn) + if err := d.Set("health_events_config", flattenHealthEventsConfig(monitor.HealthEventsConfig)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting health_events_config: %s", err) + } + if err := d.Set("internet_measurements_log_delivery", flattenInternetMeasurementsLogDelivery(monitor.InternetMeasurementsLogDelivery)); err != nil { return sdkdiag.AppendErrorf(diags, "setting internet_measurements_log_delivery: %s", err) } - - d.Set("arn", monitor.MonitorArn) d.Set("monitor_name", monitor.MonitorName) d.Set("max_city_networks_to_monitor", monitor.MaxCityNetworksToMonitor) - d.Set("traffic_percentage_to_monitor", monitor.TrafficPercentageToMonitor) + d.Set("resources", flex.FlattenStringValueSet(monitor.Resources)) d.Set("status", monitor.Status) - d.Set("resources", flex.FlattenStringSet(monitor.Resources)) + d.Set("traffic_percentage_to_monitor", monitor.TrafficPercentageToMonitor) setTagsOut(ctx, monitor.Tags) @@ -204,7 +243,7 @@ func resourceMonitorRead(ctx context.Context, d *schema.ResourceData, meta inter func resourceMonitorUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).InternetMonitorConn(ctx) + conn := meta.(*conns.AWSClient).InternetMonitorClient(ctx) if d.HasChangesExcept("tags", "tags_all") { input := &internetmonitor.UpdateMonitorInput{ @@ -212,46 +251,46 @@ func resourceMonitorUpdate(ctx context.Context, d *schema.ResourceData, meta int MonitorName: aws.String(d.Id()), } - if d.HasChange("max_city_networks_to_monitor") { - input.MaxCityNetworksToMonitor = aws.Int64(int64(d.Get("max_city_networks_to_monitor").(int))) - } - - if d.HasChange("traffic_percentage_to_monitor") { - input.TrafficPercentageToMonitor = aws.Int64(int64(d.Get("traffic_percentage_to_monitor").(int))) - } - - if d.HasChange("status") { - input.Status = aws.String(d.Get("status").(string)) + if d.HasChange("health_events_config") { + input.HealthEventsConfig = expandHealthEventsConfig(d.Get("health_events_config").([]interface{})) } if d.HasChange("internet_measurements_log_delivery") { input.InternetMeasurementsLogDelivery = expandInternetMeasurementsLogDelivery(d.Get("internet_measurements_log_delivery").([]interface{})) } + if d.HasChange("max_city_networks_to_monitor") { + input.MaxCityNetworksToMonitor = int32(d.Get("max_city_networks_to_monitor").(int)) + } + if d.HasChange("resources") { o, n := d.GetChange("resources") os, ns := o.(*schema.Set), n.(*schema.Set) - remove := flex.ExpandStringValueSet(os.Difference(ns)) - add := flex.ExpandStringValueSet(ns.Difference(os)) - - if len(add) > 0 { - input.ResourcesToAdd = aws.StringSlice(add) + if add := flex.ExpandStringValueSet(ns.Difference(os)); len(add) > 0 { + input.ResourcesToAdd = add } - - if len(remove) > 0 { - input.ResourcesToRemove = aws.StringSlice(remove) + if remove := flex.ExpandStringValueSet(os.Difference(ns)); len(remove) > 0 { + input.ResourcesToRemove = remove } } - log.Printf("[DEBUG] Updating Internet Monitor Monitor: %s", input) - _, err := conn.UpdateMonitorWithContext(ctx, input) + status := types.MonitorConfigState(d.Get("status").(string)) + if d.HasChange("status") { + input.Status = status + } + + if d.HasChange("traffic_percentage_to_monitor") { + input.TrafficPercentageToMonitor = int32(d.Get("traffic_percentage_to_monitor").(int)) + } + + _, err := conn.UpdateMonitor(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating Internet Monitor Monitor (%s): %s", d.Id(), err) } - if err := waitMonitor(ctx, conn, d.Id(), d.Get("status").(string)); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Internet Monitor Monitor (%s) update: %s", d.Id(), err) + if err := waitMonitor(ctx, conn, d.Id(), status); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Internet Monitor Monitor (%s) %s: %s", d.Id(), status, err) } } @@ -260,30 +299,36 @@ func resourceMonitorUpdate(ctx context.Context, d *schema.ResourceData, meta int func resourceMonitorDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).InternetMonitorConn(ctx) + conn := meta.(*conns.AWSClient).InternetMonitorClient(ctx) input := &internetmonitor.UpdateMonitorInput{ ClientToken: aws.String(id.UniqueId()), MonitorName: aws.String(d.Id()), - Status: aws.String(internetmonitor.MonitorConfigStateInactive), + Status: types.MonitorConfigStateInactive, } - _, err := conn.UpdateMonitorWithContext(ctx, input) + _, err := conn.UpdateMonitor(ctx, input) + + // if errs.IsA[*types.ResourceNotFoundException](err) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { + return diags + } if err != nil { - return sdkdiag.AppendErrorf(diags, "updating Internet Monitor Monitor (%s) to inactive before deletion: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "updating Internet Monitor Monitor (%s): %s", d.Id(), err) } - if err := waitMonitor(ctx, conn, d.Id(), internetmonitor.MonitorConfigStateInactive); err != nil { - return sdkdiag.AppendErrorf(diags, "waiting for Internet Monitor Monitor (%s) to be inactive before deletion: %s", d.Id(), err) + if err := waitMonitor(ctx, conn, d.Id(), types.MonitorConfigStateInactive); err != nil { + return sdkdiag.AppendErrorf(diags, "waiting for Internet Monitor Monitor (%s) INACTIVE: %s", d.Id(), err) } log.Printf("[DEBUG] Deleting Internet Monitor Monitor: %s", d.Id()) - _, err = conn.DeleteMonitorWithContext(ctx, &internetmonitor.DeleteMonitorInput{ + _, err = conn.DeleteMonitor(ctx, &internetmonitor.DeleteMonitorInput{ MonitorName: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, internetmonitor.ErrCodeNotFoundException) { + // if errs.IsA[*types.ResourceNotFoundException](err) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { return diags } @@ -294,72 +339,168 @@ func resourceMonitorDelete(ctx context.Context, d *schema.ResourceData, meta int return diags } -func expandInternetMeasurementsLogDelivery(vInternetMeasurementsLogDelivery []interface{}) *internetmonitor.InternetMeasurementsLogDelivery { - if len(vInternetMeasurementsLogDelivery) == 0 || vInternetMeasurementsLogDelivery[0] == nil { +func findMonitorByName(ctx context.Context, conn *internetmonitor.Client, name string) (*internetmonitor.GetMonitorOutput, error) { + input := &internetmonitor.GetMonitorInput{ + MonitorName: aws.String(name), + } + + output, err := conn.GetMonitor(ctx, input) + + // if errs.IsA[*types.ResourceNotFoundException](err) { + if tfawserr.ErrCodeEquals(err, errCodeResourceNotFoundException) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} + +func statusMonitor(ctx context.Context, conn *internetmonitor.Client, name string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + monitor, err := findMonitorByName(ctx, conn, name) + + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return monitor, string(monitor.Status), nil + } +} + +func waitMonitor(ctx context.Context, conn *internetmonitor.Client, name string, targetState types.MonitorConfigState) error { + const ( + timeout = 5 * time.Minute + ) + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(types.MonitorConfigStatePending), + Target: enum.Slice(targetState), + Refresh: statusMonitor(ctx, conn, name), + Timeout: timeout, + Delay: 10 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + + if output, ok := outputRaw.(*internetmonitor.GetMonitorOutput); ok { + if status := output.Status; status == types.MonitorConfigStateError { + tfresource.SetLastError(err, errors.New(aws.ToString(output.ProcessingStatusInfo))) + } + + return err + } + + return err +} + +func expandHealthEventsConfig(tfList []interface{}) *types.HealthEventsConfig { + if len(tfList) == 0 || tfList[0] == nil { + return nil + } + + tfMap := tfList[0].(map[string]interface{}) + apiObject := &types.HealthEventsConfig{} + + if v, ok := tfMap["availability_score_threshold"].(float64); ok && v != 0.0 { + apiObject.AvailabilityScoreThreshold = v + } + + if v, ok := tfMap["performance_score_threshold"].(float64); ok && v != 0.0 { + apiObject.PerformanceScoreThreshold = v + } + + return apiObject +} + +func expandInternetMeasurementsLogDelivery(tfList []interface{}) *types.InternetMeasurementsLogDelivery { + if len(tfList) == 0 || tfList[0] == nil { return nil } - mInternetMeasurementsLogDelivery := vInternetMeasurementsLogDelivery[0].(map[string]interface{}) - logDelivery := &internetmonitor.InternetMeasurementsLogDelivery{} + tfMap := tfList[0].(map[string]interface{}) + apiObject := &types.InternetMeasurementsLogDelivery{} - if v, ok := mInternetMeasurementsLogDelivery["s3_config"].([]interface{}); ok { - logDelivery.S3Config = expandS3Config(v) + if v, ok := tfMap["s3_config"].([]interface{}); ok { + apiObject.S3Config = expandS3Config(v) } - return logDelivery + return apiObject } -func expandS3Config(vS3Config []interface{}) *internetmonitor.S3Config { - if len(vS3Config) == 0 || vS3Config[0] == nil { +func expandS3Config(tfList []interface{}) *types.S3Config { + if len(tfList) == 0 || tfList[0] == nil { return nil } - mS3Config := vS3Config[0].(map[string]interface{}) - s3Config := &internetmonitor.S3Config{} + tfMap := tfList[0].(map[string]interface{}) + apiObject := &types.S3Config{} - if v, ok := mS3Config["bucket_name"].(string); ok && v != "" { - s3Config.BucketName = aws.String(v) + if v, ok := tfMap["bucket_name"].(string); ok && v != "" { + apiObject.BucketName = aws.String(v) } - if v, ok := mS3Config["bucket_prefix"].(string); ok && v != "" { - s3Config.BucketPrefix = aws.String(v) + if v, ok := tfMap["bucket_prefix"].(string); ok && v != "" { + apiObject.BucketPrefix = aws.String(v) } - if v, ok := mS3Config["log_delivery_status"].(string); ok && v != "" { - s3Config.LogDeliveryStatus = aws.String(v) + if v, ok := tfMap["log_delivery_status"].(string); ok && v != "" { + apiObject.LogDeliveryStatus = types.LogDeliveryStatus(v) } - return s3Config + return apiObject } -func flattenInternetMeasurementsLogDelivery(internetMeasurementsLogDelivery *internetmonitor.InternetMeasurementsLogDelivery) []interface{} { - if internetMeasurementsLogDelivery == nil { +func flattenHealthEventsConfig(apiObject *types.HealthEventsConfig) []interface{} { + if apiObject == nil { return []interface{}{} } - mInternetMeasurementsLogDelivery := map[string]interface{}{ - "s3_config": flattenS3Config(internetMeasurementsLogDelivery.S3Config), + tfMap := map[string]interface{}{ + "availability_score_threshold": apiObject.AvailabilityScoreThreshold, + "performance_score_threshold": apiObject.PerformanceScoreThreshold, } - return []interface{}{mInternetMeasurementsLogDelivery} + return []interface{}{tfMap} } -func flattenS3Config(s3Config *internetmonitor.S3Config) []interface{} { - if s3Config == nil { +func flattenInternetMeasurementsLogDelivery(apiObject *types.InternetMeasurementsLogDelivery) []interface{} { + if apiObject == nil { return []interface{}{} } - mS3Config := map[string]interface{}{ - "bucket_name": aws.StringValue(s3Config.BucketName), + tfMap := map[string]interface{}{ + "s3_config": flattenS3Config(apiObject.S3Config), + } + + return []interface{}{tfMap} +} + +func flattenS3Config(apiObject *types.S3Config) []interface{} { + if apiObject == nil { + return []interface{}{} } - if s3Config.BucketPrefix != nil { - mS3Config["bucket_prefix"] = aws.StringValue(s3Config.BucketPrefix) + tfMap := map[string]interface{}{ + "bucket_name": aws.ToString(apiObject.BucketName), + "log_delivery_status": string(apiObject.LogDeliveryStatus), } - if s3Config.LogDeliveryStatus != nil { - mS3Config["log_delivery_status"] = aws.StringValue(s3Config.LogDeliveryStatus) + if apiObject.BucketPrefix != nil { + tfMap["bucket_prefix"] = aws.ToString(apiObject.BucketPrefix) } - return []interface{}{mS3Config} + return []interface{}{tfMap} } diff --git a/internal/service/internetmonitor/monitor_test.go b/internal/service/internetmonitor/monitor_test.go index 51f91886ac3f..ca750e9cb512 100644 --- a/internal/service/internetmonitor/monitor_test.go +++ b/internal/service/internetmonitor/monitor_test.go @@ -6,7 +6,6 @@ import ( "regexp" "testing" - "github.com/aws/aws-sdk-go/service/internetmonitor" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -14,6 +13,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" tfinternetmonitor "github.com/hashicorp/terraform-provider-aws/internal/service/internetmonitor" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccInternetMonitorMonitor_basic(t *testing.T) { @@ -23,19 +23,23 @@ func TestAccInternetMonitorMonitor_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, internetmonitor.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.InternetMonitorEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckMonitorDestroy(ctx), Steps: []resource.TestStep{ { Config: testAccMonitorConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckMonitorExists(ctx, resourceName), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "internetmonitor", regexp.MustCompile(`monitor/.+$`)), + resource.TestCheckResourceAttr(resourceName, "health_events_config.#", "0"), + resource.TestCheckResourceAttr(resourceName, "internet_measurements_log_delivery.#", "1"), + resource.TestCheckResourceAttr(resourceName, "max_city_networks_to_monitor", "0"), resource.TestCheckResourceAttr(resourceName, "monitor_name", rName), - resource.TestCheckResourceAttr(resourceName, "traffic_percentage_to_monitor", "1"), + resource.TestCheckResourceAttr(resourceName, "resources.#", "0"), resource.TestCheckResourceAttr(resourceName, "status", "ACTIVE"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, "traffic_percentage_to_monitor", "1"), ), }, { @@ -54,75 +58,92 @@ func TestAccInternetMonitorMonitor_basic(t *testing.T) { }) } -func TestAccInternetMonitorMonitor_log(t *testing.T) { +func TestAccInternetMonitorMonitor_disappears(t *testing.T) { ctx := acctest.Context(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_internetmonitor_monitor.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, internetmonitor.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.InternetMonitorEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckMonitorDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccMonitorConfig_log(rName), + Config: testAccMonitorConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckMonitorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "internet_measurements_log_delivery.#", "1"), - resource.TestCheckResourceAttr(resourceName, "internet_measurements_log_delivery.0.s3_config.#", "1"), - resource.TestCheckResourceAttr(resourceName, "internet_measurements_log_delivery.0.s3_config.0.bucket_name", rName), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfinternetmonitor.ResourceMonitor(), resourceName), ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ExpectNonEmptyPlan: true, }, }, }) } -func TestAccInternetMonitorMonitor_disappears(t *testing.T) { +func TestAccInternetMonitorMonitor_tags(t *testing.T) { ctx := acctest.Context(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_internetmonitor_monitor.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, internetmonitor.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.InternetMonitorEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckMonitorDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccMonitorConfig_basic(rName), + Config: testAccMonitorConfig_tags1(rName, "key1", "value1"), Check: resource.ComposeTestCheckFunc( testAccCheckMonitorExists(ctx, resourceName), - acctest.CheckResourceDisappears(ctx, acctest.Provider, tfinternetmonitor.ResourceMonitor(), resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccMonitorConfig_tags2(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMonitorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccMonitorConfig_tags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckMonitorExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), ), - ExpectNonEmptyPlan: true, }, }, }) } -func TestAccInternetMonitorMonitor_tags(t *testing.T) { +func TestAccInternetMonitorMonitor_healthEventsConfig(t *testing.T) { ctx := acctest.Context(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_internetmonitor_monitor.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, internetmonitor.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.InternetMonitorEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckMonitorDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccMonitorConfig_tags1(rName, "key1", "value1"), + Config: testAccMonitorConfig_healthEventsConfig(rName), Check: resource.ComposeTestCheckFunc( testAccCheckMonitorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), - resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + resource.TestCheckResourceAttr(resourceName, "health_events_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "health_events_config.0.availability_score_threshold", "50"), + resource.TestCheckResourceAttr(resourceName, "health_events_config.0.performance_score_threshold", "95"), ), }, { @@ -131,36 +152,57 @@ func TestAccInternetMonitorMonitor_tags(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccMonitorConfig_tags2(rName, "key1", "value1updated", "key2", "value2"), + Config: testAccMonitorConfig_healthEventsConfigUpdated(rName), Check: resource.ComposeTestCheckFunc( testAccCheckMonitorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), - resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), - resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + resource.TestCheckResourceAttr(resourceName, "health_events_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "health_events_config.0.availability_score_threshold", "75"), + resource.TestCheckResourceAttr(resourceName, "health_events_config.0.performance_score_threshold", "85"), ), }, + }, + }) +} + +func TestAccInternetMonitorMonitor_log(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_internetmonitor_monitor.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.InternetMonitorEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckMonitorDestroy(ctx), + Steps: []resource.TestStep{ { - Config: testAccMonitorConfig_tags1(rName, "key2", "value2"), + Config: testAccMonitorConfig_log(rName), Check: resource.ComposeTestCheckFunc( testAccCheckMonitorExists(ctx, resourceName), - resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), - resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + resource.TestCheckResourceAttr(resourceName, "internet_measurements_log_delivery.#", "1"), + resource.TestCheckResourceAttr(resourceName, "internet_measurements_log_delivery.0.s3_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "internet_measurements_log_delivery.0.s3_config.0.bucket_name", rName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } func testAccCheckMonitorDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).InternetMonitorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).InternetMonitorClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_internetmonitor_monitor" { continue } - _, err := tfinternetmonitor.FindMonitor(ctx, conn, rs.Primary.ID) + _, err := tfinternetmonitor.FindMonitorByName(ctx, conn, rs.Primary.ID) if tfresource.NotFound(err) { continue @@ -170,27 +212,23 @@ func testAccCheckMonitorDestroy(ctx context.Context) resource.TestCheckFunc { return err } - return fmt.Errorf("InternetMonitor Monitor %s still exists", rs.Primary.ID) + return fmt.Errorf("Internet Monitor Monitor %s still exists", rs.Primary.ID) } return nil } } -func testAccCheckMonitorExists(ctx context.Context, resourceName string) resource.TestCheckFunc { +func testAccCheckMonitorExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceName] + rs, ok := s.RootModule().Resources[n] if !ok { - return fmt.Errorf("Not found: %s", resourceName) + return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No InternetMonitor Monitor ID is set") - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).InternetMonitorConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).InternetMonitorClient(ctx) - _, err := tfinternetmonitor.FindMonitor(ctx, conn, rs.Primary.ID) + _, err := tfinternetmonitor.FindMonitorByName(ctx, conn, rs.Primary.ID) return err } @@ -215,6 +253,33 @@ resource "aws_internetmonitor_monitor" "test" { `, rName, status) } +func testAccMonitorConfig_healthEventsConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_internetmonitor_monitor" "test" { + monitor_name = %[1]q + max_city_networks_to_monitor = 2 + + health_events_config { + availability_score_threshold = 50 + } +} +`, rName) +} + +func testAccMonitorConfig_healthEventsConfigUpdated(rName string) string { + return fmt.Sprintf(` +resource "aws_internetmonitor_monitor" "test" { + monitor_name = %[1]q + max_city_networks_to_monitor = 2 + + health_events_config { + availability_score_threshold = 75 + performance_score_threshold = 85 + } +} +`, rName) +} + func testAccMonitorConfig_log(rName string) string { return fmt.Sprintf(` resource "aws_s3_bucket" "test" { diff --git a/internal/service/internetmonitor/service_package_gen.go b/internal/service/internetmonitor/service_package_gen.go index d478f2a9cf68..2ea6b068201b 100644 --- a/internal/service/internetmonitor/service_package_gen.go +++ b/internal/service/internetmonitor/service_package_gen.go @@ -5,9 +5,8 @@ package internetmonitor import ( "context" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" - internetmonitor_sdkv1 "github.com/aws/aws-sdk-go/service/internetmonitor" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + internetmonitor_sdkv2 "github.com/aws/aws-sdk-go-v2/service/internetmonitor" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -30,7 +29,7 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { return []*types.ServicePackageSDKResource{ { - Factory: ResourceMonitor, + Factory: resourceMonitor, TypeName: "aws_internetmonitor_monitor", Name: "Monitor", Tags: &types.ServicePackageResourceTags{ @@ -44,11 +43,15 @@ func (p *servicePackage) ServicePackageName() string { return names.InternetMonitor } -// NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. -func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*internetmonitor_sdkv1.InternetMonitor, error) { - sess := config["session"].(*session_sdkv1.Session) +// NewClient returns a new AWS SDK for Go v2 client for this service package's AWS API. +func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*internetmonitor_sdkv2.Client, error) { + cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return internetmonitor_sdkv1.New(sess.Copy(&aws_sdkv1.Config{Endpoint: aws_sdkv1.String(config["endpoint"].(string))})), nil + return internetmonitor_sdkv2.NewFromConfig(cfg, func(o *internetmonitor_sdkv2.Options) { + if endpoint := config["endpoint"].(string); endpoint != "" { + o.EndpointResolver = internetmonitor_sdkv2.EndpointResolverFromURL(endpoint) + } + }), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/internetmonitor/status.go b/internal/service/internetmonitor/status.go deleted file mode 100644 index 9ec045172486..000000000000 --- a/internal/service/internetmonitor/status.go +++ /dev/null @@ -1,26 +0,0 @@ -package internetmonitor - -import ( - "context" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/internetmonitor" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" -) - -func statusMonitor(ctx context.Context, conn *internetmonitor.InternetMonitor, name string) retry.StateRefreshFunc { - return func() (interface{}, string, error) { - monitor, err := FindMonitor(ctx, conn, name) - - if tfresource.NotFound(err) { - return nil, "", nil - } - - if err != nil { - return nil, "", err - } - - return monitor, aws.StringValue(monitor.Status), nil - } -} diff --git a/internal/service/internetmonitor/sweep.go b/internal/service/internetmonitor/sweep.go index fb08a6969ec4..b92c5eda4acf 100644 --- a/internal/service/internetmonitor/sweep.go +++ b/internal/service/internetmonitor/sweep.go @@ -7,9 +7,8 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/internetmonitor" - "github.com/hashicorp/go-multierror" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/internetmonitor" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" ) @@ -24,45 +23,40 @@ func init() { func sweepMonitors(region string) error { ctx := sweep.Context(region) client, err := sweep.SharedRegionalSweepClient(ctx, region) - if err != nil { return fmt.Errorf("error getting client: %s", err) } - - conn := client.InternetMonitorConn(ctx) + input := &internetmonitor.ListMonitorsInput{} + conn := client.InternetMonitorClient(ctx) sweepResources := make([]sweep.Sweepable, 0) - var errs *multierror.Error - err = conn.ListMonitorsPagesWithContext(ctx, &internetmonitor.ListMonitorsInput{}, func(resp *internetmonitor.ListMonitorsOutput, lastPage bool) bool { - if len(resp.Monitors) == 0 { - log.Print("[DEBUG] No InternetMonitor Monitors to sweep") - return !lastPage + pages := internetmonitor.NewListMonitorsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if sweep.SkipSweepError(err) { + log.Printf("[WARN] Skipping Internet Monitor Monitor sweep for %s: %s", region, err) + return nil } - for _, c := range resp.Monitors { - r := ResourceMonitor() + if err != nil { + return fmt.Errorf("error listing Internet Monitor Monitors (%s): %w", region, err) + } + + for _, v := range page.Monitors { + r := resourceMonitor() d := r.Data(nil) - d.SetId(aws.StringValue(c.MonitorName)) + d.SetId(aws.ToString(v.MonitorName)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if err != nil { - errs = multierror.Append(errs, fmt.Errorf("error describing InternetMonitor Monitors: %w", err)) - // in case work can be done, don't jump out yet } - if err = sweep.SweepOrchestratorWithContext(ctx, sweepResources); err != nil { - errs = multierror.Append(errs, fmt.Errorf("error sweeping InternetMonitor Monitors for %s: %w", region, err)) - } + err = sweep.SweepOrchestratorWithContext(ctx, sweepResources) - if sweep.SkipSweepError(errs.ErrorOrNil()) { - log.Printf("[WARN] Skipping InternetMonitor Monitor sweep for %s: %s", region, err) - return nil + if err != nil { + return fmt.Errorf("error sweeping Internet Monitor Monitors (%s): %w", region, err) } - return errs.ErrorOrNil() + return nil } diff --git a/internal/service/internetmonitor/tags_gen.go b/internal/service/internetmonitor/tags_gen.go index 40ed211fd83d..842a8996f713 100644 --- a/internal/service/internetmonitor/tags_gen.go +++ b/internal/service/internetmonitor/tags_gen.go @@ -5,9 +5,8 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/internetmonitor" - "github.com/aws/aws-sdk-go/service/internetmonitor/internetmonitoriface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/internetmonitor" "github.com/hashicorp/terraform-provider-aws/internal/conns" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/types" @@ -17,12 +16,12 @@ import ( // listTags lists internetmonitor service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func listTags(ctx context.Context, conn internetmonitoriface.InternetMonitorAPI, identifier string) (tftags.KeyValueTags, error) { +func listTags(ctx context.Context, conn *internetmonitor.Client, identifier string) (tftags.KeyValueTags, error) { input := &internetmonitor.ListTagsForResourceInput{ ResourceArn: aws.String(identifier), } - output, err := conn.ListTagsForResourceWithContext(ctx, input) + output, err := conn.ListTagsForResource(ctx, input) if err != nil { return tftags.New(ctx, nil), err @@ -34,7 +33,7 @@ func listTags(ctx context.Context, conn internetmonitoriface.InternetMonitorAPI, // ListTags lists internetmonitor service tags and set them in Context. // It is called from outside this package. func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier string) error { - tags, err := listTags(ctx, meta.(*conns.AWSClient).InternetMonitorConn(ctx), identifier) + tags, err := listTags(ctx, meta.(*conns.AWSClient).InternetMonitorClient(ctx), identifier) if err != nil { return err @@ -47,21 +46,21 @@ func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier stri return nil } -// map[string]*string handling +// map[string]string handling // Tags returns internetmonitor service tags. -func Tags(tags tftags.KeyValueTags) map[string]*string { - return aws.StringMap(tags.Map()) +func Tags(tags tftags.KeyValueTags) map[string]string { + return tags.Map() } // KeyValueTags creates tftags.KeyValueTags from internetmonitor service tags. -func KeyValueTags(ctx context.Context, tags map[string]*string) tftags.KeyValueTags { +func KeyValueTags(ctx context.Context, tags map[string]string) tftags.KeyValueTags { return tftags.New(ctx, tags) } // getTagsIn returns internetmonitor service tags from Context. // nil is returned if there are no input tags. -func getTagsIn(ctx context.Context) map[string]*string { +func getTagsIn(ctx context.Context) map[string]string { if inContext, ok := tftags.FromContext(ctx); ok { if tags := Tags(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { return tags @@ -72,7 +71,7 @@ func getTagsIn(ctx context.Context) map[string]*string { } // setTagsOut sets internetmonitor service tags in Context. -func setTagsOut(ctx context.Context, tags map[string]*string) { +func setTagsOut(ctx context.Context, tags map[string]string) { if inContext, ok := tftags.FromContext(ctx); ok { inContext.TagsOut = types.Some(KeyValueTags(ctx, tags)) } @@ -81,7 +80,7 @@ func setTagsOut(ctx context.Context, tags map[string]*string) { // updateTags updates internetmonitor service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func updateTags(ctx context.Context, conn internetmonitoriface.InternetMonitorAPI, identifier string, oldTagsMap, newTagsMap any) error { +func updateTags(ctx context.Context, conn *internetmonitor.Client, identifier string, oldTagsMap, newTagsMap any) error { oldTags := tftags.New(ctx, oldTagsMap) newTags := tftags.New(ctx, newTagsMap) @@ -90,10 +89,10 @@ func updateTags(ctx context.Context, conn internetmonitoriface.InternetMonitorAP if len(removedTags) > 0 { input := &internetmonitor.UntagResourceInput{ ResourceArn: aws.String(identifier), - TagKeys: aws.StringSlice(removedTags.Keys()), + TagKeys: removedTags.Keys(), } - _, err := conn.UntagResourceWithContext(ctx, input) + _, err := conn.UntagResource(ctx, input) if err != nil { return fmt.Errorf("untagging resource (%s): %w", identifier, err) @@ -108,7 +107,7 @@ func updateTags(ctx context.Context, conn internetmonitoriface.InternetMonitorAP Tags: Tags(updatedTags), } - _, err := conn.TagResourceWithContext(ctx, input) + _, err := conn.TagResource(ctx, input) if err != nil { return fmt.Errorf("tagging resource (%s): %w", identifier, err) @@ -121,5 +120,5 @@ func updateTags(ctx context.Context, conn internetmonitoriface.InternetMonitorAP // UpdateTags updates internetmonitor service tags. // It is called from outside this package. func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { - return updateTags(ctx, meta.(*conns.AWSClient).InternetMonitorConn(ctx), identifier, oldTags, newTags) + return updateTags(ctx, meta.(*conns.AWSClient).InternetMonitorClient(ctx), identifier, oldTags, newTags) } diff --git a/internal/service/internetmonitor/wait.go b/internal/service/internetmonitor/wait.go deleted file mode 100644 index cc4a7d770063..000000000000 --- a/internal/service/internetmonitor/wait.go +++ /dev/null @@ -1,38 +0,0 @@ -package internetmonitor - -import ( - "context" - "errors" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/internetmonitor" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/tfresource" -) - -const ( - monitorCreatedTimeout = 5 * time.Minute -) - -func waitMonitor(ctx context.Context, conn *internetmonitor.InternetMonitor, name, target string) error { - stateConf := &retry.StateChangeConf{ - Pending: []string{internetmonitor.MonitorConfigStatePending}, - Target: []string{target}, - Refresh: statusMonitor(ctx, conn, name), - Timeout: monitorCreatedTimeout, - Delay: 10 * time.Second, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - - if output, ok := outputRaw.(*internetmonitor.GetMonitorOutput); ok { - if statusCode := aws.StringValue(output.Status); statusCode == internetmonitor.MonitorConfigStateError { - tfresource.SetLastError(err, errors.New(aws.StringValue(output.ProcessingStatusInfo))) - } - - return err - } - - return err -} diff --git a/names/names.go b/names/names.go index 201b2533c9b8..e52ca94b27da 100644 --- a/names/names.go +++ b/names/names.go @@ -33,6 +33,7 @@ const ( GlacierEndpointID = "glacier" IdentityStoreEndpointID = "identitystore" Inspector2EndpointID = "inspector2" + InternetMonitorEndpointID = "internetmonitor" IVSChatEndpointID = "ivschat" KendraEndpointID = "kendra" KeyspacesEndpointID = "keyspaces" diff --git a/names/names_data.csv b/names/names_data.csv index 1c9ffb5bffe9..d4912ce921f1 100644 --- a/names/names_data.csv +++ b/names/names_data.csv @@ -68,7 +68,7 @@ cloudtrail,cloudtrail,cloudtrail,cloudtrail,,cloudtrail,,,CloudTrail,CloudTrail, cloudwatch,cloudwatch,cloudwatch,cloudwatch,,cloudwatch,,,CloudWatch,CloudWatch,,1,,aws_cloudwatch_(?!(event_|log_|query_)),aws_cloudwatch_,,cloudwatch_dashboard;cloudwatch_metric_;cloudwatch_composite_,CloudWatch,Amazon,,,,, application-insights,applicationinsights,applicationinsights,applicationinsights,,applicationinsights,,,ApplicationInsights,ApplicationInsights,,1,,,aws_applicationinsights_,,applicationinsights_,CloudWatch Application Insights,Amazon,,,,, evidently,evidently,cloudwatchevidently,evidently,,evidently,,cloudwatchevidently,Evidently,CloudWatchEvidently,,1,,,aws_evidently_,,evidently_,CloudWatch Evidently,Amazon,,,,, -internetmonitor,internetmonitor,internetmonitor,internetmonitor,,internetmonitor,,,InternetMonitor,InternetMonitor,,1,,,aws_internetmonitor_,,internetmonitor_,CloudWatch Internet Monitor,Amazon,,,,, +internetmonitor,internetmonitor,internetmonitor,internetmonitor,,internetmonitor,,,InternetMonitor,InternetMonitor,,,2,,aws_internetmonitor_,,internetmonitor_,CloudWatch Internet Monitor,Amazon,,,,, logs,logs,cloudwatchlogs,cloudwatchlogs,,logs,,cloudwatchlog;cloudwatchlogs,Logs,CloudWatchLogs,,1,2,aws_cloudwatch_(log_|query_),aws_logs_,,cloudwatch_log_;cloudwatch_query_,CloudWatch Logs,Amazon,,,,, rum,rum,cloudwatchrum,rum,,rum,,cloudwatchrum,RUM,CloudWatchRUM,,1,,,aws_rum_,,rum_,CloudWatch RUM,Amazon,,,,, synthetics,synthetics,synthetics,synthetics,,synthetics,,,Synthetics,Synthetics,,1,,,aws_synthetics_,,synthetics_,CloudWatch Synthetics,Amazon,,,,, diff --git a/website/docs/r/internetmonitor_monitor.html.markdown b/website/docs/r/internetmonitor_monitor.html.markdown index 2c0da1616ce2..239224d9c6f9 100644 --- a/website/docs/r/internetmonitor_monitor.html.markdown +++ b/website/docs/r/internetmonitor_monitor.html.markdown @@ -26,13 +26,21 @@ The following arguments are required: The following arguments are optional: +* `health_events_config` - (Optional) Health event thresholds. A health event threshold percentage, for performance and availability, determines when Internet Monitor creates a health event when there's an internet issue that affects your application end users. See [Health Events Config](#health-events-config) below. * `internet_measurements_log_delivery` - (Optional) Publish internet measurements for Internet Monitor to an Amazon S3 bucket in addition to CloudWatch Logs. * `max_city_networks_to_monitor` - (Optional) The maximum number of city-networks to monitor for your resources. A city-network is the location (city) where clients access your application resources from and the network or ASN, such as an internet service provider (ISP), that clients access the resources through. This limit helps control billing costs. -* `resources` - (Optional)The resources to include in a monitor, which you provide as a set of Amazon Resource Names (ARNs). +* `resources` - (Optional) The resources to include in a monitor, which you provide as a set of Amazon Resource Names (ARNs). * `status` - (Optional) The status for a monitor. The accepted values for Status with the UpdateMonitor API call are the following: `ACTIVE` and `INACTIVE`. * `tags` - (Optional) Map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. * `traffic_percentage_to_monitor` - (Optional) The percentage of the internet-facing traffic for your application that you want to monitor with this monitor. +### Health Events Config + +Defines the health event threshold percentages, for performance score and availability score. Amazon CloudWatch Internet Monitor creates a health event when there's an internet issue that affects your application end users where a health score percentage is at or below a set threshold. If you don't set a health event threshold, the default value is 95%. + +* `availability_score_threshold` - (Optional) The health event threshold percentage set for availability scores. +* `performance_score_threshold` - (Optional) The health event threshold percentage set for performance scores. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: