From dbb01edddf5711966d6492e1c29945f40cda3614 Mon Sep 17 00:00:00 2001 From: Ahmed Bebars Date: Wed, 16 Dec 2020 02:38:07 -0500 Subject: [PATCH 01/22] Feature: AWSConnectInstance Resource --- aws/data_source_aws_connect_instance.go | 215 ++++ aws/data_source_aws_connect_instance_test.go | 114 ++ aws/internal/service/connect/waiter/status.go | 27 + aws/internal/service/connect/waiter/waiter.go | 31 + aws/provider.go | 1132 +++++++++-------- aws/resource_aws_connect_instance.go | 284 +++++ aws/resource_aws_connect_instance_test.go | 346 +++++ website/docs/d/connect_instance.html.markdown | 55 + website/docs/r/connect_instance.html.markdown | 54 + 9 files changed, 1693 insertions(+), 565 deletions(-) create mode 100644 aws/data_source_aws_connect_instance.go create mode 100644 aws/data_source_aws_connect_instance_test.go create mode 100644 aws/internal/service/connect/waiter/status.go create mode 100644 aws/internal/service/connect/waiter/waiter.go create mode 100644 aws/resource_aws_connect_instance.go create mode 100644 aws/resource_aws_connect_instance_test.go create mode 100644 website/docs/d/connect_instance.html.markdown create mode 100644 website/docs/r/connect_instance.html.markdown diff --git a/aws/data_source_aws_connect_instance.go b/aws/data_source_aws_connect_instance.go new file mode 100644 index 00000000000..1583fa6c381 --- /dev/null +++ b/aws/data_source_aws_connect_instance.go @@ -0,0 +1,215 @@ +package aws + +import ( + "context" + "errors" + "fmt" + "log" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/connect" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var dataResourceConnectInstanceAttributesMapping = map[string]string{ + connect.InstanceAttributeTypeInboundCalls: "inbound_calls_enabled", + connect.InstanceAttributeTypeOutboundCalls: "outbound_calls_enabled", + connect.InstanceAttributeTypeContactflowLogs: "contact_flow_logs_enabled", + connect.InstanceAttributeTypeContactLens: "contact_lens_enabled", + connect.InstanceAttributeTypeAutoResolveBestVoices: "auto_resolve_best_voices", + connect.InstanceAttributeTypeUseCustomTtsVoices: "use_custom_tts_voices", + connect.InstanceAttributeTypeEarlyMedia: "early_media_enabled", +} + +func dataSourceAwsConnectInstance() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceAwsConnectInstanceRead, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "instance_alias": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "created_time": { + Type: schema.TypeString, + Computed: true, + }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "identity_management_type": { + Type: schema.TypeString, + Computed: true, + }, + "inbound_calls_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "outbound_calls_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "early_media_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "contact_flow_logs_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "contact_lens_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "auto_resolve_best_voices": { + Type: schema.TypeBool, + Computed: true, + }, + "use_custom_tts_voices": { + Type: schema.TypeBool, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "service_role": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).connectconn + + var matchedInstance *connect.Instance + + instanceId, instanceIdOk := d.GetOk("instance_id") + instanceAlias, instanceAliasOk := d.GetOk("instance_alias") + + if !instanceIdOk && !instanceAliasOk { + return diag.FromErr(errors.New("error one instance_id or instance_alias of must be assigned")) + } + + if instanceIdOk { + input := connect.DescribeInstanceInput{ + InstanceId: aws.String(instanceId.(string)), + } + + log.Printf("[DEBUG] Reading Connect Instance by instance_id: %s", input) + + output, err := conn.DescribeInstance(&input) + + if err != nil { + return diag.FromErr(fmt.Errorf("error getting Connect Instance by instance_id (%s): %s", instanceId, err)) + } + + matchedInstance = output.Instance + + } else if instanceAliasOk { + instanceSummaryList, err := dataSourceAwsConnectGetAllConnectInstanceSummaries(ctx, conn) + if err != nil { + return diag.FromErr(fmt.Errorf("error listing Connect Instances: %s", err)) + } + + for _, instanceSummary := range instanceSummaryList { + log.Printf("[DEBUG] Connect Instance summary: %s", instanceSummary) + if aws.StringValue(instanceSummary.InstanceAlias) == instanceAlias.(string) { + + matchedInstance = &connect.Instance{ + Arn: instanceSummary.Arn, + CreatedTime: instanceSummary.CreatedTime, + Id: instanceSummary.Id, + IdentityManagementType: instanceSummary.IdentityManagementType, + InboundCallsEnabled: instanceSummary.InboundCallsEnabled, + InstanceAlias: instanceSummary.InstanceAlias, + InstanceStatus: instanceSummary.InstanceStatus, + OutboundCallsEnabled: instanceSummary.OutboundCallsEnabled, + ServiceRole: instanceSummary.ServiceRole, + } + break + } + } + } + + if matchedInstance == nil { + return diag.FromErr(fmt.Errorf("error finding Connect Instance by instance_alias: %s", instanceAlias)) + } + + d.SetId(aws.StringValue(matchedInstance.Id)) + + d.Set("arn", matchedInstance.Arn) + d.Set("created_time", matchedInstance.CreatedTime.Format(time.RFC3339)) + d.Set("identity_management_type", matchedInstance.IdentityManagementType) + d.Set("instance_alias", matchedInstance.InstanceAlias) + d.Set("inbound_calls_enabled", matchedInstance.InboundCallsEnabled) + d.Set("outbound_calls_enabled", matchedInstance.OutboundCallsEnabled) + d.Set("status", matchedInstance.InstanceStatus) + d.Set("service_role", matchedInstance.ServiceRole) + + for att := range dataResourceConnectInstanceAttributesMapping { + value, err := dataResourceAwsConnectInstanceReadAttribute(ctx, conn, d.Id(), att) + if err != nil { + return diag.FromErr(fmt.Errorf("error reading Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) + } + d.Set(resourceConnectInstanceAttributesMapping[att], value) + } + return nil +} + +func dataSourceAwsConnectGetAllConnectInstanceSummaries(ctx context.Context, conn *connect.Connect) ([]*connect.InstanceSummary, error) { + var instances []*connect.InstanceSummary + var nextToken string + + for { + input := &connect.ListInstancesInput{ + // MaxResults Valid Range: Minimum value of 1. Maximum value of 60 + MaxResults: aws.Int64(int64(60)), + } + if nextToken != "" { + input.NextToken = aws.String(nextToken) + } + + log.Printf("[DEBUG] Listing Connect Instances: %s", input) + + output, err := conn.ListInstancesWithContext(ctx, input) + if err != nil { + return instances, err + } + instances = append(instances, output.InstanceSummaryList...) + + if output.NextToken == nil { + break + } + nextToken = aws.StringValue(output.NextToken) + } + + return instances, nil +} + +func dataResourceAwsConnectInstanceReadAttribute(ctx context.Context, conn *connect.Connect, instanceID string, attributeType string) (bool, error) { + input := &connect.DescribeInstanceAttributeInput{ + InstanceId: aws.String(instanceID), + AttributeType: aws.String(attributeType), + } + + out, err := conn.DescribeInstanceAttributeWithContext(ctx, input) + + if err != nil { + return false, err + } + + result, parseerr := strconv.ParseBool(*out.Attribute.Value) + return result, parseerr +} diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go new file mode 100644 index 00000000000..2a4ed392c25 --- /dev/null +++ b/aws/data_source_aws_connect_instance_test.go @@ -0,0 +1,114 @@ +package aws + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { + rInt := acctest.RandInt() + resourceName := "aws_connect_instance.foo" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccAwsConnectInstanceDataSourceConfig_nonExistentId, + ExpectError: regexp.MustCompile(`error getting Connect Instance by instance_id`), + }, + { + Config: testAccAwsConnectInstanceDataSourceConfig_nonExistentAlias, + ExpectError: regexp.MustCompile(`error finding Connect Instance by instance_alias`), + }, + { + Config: testAccAwsConnectInstanceDataSourceConfigBasic(rInt), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "id"), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttrSet(resourceName, "identity_management_type"), + resource.TestCheckResourceAttrSet(resourceName, "instance_alias"), + resource.TestCheckResourceAttrSet(resourceName, "inbound_calls_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "outbound_calls_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "contact_lens_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices"), + resource.TestCheckResourceAttrSet(resourceName, "use_custom_tts_voices"), + resource.TestCheckResourceAttrSet(resourceName, "early_media_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "service_role"), + ), + }, + }, + }) +} + +func TestAccAwsConnectInstanceDataSource_alias(t *testing.T) { + rInt := acctest.RandInt() + resourceName := "aws_connect_instance.foo" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccAwsConnectInstanceDataSourceConfigAlias(rInt), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "id"), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttrSet(resourceName, "identity_management_type"), + resource.TestCheckResourceAttrSet(resourceName, "instance_alias"), + resource.TestCheckResourceAttrSet(resourceName, "inbound_calls_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "outbound_calls_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "contact_lens_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices"), + resource.TestCheckResourceAttrSet(resourceName, "use_custom_tts_voices"), + resource.TestCheckResourceAttrSet(resourceName, "early_media_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "service_role"), + ), + }, + }, + }) +} + +const testAccAwsConnectInstanceDataSourceConfig_nonExistentId = ` +data "aws_connect_instance" "foo" { + instance_id = "97afc98d-101a-ba98-ab97-ae114fc115ec" +} +` + +const testAccAwsConnectInstanceDataSourceConfig_nonExistentAlias = ` +data "aws_connect_instance" "foo" { + instance_alias = "tf-acc-test-does-not-exist" +} +` + +func testAccAwsConnectInstanceDataSourceConfigBasic(rInt int) string { + return fmt.Sprintf(` +resource "aws_connect_instance" "foo" { + instance_alias = "datasource-test-terraform-%d" +} + +data "aws_connect_instance" "foo" { + instance_id = aws_connect_instance.foo.id +} +`, rInt) +} + +func testAccAwsConnectInstanceDataSourceConfigAlias(rInt int) string { + return fmt.Sprintf(` +resource "aws_connect_instance" "foo" { + instance_alias = "datasource-test-terraform-%d" +} + +data "aws_connect_instance" "foo" { + instance_alias = aws_connect_instance.foo.instance_alias +} +`, rInt) +} diff --git a/aws/internal/service/connect/waiter/status.go b/aws/internal/service/connect/waiter/status.go new file mode 100644 index 00000000000..06e88977955 --- /dev/null +++ b/aws/internal/service/connect/waiter/status.go @@ -0,0 +1,27 @@ +package waiter + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/connect" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func InstanceStatus(ctx context.Context, conn *connect.Connect, instanceId string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + input := &connect.DescribeInstanceInput{ + InstanceId: aws.String(instanceId), + } + + output, err := conn.DescribeInstanceWithContext(ctx, input) + + if err != nil { + return nil, connect.ErrCodeResourceNotFoundException, err + } + + state := aws.StringValue(output.Instance.InstanceStatus) + + return output, state, nil + } +} diff --git a/aws/internal/service/connect/waiter/waiter.go b/aws/internal/service/connect/waiter/waiter.go new file mode 100644 index 00000000000..cfc41f94a2c --- /dev/null +++ b/aws/internal/service/connect/waiter/waiter.go @@ -0,0 +1,31 @@ +package waiter + +import ( + "context" + "time" + + "github.com/aws/aws-sdk-go/service/connect" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +const ( + // ConnectInstanceCreateTimeout Timeout for connect instance creation + ConnectInstanceCreateTimeout = 5 * time.Minute +) + +func InstanceCreated(ctx context.Context, conn *connect.Connect, instanceId string) (*connect.DescribeInstanceOutput, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{connect.InstanceStatusCreationInProgress}, + Target: []string{connect.InstanceStatusActive}, + Refresh: InstanceStatus(ctx, conn, instanceId), + Timeout: ConnectInstanceCreateTimeout, + } + + outputRaw, err := stateConf.WaitForState() + + if v, ok := outputRaw.(*connect.DescribeInstanceOutput); ok { + return v, err + } + + return nil, err +} diff --git a/aws/provider.go b/aws/provider.go index 40a8d993ba9..e5a29f68ae8 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -229,6 +229,7 @@ func Provider() *schema.Provider { "aws_cognito_user_pools": dataSourceAwsCognitoUserPools(), "aws_codecommit_repository": dataSourceAwsCodeCommitRepository(), "aws_codestarconnections_connection": dataSourceAwsCodeStarConnectionsConnection(), + "aws_connect_instance": dataSourceAwsConnectInstance(), "aws_cur_report_definition": dataSourceAwsCurReportDefinition(), "aws_default_tags": dataSourceAwsDefaultTags(), "aws_db_cluster_snapshot": dataSourceAwsDbClusterSnapshot(), @@ -464,571 +465,572 @@ func Provider() *schema.Provider { }, ResourcesMap: map[string]*schema.Resource{ - "aws_accessanalyzer_analyzer": resourceAwsAccessAnalyzerAnalyzer(), - "aws_acm_certificate": resourceAwsAcmCertificate(), - "aws_acm_certificate_validation": resourceAwsAcmCertificateValidation(), - "aws_acmpca_certificate_authority": resourceAwsAcmpcaCertificateAuthority(), - "aws_acmpca_certificate_authority_certificate": resourceAwsAcmpcaCertificateAuthorityCertificate(), - "aws_acmpca_certificate": resourceAwsAcmpcaCertificate(), - "aws_ami": resourceAwsAmi(), - "aws_ami_copy": resourceAwsAmiCopy(), - "aws_ami_from_instance": resourceAwsAmiFromInstance(), - "aws_ami_launch_permission": resourceAwsAmiLaunchPermission(), - "aws_amplify_app": resourceAwsAmplifyApp(), - "aws_amplify_backend_environment": resourceAwsAmplifyBackendEnvironment(), - "aws_amplify_branch": resourceAwsAmplifyBranch(), - "aws_amplify_domain_association": resourceAwsAmplifyDomainAssociation(), - "aws_amplify_webhook": resourceAwsAmplifyWebhook(), - "aws_api_gateway_account": resourceAwsApiGatewayAccount(), - "aws_api_gateway_api_key": resourceAwsApiGatewayApiKey(), - "aws_api_gateway_authorizer": resourceAwsApiGatewayAuthorizer(), - "aws_api_gateway_base_path_mapping": resourceAwsApiGatewayBasePathMapping(), - "aws_api_gateway_client_certificate": resourceAwsApiGatewayClientCertificate(), - "aws_api_gateway_deployment": resourceAwsApiGatewayDeployment(), - "aws_api_gateway_documentation_part": resourceAwsApiGatewayDocumentationPart(), - "aws_api_gateway_documentation_version": resourceAwsApiGatewayDocumentationVersion(), - "aws_api_gateway_domain_name": resourceAwsApiGatewayDomainName(), - "aws_api_gateway_gateway_response": resourceAwsApiGatewayGatewayResponse(), - "aws_api_gateway_integration": resourceAwsApiGatewayIntegration(), - "aws_api_gateway_integration_response": resourceAwsApiGatewayIntegrationResponse(), - "aws_api_gateway_method": resourceAwsApiGatewayMethod(), - "aws_api_gateway_method_response": resourceAwsApiGatewayMethodResponse(), - "aws_api_gateway_method_settings": resourceAwsApiGatewayMethodSettings(), - "aws_api_gateway_model": resourceAwsApiGatewayModel(), - "aws_api_gateway_request_validator": resourceAwsApiGatewayRequestValidator(), - "aws_api_gateway_resource": resourceAwsApiGatewayResource(), - "aws_api_gateway_rest_api": resourceAwsApiGatewayRestApi(), - "aws_api_gateway_rest_api_policy": resourceAwsApiGatewayRestApiPolicy(), - "aws_api_gateway_stage": resourceAwsApiGatewayStage(), - "aws_api_gateway_usage_plan": resourceAwsApiGatewayUsagePlan(), - "aws_api_gateway_usage_plan_key": resourceAwsApiGatewayUsagePlanKey(), - "aws_api_gateway_vpc_link": resourceAwsApiGatewayVpcLink(), - "aws_apigatewayv2_api": resourceAwsApiGatewayV2Api(), - "aws_apigatewayv2_api_mapping": resourceAwsApiGatewayV2ApiMapping(), - "aws_apigatewayv2_authorizer": resourceAwsApiGatewayV2Authorizer(), - "aws_apigatewayv2_deployment": resourceAwsApiGatewayV2Deployment(), - "aws_apigatewayv2_domain_name": resourceAwsApiGatewayV2DomainName(), - "aws_apigatewayv2_integration": resourceAwsApiGatewayV2Integration(), - "aws_apigatewayv2_integration_response": resourceAwsApiGatewayV2IntegrationResponse(), - "aws_apigatewayv2_model": resourceAwsApiGatewayV2Model(), - "aws_apigatewayv2_route": resourceAwsApiGatewayV2Route(), - "aws_apigatewayv2_route_response": resourceAwsApiGatewayV2RouteResponse(), - "aws_apigatewayv2_stage": resourceAwsApiGatewayV2Stage(), - "aws_apigatewayv2_vpc_link": resourceAwsApiGatewayV2VpcLink(), - "aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(), - "aws_appautoscaling_target": resourceAwsAppautoscalingTarget(), - "aws_appautoscaling_policy": resourceAwsAppautoscalingPolicy(), - "aws_appautoscaling_scheduled_action": resourceAwsAppautoscalingScheduledAction(), - "aws_appconfig_application": resourceAwsAppconfigApplication(), - "aws_appconfig_configuration_profile": resourceAwsAppconfigConfigurationProfile(), - "aws_appconfig_deployment": resourceAwsAppconfigDeployment(), - "aws_appconfig_deployment_strategy": resourceAwsAppconfigDeploymentStrategy(), - "aws_appconfig_environment": resourceAwsAppconfigEnvironment(), - "aws_appconfig_hosted_configuration_version": resourceAwsAppconfigHostedConfigurationVersion(), - "aws_appmesh_gateway_route": resourceAwsAppmeshGatewayRoute(), - "aws_appmesh_mesh": resourceAwsAppmeshMesh(), - "aws_appmesh_route": resourceAwsAppmeshRoute(), - "aws_appmesh_virtual_gateway": resourceAwsAppmeshVirtualGateway(), - "aws_appmesh_virtual_node": resourceAwsAppmeshVirtualNode(), - "aws_appmesh_virtual_router": resourceAwsAppmeshVirtualRouter(), - "aws_appmesh_virtual_service": resourceAwsAppmeshVirtualService(), - "aws_apprunner_auto_scaling_configuration_version": resourceAwsAppRunnerAutoScalingConfigurationVersion(), - "aws_apprunner_connection": resourceAwsAppRunnerConnection(), - "aws_apprunner_custom_domain_association": resourceAwsAppRunnerCustomDomainAssociation(), - "aws_apprunner_service": resourceAwsAppRunnerService(), - "aws_appstream_stack": resourceAwsAppStreamStack(), - "aws_appstream_fleet": resourceAwsAppStreamFleet(), - "aws_appsync_api_key": resourceAwsAppsyncApiKey(), - "aws_appsync_datasource": resourceAwsAppsyncDatasource(), - "aws_appsync_function": resourceAwsAppsyncFunction(), - "aws_appsync_graphql_api": resourceAwsAppsyncGraphqlApi(), - "aws_appsync_resolver": resourceAwsAppsyncResolver(), - "aws_athena_database": resourceAwsAthenaDatabase(), - "aws_athena_named_query": resourceAwsAthenaNamedQuery(), - "aws_athena_workgroup": resourceAwsAthenaWorkgroup(), - "aws_autoscaling_attachment": resourceAwsAutoscalingAttachment(), - "aws_autoscaling_group": resourceAwsAutoscalingGroup(), - "aws_autoscaling_group_tag": resourceAwsAutoscalingGroupTag(), - "aws_autoscaling_lifecycle_hook": resourceAwsAutoscalingLifecycleHook(), - "aws_autoscaling_notification": resourceAwsAutoscalingNotification(), - "aws_autoscaling_policy": resourceAwsAutoscalingPolicy(), - "aws_autoscaling_schedule": resourceAwsAutoscalingSchedule(), - "aws_autoscalingplans_scaling_plan": resourceAwsAutoScalingPlansScalingPlan(), - "aws_backup_global_settings": resourceAwsBackupGlobalSettings(), - "aws_backup_plan": resourceAwsBackupPlan(), - "aws_backup_region_settings": resourceAwsBackupRegionSettings(), - "aws_backup_selection": resourceAwsBackupSelection(), - "aws_backup_vault": resourceAwsBackupVault(), - "aws_backup_vault_notifications": resourceAwsBackupVaultNotifications(), - "aws_backup_vault_policy": resourceAwsBackupVaultPolicy(), - "aws_budgets_budget": resourceAwsBudgetsBudget(), - "aws_budgets_budget_action": resourceAwsBudgetsBudgetAction(), - "aws_chime_voice_connector": resourceAwsChimeVoiceConnector(), - "aws_chime_voice_connector_group": resourceAwsChimeVoiceConnectorGroup(), - "aws_chime_voice_connector_logging": resourceAwsChimeVoiceConnectorLogging(), - "aws_chime_voice_connector_streaming": resourceAwsChimeVoiceConnectorStreaming(), - "aws_chime_voice_connector_origination": resourceAwsChimeVoiceConnectorOrigination(), - "aws_chime_voice_connector_termination": resourceAwsChimeVoiceConnectorTermination(), - "aws_cloud9_environment_ec2": resourceAwsCloud9EnvironmentEc2(), - "aws_cloudformation_stack": resourceAwsCloudFormationStack(), - "aws_cloudformation_stack_set": resourceAwsCloudFormationStackSet(), - "aws_cloudformation_stack_set_instance": resourceAwsCloudFormationStackSetInstance(), - "aws_cloudformation_type": resourceAwsCloudFormationType(), - "aws_cloudfront_cache_policy": resourceAwsCloudFrontCachePolicy(), - "aws_cloudfront_distribution": resourceAwsCloudFrontDistribution(), - "aws_cloudfront_function": resourceAwsCloudFrontFunction(), - "aws_cloudfront_key_group": resourceAwsCloudFrontKeyGroup(), - "aws_cloudfront_monitoring_subscription": resourceAwsCloudFrontMonitoringSubscription(), - "aws_cloudfront_origin_access_identity": resourceAwsCloudFrontOriginAccessIdentity(), - "aws_cloudfront_origin_request_policy": resourceAwsCloudFrontOriginRequestPolicy(), - "aws_cloudfront_public_key": resourceAwsCloudFrontPublicKey(), - "aws_cloudfront_realtime_log_config": resourceAwsCloudFrontRealtimeLogConfig(), - "aws_cloudtrail": resourceAwsCloudTrail(), - "aws_cloudwatch_event_bus": resourceAwsCloudWatchEventBus(), - "aws_cloudwatch_event_bus_policy": resourceAwsCloudWatchEventBusPolicy(), - "aws_cloudwatch_event_permission": resourceAwsCloudWatchEventPermission(), - "aws_cloudwatch_event_rule": resourceAwsCloudWatchEventRule(), - "aws_cloudwatch_event_target": resourceAwsCloudWatchEventTarget(), - "aws_cloudwatch_event_archive": resourceAwsCloudWatchEventArchive(), - "aws_cloudwatch_event_connection": resourceAwsCloudWatchEventConnection(), - "aws_cloudwatch_event_api_destination": resourceAwsCloudWatchEventApiDestination(), - "aws_cloudwatch_log_destination": resourceAwsCloudWatchLogDestination(), - "aws_cloudwatch_log_destination_policy": resourceAwsCloudWatchLogDestinationPolicy(), - "aws_cloudwatch_log_group": resourceAwsCloudWatchLogGroup(), - "aws_cloudwatch_log_metric_filter": resourceAwsCloudWatchLogMetricFilter(), - "aws_cloudwatch_log_resource_policy": resourceAwsCloudWatchLogResourcePolicy(), - "aws_cloudwatch_log_stream": resourceAwsCloudWatchLogStream(), - "aws_cloudwatch_log_subscription_filter": resourceAwsCloudwatchLogSubscriptionFilter(), - "aws_config_aggregate_authorization": resourceAwsConfigAggregateAuthorization(), - "aws_config_config_rule": resourceAwsConfigConfigRule(), - "aws_config_configuration_aggregator": resourceAwsConfigConfigurationAggregator(), - "aws_config_configuration_recorder": resourceAwsConfigConfigurationRecorder(), - "aws_config_configuration_recorder_status": resourceAwsConfigConfigurationRecorderStatus(), - "aws_config_conformance_pack": resourceAwsConfigConformancePack(), - "aws_config_delivery_channel": resourceAwsConfigDeliveryChannel(), - "aws_config_organization_conformance_pack": resourceAwsConfigOrganizationConformancePack(), - "aws_config_organization_custom_rule": resourceAwsConfigOrganizationCustomRule(), - "aws_config_organization_managed_rule": resourceAwsConfigOrganizationManagedRule(), - "aws_config_remediation_configuration": resourceAwsConfigRemediationConfiguration(), - "aws_cognito_identity_pool": resourceAwsCognitoIdentityPool(), - "aws_cognito_identity_pool_roles_attachment": resourceAwsCognitoIdentityPoolRolesAttachment(), - "aws_cognito_identity_provider": resourceAwsCognitoIdentityProvider(), - "aws_cognito_resource_server": resourceAwsCognitoResourceServer(), - "aws_cognito_user_group": resourceAwsCognitoUserGroup(), - "aws_cognito_user_pool": resourceAwsCognitoUserPool(), - "aws_cognito_user_pool_client": resourceAwsCognitoUserPoolClient(), - "aws_cognito_user_pool_domain": resourceAwsCognitoUserPoolDomain(), - "aws_cognito_user_pool_ui_customization": resourceAwsCognitoUserPoolUICustomization(), - "aws_cloudhsm_v2_cluster": resourceAwsCloudHsmV2Cluster(), - "aws_cloudhsm_v2_hsm": resourceAwsCloudHsmV2Hsm(), - "aws_cloudwatch_composite_alarm": resourceAwsCloudWatchCompositeAlarm(), - "aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(), - "aws_cloudwatch_dashboard": resourceAwsCloudWatchDashboard(), - "aws_cloudwatch_metric_stream": resourceAwsCloudWatchMetricStream(), - "aws_cloudwatch_query_definition": resourceAwsCloudWatchQueryDefinition(), - "aws_codedeploy_app": resourceAwsCodeDeployApp(), - "aws_codedeploy_deployment_config": resourceAwsCodeDeployDeploymentConfig(), - "aws_codedeploy_deployment_group": resourceAwsCodeDeployDeploymentGroup(), - "aws_codecommit_repository": resourceAwsCodeCommitRepository(), - "aws_codecommit_trigger": resourceAwsCodeCommitTrigger(), - "aws_codeartifact_domain": resourceAwsCodeArtifactDomain(), - "aws_codeartifact_domain_permissions_policy": resourceAwsCodeArtifactDomainPermissionsPolicy(), - "aws_codeartifact_repository": resourceAwsCodeArtifactRepository(), - "aws_codeartifact_repository_permissions_policy": resourceAwsCodeArtifactRepositoryPermissionsPolicy(), - "aws_codebuild_project": resourceAwsCodeBuildProject(), - "aws_codebuild_report_group": resourceAwsCodeBuildReportGroup(), - "aws_codebuild_source_credential": resourceAwsCodeBuildSourceCredential(), - "aws_codebuild_webhook": resourceAwsCodeBuildWebhook(), - "aws_codepipeline": resourceAwsCodePipeline(), - "aws_codepipeline_webhook": resourceAwsCodePipelineWebhook(), - "aws_codestarconnections_connection": resourceAwsCodeStarConnectionsConnection(), - "aws_codestarconnections_host": resourceAwsCodeStarConnectionsHost(), - "aws_codestarnotifications_notification_rule": resourceAwsCodeStarNotificationsNotificationRule(), - "aws_cur_report_definition": resourceAwsCurReportDefinition(), - "aws_customer_gateway": resourceAwsCustomerGateway(), - "aws_datapipeline_pipeline": resourceAwsDataPipelinePipeline(), - "aws_datasync_agent": resourceAwsDataSyncAgent(), - "aws_datasync_location_efs": resourceAwsDataSyncLocationEfs(), - "aws_datasync_location_fsx_windows_file_system": resourceAwsDataSyncLocationFsxWindowsFileSystem(), - "aws_datasync_location_nfs": resourceAwsDataSyncLocationNfs(), - "aws_datasync_location_s3": resourceAwsDataSyncLocationS3(), - "aws_datasync_location_smb": resourceAwsDataSyncLocationSmb(), - "aws_datasync_task": resourceAwsDataSyncTask(), - "aws_dax_cluster": resourceAwsDaxCluster(), - "aws_dax_parameter_group": resourceAwsDaxParameterGroup(), - "aws_dax_subnet_group": resourceAwsDaxSubnetGroup(), - "aws_db_cluster_snapshot": resourceAwsDbClusterSnapshot(), - "aws_db_event_subscription": resourceAwsDbEventSubscription(), - "aws_db_instance": resourceAwsDbInstance(), - "aws_db_instance_role_association": resourceAwsDbInstanceRoleAssociation(), - "aws_db_option_group": resourceAwsDbOptionGroup(), - "aws_db_parameter_group": resourceAwsDbParameterGroup(), - "aws_db_proxy": resourceAwsDbProxy(), - "aws_db_proxy_default_target_group": resourceAwsDbProxyDefaultTargetGroup(), - "aws_db_proxy_endpoint": resourceAwsDbProxyEndpoint(), - "aws_db_proxy_target": resourceAwsDbProxyTarget(), - "aws_db_security_group": resourceAwsDbSecurityGroup(), - "aws_db_snapshot": resourceAwsDbSnapshot(), - "aws_db_subnet_group": resourceAwsDbSubnetGroup(), - "aws_devicefarm_project": resourceAwsDevicefarmProject(), - "aws_directory_service_directory": resourceAwsDirectoryServiceDirectory(), - "aws_directory_service_conditional_forwarder": resourceAwsDirectoryServiceConditionalForwarder(), - "aws_directory_service_log_subscription": resourceAwsDirectoryServiceLogSubscription(), - "aws_dlm_lifecycle_policy": resourceAwsDlmLifecyclePolicy(), - "aws_dms_certificate": resourceAwsDmsCertificate(), - "aws_dms_endpoint": resourceAwsDmsEndpoint(), - "aws_dms_event_subscription": resourceAwsDmsEventSubscription(), - "aws_dms_replication_instance": resourceAwsDmsReplicationInstance(), - "aws_dms_replication_subnet_group": resourceAwsDmsReplicationSubnetGroup(), - "aws_dms_replication_task": resourceAwsDmsReplicationTask(), - "aws_docdb_cluster": resourceAwsDocDBCluster(), - "aws_docdb_cluster_instance": resourceAwsDocDBClusterInstance(), - "aws_docdb_cluster_parameter_group": resourceAwsDocDBClusterParameterGroup(), - "aws_docdb_cluster_snapshot": resourceAwsDocDBClusterSnapshot(), - "aws_docdb_subnet_group": resourceAwsDocDBSubnetGroup(), - "aws_dx_bgp_peer": resourceAwsDxBgpPeer(), - "aws_dx_connection": resourceAwsDxConnection(), - "aws_dx_connection_association": resourceAwsDxConnectionAssociation(), - "aws_dx_gateway": resourceAwsDxGateway(), - "aws_dx_gateway_association": resourceAwsDxGatewayAssociation(), - "aws_dx_gateway_association_proposal": resourceAwsDxGatewayAssociationProposal(), - "aws_dx_hosted_private_virtual_interface": resourceAwsDxHostedPrivateVirtualInterface(), - "aws_dx_hosted_private_virtual_interface_accepter": resourceAwsDxHostedPrivateVirtualInterfaceAccepter(), - "aws_dx_hosted_public_virtual_interface": resourceAwsDxHostedPublicVirtualInterface(), - "aws_dx_hosted_public_virtual_interface_accepter": resourceAwsDxHostedPublicVirtualInterfaceAccepter(), - "aws_dx_hosted_transit_virtual_interface": resourceAwsDxHostedTransitVirtualInterface(), - "aws_dx_hosted_transit_virtual_interface_accepter": resourceAwsDxHostedTransitVirtualInterfaceAccepter(), - "aws_dx_lag": resourceAwsDxLag(), - "aws_dx_private_virtual_interface": resourceAwsDxPrivateVirtualInterface(), - "aws_dx_public_virtual_interface": resourceAwsDxPublicVirtualInterface(), - "aws_dx_transit_virtual_interface": resourceAwsDxTransitVirtualInterface(), - "aws_dynamodb_table": resourceAwsDynamoDbTable(), - "aws_dynamodb_table_item": resourceAwsDynamoDbTableItem(), - "aws_dynamodb_tag": resourceAwsDynamodbTag(), - "aws_dynamodb_global_table": resourceAwsDynamoDbGlobalTable(), - "aws_dynamodb_kinesis_streaming_destination": resourceAwsDynamoDbKinesisStreamingDestination(), - "aws_ebs_default_kms_key": resourceAwsEbsDefaultKmsKey(), - "aws_ebs_encryption_by_default": resourceAwsEbsEncryptionByDefault(), - "aws_ebs_snapshot": resourceAwsEbsSnapshot(), - "aws_ebs_snapshot_copy": resourceAwsEbsSnapshotCopy(), - "aws_ebs_snapshot_import": resourceAwsEbsSnapshotImport(), - "aws_ebs_volume": resourceAwsEbsVolume(), - "aws_ec2_availability_zone_group": resourceAwsEc2AvailabilityZoneGroup(), - "aws_ec2_capacity_reservation": resourceAwsEc2CapacityReservation(), - "aws_ec2_carrier_gateway": resourceAwsEc2CarrierGateway(), - "aws_ec2_client_vpn_authorization_rule": resourceAwsEc2ClientVpnAuthorizationRule(), - "aws_ec2_client_vpn_endpoint": resourceAwsEc2ClientVpnEndpoint(), - "aws_ec2_client_vpn_network_association": resourceAwsEc2ClientVpnNetworkAssociation(), - "aws_ec2_client_vpn_route": resourceAwsEc2ClientVpnRoute(), - "aws_ec2_fleet": resourceAwsEc2Fleet(), - "aws_ec2_local_gateway_route": resourceAwsEc2LocalGatewayRoute(), - "aws_ec2_local_gateway_route_table_vpc_association": resourceAwsEc2LocalGatewayRouteTableVpcAssociation(), - "aws_ec2_managed_prefix_list": resourceAwsEc2ManagedPrefixList(), - "aws_ec2_tag": resourceAwsEc2Tag(), - "aws_ec2_traffic_mirror_filter": resourceAwsEc2TrafficMirrorFilter(), - "aws_ec2_traffic_mirror_filter_rule": resourceAwsEc2TrafficMirrorFilterRule(), - "aws_ec2_traffic_mirror_target": resourceAwsEc2TrafficMirrorTarget(), - "aws_ec2_traffic_mirror_session": resourceAwsEc2TrafficMirrorSession(), - "aws_ec2_transit_gateway": resourceAwsEc2TransitGateway(), - "aws_ec2_transit_gateway_peering_attachment": resourceAwsEc2TransitGatewayPeeringAttachment(), - "aws_ec2_transit_gateway_peering_attachment_accepter": resourceAwsEc2TransitGatewayPeeringAttachmentAccepter(), - "aws_ec2_transit_gateway_prefix_list_reference": resourceAwsEc2TransitGatewayPrefixListReference(), - "aws_ec2_transit_gateway_route": resourceAwsEc2TransitGatewayRoute(), - "aws_ec2_transit_gateway_route_table": resourceAwsEc2TransitGatewayRouteTable(), - "aws_ec2_transit_gateway_route_table_association": resourceAwsEc2TransitGatewayRouteTableAssociation(), - "aws_ec2_transit_gateway_route_table_propagation": resourceAwsEc2TransitGatewayRouteTablePropagation(), - "aws_ec2_transit_gateway_vpc_attachment": resourceAwsEc2TransitGatewayVpcAttachment(), - "aws_ec2_transit_gateway_vpc_attachment_accepter": resourceAwsEc2TransitGatewayVpcAttachmentAccepter(), - "aws_ecr_lifecycle_policy": resourceAwsEcrLifecyclePolicy(), - "aws_ecrpublic_repository": resourceAwsEcrPublicRepository(), - "aws_ecr_registry_policy": resourceAwsEcrRegistryPolicy(), - "aws_ecr_replication_configuration": resourceAwsEcrReplicationConfiguration(), - "aws_ecr_repository": resourceAwsEcrRepository(), - "aws_ecr_repository_policy": resourceAwsEcrRepositoryPolicy(), - "aws_ecs_capacity_provider": resourceAwsEcsCapacityProvider(), - "aws_ecs_cluster": resourceAwsEcsCluster(), - "aws_ecs_service": resourceAwsEcsService(), - "aws_ecs_tag": resourceAwsEcsTag(), - "aws_ecs_task_definition": resourceAwsEcsTaskDefinition(), - "aws_efs_access_point": resourceAwsEfsAccessPoint(), - "aws_efs_backup_policy": resourceAwsEfsBackupPolicy(), - "aws_efs_file_system": resourceAwsEfsFileSystem(), - "aws_efs_file_system_policy": resourceAwsEfsFileSystemPolicy(), - "aws_efs_mount_target": resourceAwsEfsMountTarget(), - "aws_egress_only_internet_gateway": resourceAwsEgressOnlyInternetGateway(), - "aws_eip": resourceAwsEip(), - "aws_eip_association": resourceAwsEipAssociation(), - "aws_eks_cluster": resourceAwsEksCluster(), - "aws_eks_addon": resourceAwsEksAddon(), - "aws_eks_fargate_profile": resourceAwsEksFargateProfile(), - "aws_eks_identity_provider_config": resourceAwsEksIdentityProviderConfig(), - "aws_eks_node_group": resourceAwsEksNodeGroup(), - "aws_elasticache_cluster": resourceAwsElasticacheCluster(), - "aws_elasticache_global_replication_group": resourceAwsElasticacheGlobalReplicationGroup(), - "aws_elasticache_parameter_group": resourceAwsElasticacheParameterGroup(), - "aws_elasticache_replication_group": resourceAwsElasticacheReplicationGroup(), - "aws_elasticache_security_group": resourceAwsElasticacheSecurityGroup(), - "aws_elasticache_subnet_group": resourceAwsElasticacheSubnetGroup(), - "aws_elasticache_user": resourceAwsElasticacheUser(), - "aws_elasticache_user_group": resourceAwsElasticacheUserGroup(), - "aws_elastic_beanstalk_application": resourceAwsElasticBeanstalkApplication(), - "aws_elastic_beanstalk_application_version": resourceAwsElasticBeanstalkApplicationVersion(), - "aws_elastic_beanstalk_configuration_template": resourceAwsElasticBeanstalkConfigurationTemplate(), - "aws_elastic_beanstalk_environment": resourceAwsElasticBeanstalkEnvironment(), - "aws_elasticsearch_domain": resourceAwsElasticSearchDomain(), - "aws_elasticsearch_domain_policy": resourceAwsElasticSearchDomainPolicy(), - "aws_elasticsearch_domain_saml_options": resourceAwsElasticSearchDomainSAMLOptions(), - "aws_elastictranscoder_pipeline": resourceAwsElasticTranscoderPipeline(), - "aws_elastictranscoder_preset": resourceAwsElasticTranscoderPreset(), - "aws_elb": resourceAwsElb(), - "aws_elb_attachment": resourceAwsElbAttachment(), - "aws_emr_cluster": resourceAwsEMRCluster(), - "aws_emr_instance_group": resourceAwsEMRInstanceGroup(), - "aws_emr_instance_fleet": resourceAwsEMRInstanceFleet(), - "aws_emr_managed_scaling_policy": resourceAwsEMRManagedScalingPolicy(), - "aws_emr_security_configuration": resourceAwsEMRSecurityConfiguration(), - "aws_flow_log": resourceAwsFlowLog(), - "aws_fsx_backup": resourceAwsFsxBackup(), - "aws_fsx_lustre_file_system": resourceAwsFsxLustreFileSystem(), - "aws_fsx_ontap_file_system": resourceAwsFsxOntapFileSystem(), - "aws_fsx_windows_file_system": resourceAwsFsxWindowsFileSystem(), - "aws_fms_admin_account": resourceAwsFmsAdminAccount(), - "aws_fms_policy": resourceAwsFmsPolicy(), - "aws_gamelift_alias": resourceAwsGameliftAlias(), - "aws_gamelift_build": resourceAwsGameliftBuild(), - "aws_gamelift_fleet": resourceAwsGameliftFleet(), - "aws_gamelift_game_session_queue": resourceAwsGameliftGameSessionQueue(), - "aws_glacier_vault": resourceAwsGlacierVault(), - "aws_glacier_vault_lock": resourceAwsGlacierVaultLock(), - "aws_globalaccelerator_accelerator": resourceAwsGlobalAcceleratorAccelerator(), - "aws_globalaccelerator_endpoint_group": resourceAwsGlobalAcceleratorEndpointGroup(), - "aws_globalaccelerator_listener": resourceAwsGlobalAcceleratorListener(), - "aws_glue_catalog_database": resourceAwsGlueCatalogDatabase(), - "aws_glue_catalog_table": resourceAwsGlueCatalogTable(), - "aws_glue_classifier": resourceAwsGlueClassifier(), - "aws_glue_connection": resourceAwsGlueConnection(), - "aws_glue_dev_endpoint": resourceAwsGlueDevEndpoint(), - "aws_glue_crawler": resourceAwsGlueCrawler(), - "aws_glue_data_catalog_encryption_settings": resourceAwsGlueDataCatalogEncryptionSettings(), - "aws_glue_job": resourceAwsGlueJob(), - "aws_glue_ml_transform": resourceAwsGlueMLTransform(), - "aws_glue_partition": resourceAwsGluePartition(), - "aws_glue_registry": resourceAwsGlueRegistry(), - "aws_glue_resource_policy": resourceAwsGlueResourcePolicy(), - "aws_glue_schema": resourceAwsGlueSchema(), - "aws_glue_security_configuration": resourceAwsGlueSecurityConfiguration(), - "aws_glue_trigger": resourceAwsGlueTrigger(), - "aws_glue_user_defined_function": resourceAwsGlueUserDefinedFunction(), - "aws_glue_workflow": resourceAwsGlueWorkflow(), - "aws_guardduty_detector": resourceAwsGuardDutyDetector(), - "aws_guardduty_filter": resourceAwsGuardDutyFilter(), - "aws_guardduty_invite_accepter": resourceAwsGuardDutyInviteAccepter(), - "aws_guardduty_ipset": resourceAwsGuardDutyIpset(), - "aws_guardduty_member": resourceAwsGuardDutyMember(), - "aws_guardduty_organization_admin_account": resourceAwsGuardDutyOrganizationAdminAccount(), - "aws_guardduty_organization_configuration": resourceAwsGuardDutyOrganizationConfiguration(), - "aws_guardduty_publishing_destination": resourceAwsGuardDutyPublishingDestination(), - "aws_guardduty_threatintelset": resourceAwsGuardDutyThreatintelset(), - "aws_iam_access_key": resourceAwsIamAccessKey(), - "aws_iam_account_alias": resourceAwsIamAccountAlias(), - "aws_iam_account_password_policy": resourceAwsIamAccountPasswordPolicy(), - "aws_iam_group_policy": resourceAwsIamGroupPolicy(), - "aws_iam_group": resourceAwsIamGroup(), - "aws_iam_group_membership": resourceAwsIamGroupMembership(), - "aws_iam_group_policy_attachment": resourceAwsIamGroupPolicyAttachment(), - "aws_iam_instance_profile": resourceAwsIamInstanceProfile(), - "aws_iam_openid_connect_provider": resourceAwsIamOpenIDConnectProvider(), - "aws_iam_policy": resourceAwsIamPolicy(), - "aws_iam_policy_attachment": resourceAwsIamPolicyAttachment(), - "aws_iam_role_policy_attachment": resourceAwsIamRolePolicyAttachment(), - "aws_iam_role_policy": resourceAwsIamRolePolicy(), - "aws_iam_role": resourceAwsIamRole(), - "aws_iam_saml_provider": resourceAwsIamSamlProvider(), - "aws_iam_server_certificate": resourceAwsIAMServerCertificate(), - "aws_iam_service_linked_role": resourceAwsIamServiceLinkedRole(), - "aws_iam_user_group_membership": resourceAwsIamUserGroupMembership(), - "aws_iam_user_policy_attachment": resourceAwsIamUserPolicyAttachment(), - "aws_iam_user_policy": resourceAwsIamUserPolicy(), - "aws_iam_user_ssh_key": resourceAwsIamUserSshKey(), - "aws_iam_user": resourceAwsIamUser(), - "aws_iam_user_login_profile": resourceAwsIamUserLoginProfile(), - "aws_imagebuilder_component": resourceAwsImageBuilderComponent(), - "aws_imagebuilder_distribution_configuration": resourceAwsImageBuilderDistributionConfiguration(), - "aws_imagebuilder_image": resourceAwsImageBuilderImage(), - "aws_imagebuilder_image_pipeline": resourceAwsImageBuilderImagePipeline(), - "aws_imagebuilder_image_recipe": resourceAwsImageBuilderImageRecipe(), - "aws_imagebuilder_infrastructure_configuration": resourceAwsImageBuilderInfrastructureConfiguration(), - "aws_inspector_assessment_target": resourceAWSInspectorAssessmentTarget(), - "aws_inspector_assessment_template": resourceAWSInspectorAssessmentTemplate(), - "aws_inspector_resource_group": resourceAWSInspectorResourceGroup(), - "aws_instance": resourceAwsInstance(), - "aws_internet_gateway": resourceAwsInternetGateway(), - "aws_iot_certificate": resourceAwsIotCertificate(), - "aws_iot_policy": resourceAwsIotPolicy(), - "aws_iot_policy_attachment": resourceAwsIotPolicyAttachment(), - "aws_iot_thing": resourceAwsIotThing(), - "aws_iot_thing_principal_attachment": resourceAwsIotThingPrincipalAttachment(), - "aws_iot_thing_type": resourceAwsIotThingType(), - "aws_iot_topic_rule": resourceAwsIotTopicRule(), - "aws_iot_role_alias": resourceAwsIotRoleAlias(), - "aws_key_pair": resourceAwsKeyPair(), - "aws_kinesis_analytics_application": resourceAwsKinesisAnalyticsApplication(), - "aws_kinesisanalyticsv2_application": resourceAwsKinesisAnalyticsV2Application(), - "aws_kinesisanalyticsv2_application_snapshot": resourceAwsKinesisAnalyticsV2ApplicationSnapshot(), - "aws_kinesis_firehose_delivery_stream": resourceAwsKinesisFirehoseDeliveryStream(), - "aws_kinesis_stream": resourceAwsKinesisStream(), - "aws_kinesis_stream_consumer": resourceAwsKinesisStreamConsumer(), - "aws_kinesis_video_stream": resourceAwsKinesisVideoStream(), - "aws_kms_alias": resourceAwsKmsAlias(), - "aws_kms_external_key": resourceAwsKmsExternalKey(), - "aws_kms_grant": resourceAwsKmsGrant(), - "aws_kms_key": resourceAwsKmsKey(), - "aws_kms_ciphertext": resourceAwsKmsCiphertext(), - "aws_lakeformation_data_lake_settings": resourceAwsLakeFormationDataLakeSettings(), - "aws_lakeformation_permissions": resourceAwsLakeFormationPermissions(), - "aws_lakeformation_resource": resourceAwsLakeFormationResource(), - "aws_lambda_alias": resourceAwsLambdaAlias(), - "aws_lambda_code_signing_config": resourceAwsLambdaCodeSigningConfig(), - "aws_lambda_event_source_mapping": resourceAwsLambdaEventSourceMapping(), - "aws_lambda_function_event_invoke_config": resourceAwsLambdaFunctionEventInvokeConfig(), - "aws_lambda_function": resourceAwsLambdaFunction(), - "aws_lambda_layer_version": resourceAwsLambdaLayerVersion(), - "aws_lambda_permission": resourceAwsLambdaPermission(), - "aws_lambda_provisioned_concurrency_config": resourceAwsLambdaProvisionedConcurrencyConfig(), - "aws_launch_configuration": resourceAwsLaunchConfiguration(), - "aws_launch_template": resourceAwsLaunchTemplate(), - "aws_lex_bot": resourceAwsLexBot(), - "aws_lex_bot_alias": resourceAwsLexBotAlias(), - "aws_lex_intent": resourceAwsLexIntent(), - "aws_lex_slot_type": resourceAwsLexSlotType(), - "aws_licensemanager_association": resourceAwsLicenseManagerAssociation(), - "aws_licensemanager_license_configuration": resourceAwsLicenseManagerLicenseConfiguration(), - "aws_lightsail_domain": resourceAwsLightsailDomain(), - "aws_lightsail_instance": resourceAwsLightsailInstance(), - "aws_lightsail_instance_public_ports": resourceAwsLightsailInstancePublicPorts(), - "aws_lightsail_key_pair": resourceAwsLightsailKeyPair(), - "aws_lightsail_static_ip": resourceAwsLightsailStaticIp(), - "aws_lightsail_static_ip_attachment": resourceAwsLightsailStaticIpAttachment(), - "aws_lb_cookie_stickiness_policy": resourceAwsLBCookieStickinessPolicy(), - "aws_load_balancer_policy": resourceAwsLoadBalancerPolicy(), - "aws_load_balancer_backend_server_policy": resourceAwsLoadBalancerBackendServerPolicies(), - "aws_load_balancer_listener_policy": resourceAwsLoadBalancerListenerPolicies(), - "aws_lb_ssl_negotiation_policy": resourceAwsLBSSLNegotiationPolicy(), - "aws_macie2_account": resourceAwsMacie2Account(), - "aws_macie2_classification_job": resourceAwsMacie2ClassificationJob(), - "aws_macie2_custom_data_identifier": resourceAwsMacie2CustomDataIdentifier(), - "aws_macie2_findings_filter": resourceAwsMacie2FindingsFilter(), - "aws_macie2_invitation_accepter": resourceAwsMacie2InvitationAccepter(), - "aws_macie2_member": resourceAwsMacie2Member(), - "aws_macie2_organization_admin_account": resourceAwsMacie2OrganizationAdminAccount(), - "aws_macie_member_account_association": resourceAwsMacieMemberAccountAssociation(), - "aws_macie_s3_bucket_association": resourceAwsMacieS3BucketAssociation(), - "aws_main_route_table_association": resourceAwsMainRouteTableAssociation(), - "aws_mq_broker": resourceAwsMqBroker(), - "aws_mq_configuration": resourceAwsMqConfiguration(), - "aws_media_convert_queue": resourceAwsMediaConvertQueue(), - "aws_media_package_channel": resourceAwsMediaPackageChannel(), - "aws_media_store_container": resourceAwsMediaStoreContainer(), - "aws_media_store_container_policy": resourceAwsMediaStoreContainerPolicy(), - "aws_msk_cluster": resourceAwsMskCluster(), - "aws_msk_configuration": resourceAwsMskConfiguration(), - "aws_msk_scram_secret_association": resourceAwsMskScramSecretAssociation(), - "aws_mwaa_environment": resourceAwsMwaaEnvironment(), - "aws_nat_gateway": resourceAwsNatGateway(), - "aws_network_acl": resourceAwsNetworkAcl(), - "aws_default_network_acl": resourceAwsDefaultNetworkAcl(), - "aws_neptune_cluster": resourceAwsNeptuneCluster(), - "aws_neptune_cluster_endpoint": resourceAwsNeptuneClusterEndpoint(), - "aws_neptune_cluster_instance": resourceAwsNeptuneClusterInstance(), - "aws_neptune_cluster_parameter_group": resourceAwsNeptuneClusterParameterGroup(), - "aws_neptune_cluster_snapshot": resourceAwsNeptuneClusterSnapshot(), - "aws_neptune_event_subscription": resourceAwsNeptuneEventSubscription(), - "aws_neptune_parameter_group": resourceAwsNeptuneParameterGroup(), - "aws_neptune_subnet_group": resourceAwsNeptuneSubnetGroup(), - "aws_network_acl_rule": resourceAwsNetworkAclRule(), - "aws_network_interface": resourceAwsNetworkInterface(), - "aws_network_interface_attachment": resourceAwsNetworkInterfaceAttachment(), - "aws_networkfirewall_firewall": resourceAwsNetworkFirewallFirewall(), - "aws_networkfirewall_firewall_policy": resourceAwsNetworkFirewallFirewallPolicy(), - "aws_networkfirewall_logging_configuration": resourceAwsNetworkFirewallLoggingConfiguration(), - "aws_networkfirewall_resource_policy": resourceAwsNetworkFirewallResourcePolicy(), - "aws_networkfirewall_rule_group": resourceAwsNetworkFirewallRuleGroup(), - "aws_opsworks_application": resourceAwsOpsworksApplication(), - "aws_opsworks_stack": resourceAwsOpsworksStack(), - "aws_opsworks_java_app_layer": resourceAwsOpsworksJavaAppLayer(), - "aws_opsworks_haproxy_layer": resourceAwsOpsworksHaproxyLayer(), - "aws_opsworks_static_web_layer": resourceAwsOpsworksStaticWebLayer(), - "aws_opsworks_php_app_layer": resourceAwsOpsworksPhpAppLayer(), - "aws_opsworks_rails_app_layer": resourceAwsOpsworksRailsAppLayer(), - "aws_opsworks_nodejs_app_layer": resourceAwsOpsworksNodejsAppLayer(), - "aws_opsworks_memcached_layer": resourceAwsOpsworksMemcachedLayer(), - "aws_opsworks_mysql_layer": resourceAwsOpsworksMysqlLayer(), - "aws_opsworks_ganglia_layer": resourceAwsOpsworksGangliaLayer(), - "aws_opsworks_custom_layer": resourceAwsOpsworksCustomLayer(), - "aws_opsworks_instance": resourceAwsOpsworksInstance(), - "aws_opsworks_user_profile": resourceAwsOpsworksUserProfile(), - "aws_opsworks_permission": resourceAwsOpsworksPermission(), - "aws_opsworks_rds_db_instance": resourceAwsOpsworksRdsDbInstance(), - "aws_organizations_organization": resourceAwsOrganizationsOrganization(), - "aws_organizations_account": resourceAwsOrganizationsAccount(), - "aws_organizations_delegated_administrator": resourceAwsOrganizationsDelegatedAdministrator(), - "aws_organizations_policy": resourceAwsOrganizationsPolicy(), - "aws_organizations_policy_attachment": resourceAwsOrganizationsPolicyAttachment(), - "aws_organizations_organizational_unit": resourceAwsOrganizationsOrganizationalUnit(), - "aws_placement_group": resourceAwsPlacementGroup(), - "aws_prometheus_workspace": resourceAwsPrometheusWorkspace(), - "aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(), - "aws_qldb_ledger": resourceAwsQLDBLedger(), - "aws_quicksight_group": resourceAwsQuickSightGroup(), - "aws_quicksight_group_membership": resourceAwsQuickSightGroupMembership(), - "aws_quicksight_user": resourceAwsQuickSightUser(), - "aws_ram_principal_association": resourceAwsRamPrincipalAssociation(), - "aws_ram_resource_association": resourceAwsRamResourceAssociation(), - "aws_ram_resource_share": resourceAwsRamResourceShare(), - "aws_ram_resource_share_accepter": resourceAwsRamResourceShareAccepter(), - "aws_rds_cluster": resourceAwsRDSCluster(), - "aws_rds_cluster_endpoint": resourceAwsRDSClusterEndpoint(), - "aws_rds_cluster_instance": resourceAwsRDSClusterInstance(), - "aws_rds_cluster_parameter_group": resourceAwsRDSClusterParameterGroup(), - "aws_rds_cluster_role_association": resourceAwsRDSClusterRoleAssociation(), - "aws_rds_global_cluster": resourceAwsRDSGlobalCluster(), - "aws_redshift_cluster": resourceAwsRedshiftCluster(), - "aws_redshift_security_group": resourceAwsRedshiftSecurityGroup(), - "aws_redshift_parameter_group": resourceAwsRedshiftParameterGroup(), - "aws_redshift_subnet_group": resourceAwsRedshiftSubnetGroup(), - "aws_redshift_snapshot_copy_grant": resourceAwsRedshiftSnapshotCopyGrant(), - "aws_redshift_snapshot_schedule": resourceAwsRedshiftSnapshotSchedule(), - "aws_redshift_snapshot_schedule_association": resourceAwsRedshiftSnapshotScheduleAssociation(), - "aws_redshift_event_subscription": resourceAwsRedshiftEventSubscription(), - "aws_resourcegroups_group": resourceAwsResourceGroupsGroup(), - "aws_route53_delegation_set": resourceAwsRoute53DelegationSet(), - "aws_route53_hosted_zone_dnssec": resourceAwsRoute53HostedZoneDnssec(), - "aws_route53_key_signing_key": resourceAwsRoute53KeySigningKey(), - "aws_route53_query_log": resourceAwsRoute53QueryLog(), - "aws_route53_record": resourceAwsRoute53Record(), - "aws_route53_zone_association": resourceAwsRoute53ZoneAssociation(), - "aws_route53_vpc_association_authorization": resourceAwsRoute53VPCAssociationAuthorization(), - "aws_route53_zone": resourceAwsRoute53Zone(), - "aws_route53_health_check": resourceAwsRoute53HealthCheck(), - "aws_route53_resolver_dnssec_config": resourceAwsRoute53ResolverDnssecConfig(), - "aws_route53_resolver_endpoint": resourceAwsRoute53ResolverEndpoint(), - "aws_route53_resolver_firewall_config": resourceAwsRoute53ResolverFirewallConfig(), - "aws_route53_resolver_firewall_domain_list": resourceAwsRoute53ResolverFirewallDomainList(), - "aws_route53_resolver_firewall_rule": resourceAwsRoute53ResolverFirewallRule(), - "aws_route53_resolver_firewall_rule_group": resourceAwsRoute53ResolverFirewallRuleGroup(), - "aws_route53_resolver_firewall_rule_group_association": resourceAwsRoute53ResolverFirewallRuleGroupAssociation(), - "aws_route53_resolver_query_log_config": resourceAwsRoute53ResolverQueryLogConfig(), - "aws_route53_resolver_query_log_config_association": resourceAwsRoute53ResolverQueryLogConfigAssociation(), - "aws_route53_resolver_rule_association": resourceAwsRoute53ResolverRuleAssociation(), - "aws_route53_resolver_rule": resourceAwsRoute53ResolverRule(), - "aws_route53recoverycontrolconfig_cluster": resourceAwsRoute53RecoveryControlConfigCluster(), - "aws_route53recoverycontrolconfig_control_panel": resourceAwsRoute53RecoveryControlConfigControlPanel(), - "aws_route53recoverycontrolconfig_routing_control": resourceAwsRoute53RecoveryControlConfigRoutingControl(), - "aws_route53recoverycontrolconfig_safety_rule": resourceAwsRoute53RecoveryControlConfigSafetyRule(), - "aws_route53recoveryreadiness_cell": resourceAwsRoute53RecoveryReadinessCell(), - "aws_route53recoveryreadiness_readiness_check": resourceAwsRoute53RecoveryReadinessReadinessCheck(), - "aws_route53recoveryreadiness_recovery_group": resourceAwsRoute53RecoveryReadinessRecoveryGroup(), - "aws_route53recoveryreadiness_resource_set": resourceAwsRoute53RecoveryReadinessResourceSet(), + "aws_accessanalyzer_analyzer": resourceAwsAccessAnalyzerAnalyzer(), + "aws_acm_certificate": resourceAwsAcmCertificate(), + "aws_acm_certificate_validation": resourceAwsAcmCertificateValidation(), + "aws_acmpca_certificate_authority": resourceAwsAcmpcaCertificateAuthority(), + "aws_acmpca_certificate_authority_certificate": resourceAwsAcmpcaCertificateAuthorityCertificate(), + "aws_acmpca_certificate": resourceAwsAcmpcaCertificate(), + "aws_ami": resourceAwsAmi(), + "aws_ami_copy": resourceAwsAmiCopy(), + "aws_ami_from_instance": resourceAwsAmiFromInstance(), + "aws_ami_launch_permission": resourceAwsAmiLaunchPermission(), + "aws_amplify_app": resourceAwsAmplifyApp(), + "aws_amplify_backend_environment": resourceAwsAmplifyBackendEnvironment(), + "aws_amplify_branch": resourceAwsAmplifyBranch(), + "aws_amplify_domain_association": resourceAwsAmplifyDomainAssociation(), + "aws_amplify_webhook": resourceAwsAmplifyWebhook(), + "aws_api_gateway_account": resourceAwsApiGatewayAccount(), + "aws_api_gateway_api_key": resourceAwsApiGatewayApiKey(), + "aws_api_gateway_authorizer": resourceAwsApiGatewayAuthorizer(), + "aws_api_gateway_base_path_mapping": resourceAwsApiGatewayBasePathMapping(), + "aws_api_gateway_client_certificate": resourceAwsApiGatewayClientCertificate(), + "aws_api_gateway_deployment": resourceAwsApiGatewayDeployment(), + "aws_api_gateway_documentation_part": resourceAwsApiGatewayDocumentationPart(), + "aws_api_gateway_documentation_version": resourceAwsApiGatewayDocumentationVersion(), + "aws_api_gateway_domain_name": resourceAwsApiGatewayDomainName(), + "aws_api_gateway_gateway_response": resourceAwsApiGatewayGatewayResponse(), + "aws_api_gateway_integration": resourceAwsApiGatewayIntegration(), + "aws_api_gateway_integration_response": resourceAwsApiGatewayIntegrationResponse(), + "aws_api_gateway_method": resourceAwsApiGatewayMethod(), + "aws_api_gateway_method_response": resourceAwsApiGatewayMethodResponse(), + "aws_api_gateway_method_settings": resourceAwsApiGatewayMethodSettings(), + "aws_api_gateway_model": resourceAwsApiGatewayModel(), + "aws_api_gateway_request_validator": resourceAwsApiGatewayRequestValidator(), + "aws_api_gateway_resource": resourceAwsApiGatewayResource(), + "aws_api_gateway_rest_api": resourceAwsApiGatewayRestApi(), + "aws_api_gateway_rest_api_policy": resourceAwsApiGatewayRestApiPolicy(), + "aws_api_gateway_stage": resourceAwsApiGatewayStage(), + "aws_api_gateway_usage_plan": resourceAwsApiGatewayUsagePlan(), + "aws_api_gateway_usage_plan_key": resourceAwsApiGatewayUsagePlanKey(), + "aws_api_gateway_vpc_link": resourceAwsApiGatewayVpcLink(), + "aws_apigatewayv2_api": resourceAwsApiGatewayV2Api(), + "aws_apigatewayv2_api_mapping": resourceAwsApiGatewayV2ApiMapping(), + "aws_apigatewayv2_authorizer": resourceAwsApiGatewayV2Authorizer(), + "aws_apigatewayv2_deployment": resourceAwsApiGatewayV2Deployment(), + "aws_apigatewayv2_domain_name": resourceAwsApiGatewayV2DomainName(), + "aws_apigatewayv2_integration": resourceAwsApiGatewayV2Integration(), + "aws_apigatewayv2_integration_response": resourceAwsApiGatewayV2IntegrationResponse(), + "aws_apigatewayv2_model": resourceAwsApiGatewayV2Model(), + "aws_apigatewayv2_route": resourceAwsApiGatewayV2Route(), + "aws_apigatewayv2_route_response": resourceAwsApiGatewayV2RouteResponse(), + "aws_apigatewayv2_stage": resourceAwsApiGatewayV2Stage(), + "aws_apigatewayv2_vpc_link": resourceAwsApiGatewayV2VpcLink(), + "aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(), + "aws_appautoscaling_target": resourceAwsAppautoscalingTarget(), + "aws_appautoscaling_policy": resourceAwsAppautoscalingPolicy(), + "aws_appautoscaling_scheduled_action": resourceAwsAppautoscalingScheduledAction(), + "aws_appconfig_application": resourceAwsAppconfigApplication(), + "aws_appconfig_configuration_profile": resourceAwsAppconfigConfigurationProfile(), + "aws_appconfig_deployment": resourceAwsAppconfigDeployment(), + "aws_appconfig_deployment_strategy": resourceAwsAppconfigDeploymentStrategy(), + "aws_appconfig_environment": resourceAwsAppconfigEnvironment(), + "aws_appconfig_hosted_configuration_version": resourceAwsAppconfigHostedConfigurationVersion(), + "aws_appmesh_gateway_route": resourceAwsAppmeshGatewayRoute(), + "aws_appmesh_mesh": resourceAwsAppmeshMesh(), + "aws_appmesh_route": resourceAwsAppmeshRoute(), + "aws_appmesh_virtual_gateway": resourceAwsAppmeshVirtualGateway(), + "aws_appmesh_virtual_node": resourceAwsAppmeshVirtualNode(), + "aws_appmesh_virtual_router": resourceAwsAppmeshVirtualRouter(), + "aws_appmesh_virtual_service": resourceAwsAppmeshVirtualService(), + "aws_apprunner_auto_scaling_configuration_version": resourceAwsAppRunnerAutoScalingConfigurationVersion(), + "aws_apprunner_connection": resourceAwsAppRunnerConnection(), + "aws_apprunner_custom_domain_association": resourceAwsAppRunnerCustomDomainAssociation(), + "aws_apprunner_service": resourceAwsAppRunnerService(), + "aws_appstream_stack": resourceAwsAppStreamStack(), + "aws_appstream_fleet": resourceAwsAppStreamFleet(), + "aws_appsync_api_key": resourceAwsAppsyncApiKey(), + "aws_appsync_datasource": resourceAwsAppsyncDatasource(), + "aws_appsync_function": resourceAwsAppsyncFunction(), + "aws_appsync_graphql_api": resourceAwsAppsyncGraphqlApi(), + "aws_appsync_resolver": resourceAwsAppsyncResolver(), + "aws_athena_database": resourceAwsAthenaDatabase(), + "aws_athena_named_query": resourceAwsAthenaNamedQuery(), + "aws_athena_workgroup": resourceAwsAthenaWorkgroup(), + "aws_autoscaling_attachment": resourceAwsAutoscalingAttachment(), + "aws_autoscaling_group": resourceAwsAutoscalingGroup(), + "aws_autoscaling_group_tag": resourceAwsAutoscalingGroupTag(), + "aws_autoscaling_lifecycle_hook": resourceAwsAutoscalingLifecycleHook(), + "aws_autoscaling_notification": resourceAwsAutoscalingNotification(), + "aws_autoscaling_policy": resourceAwsAutoscalingPolicy(), + "aws_autoscaling_schedule": resourceAwsAutoscalingSchedule(), + "aws_autoscalingplans_scaling_plan": resourceAwsAutoScalingPlansScalingPlan(), + "aws_backup_global_settings": resourceAwsBackupGlobalSettings(), + "aws_backup_plan": resourceAwsBackupPlan(), + "aws_backup_region_settings": resourceAwsBackupRegionSettings(), + "aws_backup_selection": resourceAwsBackupSelection(), + "aws_backup_vault": resourceAwsBackupVault(), + "aws_backup_vault_notifications": resourceAwsBackupVaultNotifications(), + "aws_backup_vault_policy": resourceAwsBackupVaultPolicy(), + "aws_budgets_budget": resourceAwsBudgetsBudget(), + "aws_budgets_budget_action": resourceAwsBudgetsBudgetAction(), + "aws_chime_voice_connector": resourceAwsChimeVoiceConnector(), + "aws_chime_voice_connector_group": resourceAwsChimeVoiceConnectorGroup(), + "aws_chime_voice_connector_logging": resourceAwsChimeVoiceConnectorLogging(), + "aws_chime_voice_connector_streaming": resourceAwsChimeVoiceConnectorStreaming(), + "aws_chime_voice_connector_origination": resourceAwsChimeVoiceConnectorOrigination(), + "aws_chime_voice_connector_termination": resourceAwsChimeVoiceConnectorTermination(), + "aws_cloud9_environment_ec2": resourceAwsCloud9EnvironmentEc2(), + "aws_cloudformation_stack": resourceAwsCloudFormationStack(), + "aws_cloudformation_stack_set": resourceAwsCloudFormationStackSet(), + "aws_cloudformation_stack_set_instance": resourceAwsCloudFormationStackSetInstance(), + "aws_cloudformation_type": resourceAwsCloudFormationType(), + "aws_cloudfront_cache_policy": resourceAwsCloudFrontCachePolicy(), + "aws_cloudfront_distribution": resourceAwsCloudFrontDistribution(), + "aws_cloudfront_function": resourceAwsCloudFrontFunction(), + "aws_cloudfront_key_group": resourceAwsCloudFrontKeyGroup(), + "aws_cloudfront_monitoring_subscription": resourceAwsCloudFrontMonitoringSubscription(), + "aws_cloudfront_origin_access_identity": resourceAwsCloudFrontOriginAccessIdentity(), + "aws_cloudfront_origin_request_policy": resourceAwsCloudFrontOriginRequestPolicy(), + "aws_cloudfront_public_key": resourceAwsCloudFrontPublicKey(), + "aws_cloudfront_realtime_log_config": resourceAwsCloudFrontRealtimeLogConfig(), + "aws_cloudtrail": resourceAwsCloudTrail(), + "aws_cloudwatch_event_bus": resourceAwsCloudWatchEventBus(), + "aws_cloudwatch_event_bus_policy": resourceAwsCloudWatchEventBusPolicy(), + "aws_cloudwatch_event_permission": resourceAwsCloudWatchEventPermission(), + "aws_cloudwatch_event_rule": resourceAwsCloudWatchEventRule(), + "aws_cloudwatch_event_target": resourceAwsCloudWatchEventTarget(), + "aws_cloudwatch_event_archive": resourceAwsCloudWatchEventArchive(), + "aws_cloudwatch_event_connection": resourceAwsCloudWatchEventConnection(), + "aws_cloudwatch_event_api_destination": resourceAwsCloudWatchEventApiDestination(), + "aws_cloudwatch_log_destination": resourceAwsCloudWatchLogDestination(), + "aws_cloudwatch_log_destination_policy": resourceAwsCloudWatchLogDestinationPolicy(), + "aws_cloudwatch_log_group": resourceAwsCloudWatchLogGroup(), + "aws_cloudwatch_log_metric_filter": resourceAwsCloudWatchLogMetricFilter(), + "aws_cloudwatch_log_resource_policy": resourceAwsCloudWatchLogResourcePolicy(), + "aws_cloudwatch_log_stream": resourceAwsCloudWatchLogStream(), + "aws_cloudwatch_log_subscription_filter": resourceAwsCloudwatchLogSubscriptionFilter(), + "aws_config_aggregate_authorization": resourceAwsConfigAggregateAuthorization(), + "aws_config_config_rule": resourceAwsConfigConfigRule(), + "aws_config_configuration_aggregator": resourceAwsConfigConfigurationAggregator(), + "aws_config_configuration_recorder": resourceAwsConfigConfigurationRecorder(), + "aws_config_configuration_recorder_status": resourceAwsConfigConfigurationRecorderStatus(), + "aws_config_conformance_pack": resourceAwsConfigConformancePack(), + "aws_config_delivery_channel": resourceAwsConfigDeliveryChannel(), + "aws_config_organization_conformance_pack": resourceAwsConfigOrganizationConformancePack(), + "aws_config_organization_custom_rule": resourceAwsConfigOrganizationCustomRule(), + "aws_config_organization_managed_rule": resourceAwsConfigOrganizationManagedRule(), + "aws_config_remediation_configuration": resourceAwsConfigRemediationConfiguration(), + "aws_cognito_identity_pool": resourceAwsCognitoIdentityPool(), + "aws_cognito_identity_pool_roles_attachment": resourceAwsCognitoIdentityPoolRolesAttachment(), + "aws_cognito_identity_provider": resourceAwsCognitoIdentityProvider(), + "aws_cognito_resource_server": resourceAwsCognitoResourceServer(), + "aws_cognito_user_group": resourceAwsCognitoUserGroup(), + "aws_cognito_user_pool": resourceAwsCognitoUserPool(), + "aws_cognito_user_pool_client": resourceAwsCognitoUserPoolClient(), + "aws_cognito_user_pool_domain": resourceAwsCognitoUserPoolDomain(), + "aws_cognito_user_pool_ui_customization": resourceAwsCognitoUserPoolUICustomization(), + "aws_cloudhsm_v2_cluster": resourceAwsCloudHsmV2Cluster(), + "aws_cloudhsm_v2_hsm": resourceAwsCloudHsmV2Hsm(), + "aws_cloudwatch_composite_alarm": resourceAwsCloudWatchCompositeAlarm(), + "aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(), + "aws_cloudwatch_dashboard": resourceAwsCloudWatchDashboard(), + "aws_cloudwatch_metric_stream": resourceAwsCloudWatchMetricStream(), + "aws_cloudwatch_query_definition": resourceAwsCloudWatchQueryDefinition(), + "aws_codedeploy_app": resourceAwsCodeDeployApp(), + "aws_codedeploy_deployment_config": resourceAwsCodeDeployDeploymentConfig(), + "aws_codedeploy_deployment_group": resourceAwsCodeDeployDeploymentGroup(), + "aws_codecommit_repository": resourceAwsCodeCommitRepository(), + "aws_codecommit_trigger": resourceAwsCodeCommitTrigger(), + "aws_codeartifact_domain": resourceAwsCodeArtifactDomain(), + "aws_codeartifact_domain_permissions_policy": resourceAwsCodeArtifactDomainPermissionsPolicy(), + "aws_codeartifact_repository": resourceAwsCodeArtifactRepository(), + "aws_codeartifact_repository_permissions_policy": resourceAwsCodeArtifactRepositoryPermissionsPolicy(), + "aws_codebuild_project": resourceAwsCodeBuildProject(), + "aws_codebuild_report_group": resourceAwsCodeBuildReportGroup(), + "aws_codebuild_source_credential": resourceAwsCodeBuildSourceCredential(), + "aws_codebuild_webhook": resourceAwsCodeBuildWebhook(), + "aws_codepipeline": resourceAwsCodePipeline(), + "aws_codepipeline_webhook": resourceAwsCodePipelineWebhook(), + "aws_codestarconnections_connection": resourceAwsCodeStarConnectionsConnection(), + "aws_codestarconnections_host": resourceAwsCodeStarConnectionsHost(), + "aws_codestarnotifications_notification_rule": resourceAwsCodeStarNotificationsNotificationRule(), + "aws_connect_instance": resourceAwsConnectInstance(), + "aws_cur_report_definition": resourceAwsCurReportDefinition(), + "aws_customer_gateway": resourceAwsCustomerGateway(), + "aws_datapipeline_pipeline": resourceAwsDataPipelinePipeline(), + "aws_datasync_agent": resourceAwsDataSyncAgent(), + "aws_datasync_location_efs": resourceAwsDataSyncLocationEfs(), + "aws_datasync_location_fsx_windows_file_system": resourceAwsDataSyncLocationFsxWindowsFileSystem(), + "aws_datasync_location_nfs": resourceAwsDataSyncLocationNfs(), + "aws_datasync_location_s3": resourceAwsDataSyncLocationS3(), + "aws_datasync_location_smb": resourceAwsDataSyncLocationSmb(), + "aws_datasync_task": resourceAwsDataSyncTask(), + "aws_dax_cluster": resourceAwsDaxCluster(), + "aws_dax_parameter_group": resourceAwsDaxParameterGroup(), + "aws_dax_subnet_group": resourceAwsDaxSubnetGroup(), + "aws_db_cluster_snapshot": resourceAwsDbClusterSnapshot(), + "aws_db_event_subscription": resourceAwsDbEventSubscription(), + "aws_db_instance": resourceAwsDbInstance(), + "aws_db_instance_role_association": resourceAwsDbInstanceRoleAssociation(), + "aws_db_option_group": resourceAwsDbOptionGroup(), + "aws_db_parameter_group": resourceAwsDbParameterGroup(), + "aws_db_proxy": resourceAwsDbProxy(), + "aws_db_proxy_default_target_group": resourceAwsDbProxyDefaultTargetGroup(), + "aws_db_proxy_endpoint": resourceAwsDbProxyEndpoint(), + "aws_db_proxy_target": resourceAwsDbProxyTarget(), + "aws_db_security_group": resourceAwsDbSecurityGroup(), + "aws_db_snapshot": resourceAwsDbSnapshot(), + "aws_db_subnet_group": resourceAwsDbSubnetGroup(), + "aws_devicefarm_project": resourceAwsDevicefarmProject(), + "aws_directory_service_directory": resourceAwsDirectoryServiceDirectory(), + "aws_directory_service_conditional_forwarder": resourceAwsDirectoryServiceConditionalForwarder(), + "aws_directory_service_log_subscription": resourceAwsDirectoryServiceLogSubscription(), + "aws_dlm_lifecycle_policy": resourceAwsDlmLifecyclePolicy(), + "aws_dms_certificate": resourceAwsDmsCertificate(), + "aws_dms_endpoint": resourceAwsDmsEndpoint(), + "aws_dms_event_subscription": resourceAwsDmsEventSubscription(), + "aws_dms_replication_instance": resourceAwsDmsReplicationInstance(), + "aws_dms_replication_subnet_group": resourceAwsDmsReplicationSubnetGroup(), + "aws_dms_replication_task": resourceAwsDmsReplicationTask(), + "aws_docdb_cluster": resourceAwsDocDBCluster(), + "aws_docdb_cluster_instance": resourceAwsDocDBClusterInstance(), + "aws_docdb_cluster_parameter_group": resourceAwsDocDBClusterParameterGroup(), + "aws_docdb_cluster_snapshot": resourceAwsDocDBClusterSnapshot(), + "aws_docdb_subnet_group": resourceAwsDocDBSubnetGroup(), + "aws_dx_bgp_peer": resourceAwsDxBgpPeer(), + "aws_dx_connection": resourceAwsDxConnection(), + "aws_dx_connection_association": resourceAwsDxConnectionAssociation(), + "aws_dx_gateway": resourceAwsDxGateway(), + "aws_dx_gateway_association": resourceAwsDxGatewayAssociation(), + "aws_dx_gateway_association_proposal": resourceAwsDxGatewayAssociationProposal(), + "aws_dx_hosted_private_virtual_interface": resourceAwsDxHostedPrivateVirtualInterface(), + "aws_dx_hosted_private_virtual_interface_accepter": resourceAwsDxHostedPrivateVirtualInterfaceAccepter(), + "aws_dx_hosted_public_virtual_interface": resourceAwsDxHostedPublicVirtualInterface(), + "aws_dx_hosted_public_virtual_interface_accepter": resourceAwsDxHostedPublicVirtualInterfaceAccepter(), + "aws_dx_hosted_transit_virtual_interface": resourceAwsDxHostedTransitVirtualInterface(), + "aws_dx_hosted_transit_virtual_interface_accepter": resourceAwsDxHostedTransitVirtualInterfaceAccepter(), + "aws_dx_lag": resourceAwsDxLag(), + "aws_dx_private_virtual_interface": resourceAwsDxPrivateVirtualInterface(), + "aws_dx_public_virtual_interface": resourceAwsDxPublicVirtualInterface(), + "aws_dx_transit_virtual_interface": resourceAwsDxTransitVirtualInterface(), + "aws_dynamodb_table": resourceAwsDynamoDbTable(), + "aws_dynamodb_table_item": resourceAwsDynamoDbTableItem(), + "aws_dynamodb_tag": resourceAwsDynamodbTag(), + "aws_dynamodb_global_table": resourceAwsDynamoDbGlobalTable(), + "aws_dynamodb_kinesis_streaming_destination": resourceAwsDynamoDbKinesisStreamingDestination(), + "aws_ebs_default_kms_key": resourceAwsEbsDefaultKmsKey(), + "aws_ebs_encryption_by_default": resourceAwsEbsEncryptionByDefault(), + "aws_ebs_snapshot": resourceAwsEbsSnapshot(), + "aws_ebs_snapshot_copy": resourceAwsEbsSnapshotCopy(), + "aws_ebs_snapshot_import": resourceAwsEbsSnapshotImport(), + "aws_ebs_volume": resourceAwsEbsVolume(), + "aws_ec2_availability_zone_group": resourceAwsEc2AvailabilityZoneGroup(), + "aws_ec2_capacity_reservation": resourceAwsEc2CapacityReservation(), + "aws_ec2_carrier_gateway": resourceAwsEc2CarrierGateway(), + "aws_ec2_client_vpn_authorization_rule": resourceAwsEc2ClientVpnAuthorizationRule(), + "aws_ec2_client_vpn_endpoint": resourceAwsEc2ClientVpnEndpoint(), + "aws_ec2_client_vpn_network_association": resourceAwsEc2ClientVpnNetworkAssociation(), + "aws_ec2_client_vpn_route": resourceAwsEc2ClientVpnRoute(), + "aws_ec2_fleet": resourceAwsEc2Fleet(), + "aws_ec2_local_gateway_route": resourceAwsEc2LocalGatewayRoute(), + "aws_ec2_local_gateway_route_table_vpc_association": resourceAwsEc2LocalGatewayRouteTableVpcAssociation(), + "aws_ec2_managed_prefix_list": resourceAwsEc2ManagedPrefixList(), + "aws_ec2_tag": resourceAwsEc2Tag(), + "aws_ec2_traffic_mirror_filter": resourceAwsEc2TrafficMirrorFilter(), + "aws_ec2_traffic_mirror_filter_rule": resourceAwsEc2TrafficMirrorFilterRule(), + "aws_ec2_traffic_mirror_target": resourceAwsEc2TrafficMirrorTarget(), + "aws_ec2_traffic_mirror_session": resourceAwsEc2TrafficMirrorSession(), + "aws_ec2_transit_gateway": resourceAwsEc2TransitGateway(), + "aws_ec2_transit_gateway_peering_attachment": resourceAwsEc2TransitGatewayPeeringAttachment(), + "aws_ec2_transit_gateway_peering_attachment_accepter": resourceAwsEc2TransitGatewayPeeringAttachmentAccepter(), + "aws_ec2_transit_gateway_prefix_list_reference": resourceAwsEc2TransitGatewayPrefixListReference(), + "aws_ec2_transit_gateway_route": resourceAwsEc2TransitGatewayRoute(), + "aws_ec2_transit_gateway_route_table": resourceAwsEc2TransitGatewayRouteTable(), + "aws_ec2_transit_gateway_route_table_association": resourceAwsEc2TransitGatewayRouteTableAssociation(), + "aws_ec2_transit_gateway_route_table_propagation": resourceAwsEc2TransitGatewayRouteTablePropagation(), + "aws_ec2_transit_gateway_vpc_attachment": resourceAwsEc2TransitGatewayVpcAttachment(), + "aws_ec2_transit_gateway_vpc_attachment_accepter": resourceAwsEc2TransitGatewayVpcAttachmentAccepter(), + "aws_ecr_lifecycle_policy": resourceAwsEcrLifecyclePolicy(), + "aws_ecrpublic_repository": resourceAwsEcrPublicRepository(), + "aws_ecr_registry_policy": resourceAwsEcrRegistryPolicy(), + "aws_ecr_replication_configuration": resourceAwsEcrReplicationConfiguration(), + "aws_ecr_repository": resourceAwsEcrRepository(), + "aws_ecr_repository_policy": resourceAwsEcrRepositoryPolicy(), + "aws_ecs_capacity_provider": resourceAwsEcsCapacityProvider(), + "aws_ecs_cluster": resourceAwsEcsCluster(), + "aws_ecs_service": resourceAwsEcsService(), + "aws_ecs_tag": resourceAwsEcsTag(), + "aws_ecs_task_definition": resourceAwsEcsTaskDefinition(), + "aws_efs_access_point": resourceAwsEfsAccessPoint(), + "aws_efs_backup_policy": resourceAwsEfsBackupPolicy(), + "aws_efs_file_system": resourceAwsEfsFileSystem(), + "aws_efs_file_system_policy": resourceAwsEfsFileSystemPolicy(), + "aws_efs_mount_target": resourceAwsEfsMountTarget(), + "aws_egress_only_internet_gateway": resourceAwsEgressOnlyInternetGateway(), + "aws_eip": resourceAwsEip(), + "aws_eip_association": resourceAwsEipAssociation(), + "aws_eks_cluster": resourceAwsEksCluster(), + "aws_eks_addon": resourceAwsEksAddon(), + "aws_eks_fargate_profile": resourceAwsEksFargateProfile(), + "aws_eks_identity_provider_config": resourceAwsEksIdentityProviderConfig(), + "aws_eks_node_group": resourceAwsEksNodeGroup(), + "aws_elasticache_cluster": resourceAwsElasticacheCluster(), + "aws_elasticache_global_replication_group": resourceAwsElasticacheGlobalReplicationGroup(), + "aws_elasticache_parameter_group": resourceAwsElasticacheParameterGroup(), + "aws_elasticache_replication_group": resourceAwsElasticacheReplicationGroup(), + "aws_elasticache_security_group": resourceAwsElasticacheSecurityGroup(), + "aws_elasticache_subnet_group": resourceAwsElasticacheSubnetGroup(), + "aws_elasticache_user": resourceAwsElasticacheUser(), + "aws_elasticache_user_group": resourceAwsElasticacheUserGroup(), + "aws_elastic_beanstalk_application": resourceAwsElasticBeanstalkApplication(), + "aws_elastic_beanstalk_application_version": resourceAwsElasticBeanstalkApplicationVersion(), + "aws_elastic_beanstalk_configuration_template": resourceAwsElasticBeanstalkConfigurationTemplate(), + "aws_elastic_beanstalk_environment": resourceAwsElasticBeanstalkEnvironment(), + "aws_elasticsearch_domain": resourceAwsElasticSearchDomain(), + "aws_elasticsearch_domain_policy": resourceAwsElasticSearchDomainPolicy(), + "aws_elasticsearch_domain_saml_options": resourceAwsElasticSearchDomainSAMLOptions(), + "aws_elastictranscoder_pipeline": resourceAwsElasticTranscoderPipeline(), + "aws_elastictranscoder_preset": resourceAwsElasticTranscoderPreset(), + "aws_elb": resourceAwsElb(), + "aws_elb_attachment": resourceAwsElbAttachment(), + "aws_emr_cluster": resourceAwsEMRCluster(), + "aws_emr_instance_group": resourceAwsEMRInstanceGroup(), + "aws_emr_instance_fleet": resourceAwsEMRInstanceFleet(), + "aws_emr_managed_scaling_policy": resourceAwsEMRManagedScalingPolicy(), + "aws_emr_security_configuration": resourceAwsEMRSecurityConfiguration(), + "aws_flow_log": resourceAwsFlowLog(), + "aws_fsx_backup": resourceAwsFsxBackup(), + "aws_fsx_lustre_file_system": resourceAwsFsxLustreFileSystem(), + "aws_fsx_ontap_file_system": resourceAwsFsxOntapFileSystem(), + "aws_fsx_windows_file_system": resourceAwsFsxWindowsFileSystem(), + "aws_fms_admin_account": resourceAwsFmsAdminAccount(), + "aws_fms_policy": resourceAwsFmsPolicy(), + "aws_gamelift_alias": resourceAwsGameliftAlias(), + "aws_gamelift_build": resourceAwsGameliftBuild(), + "aws_gamelift_fleet": resourceAwsGameliftFleet(), + "aws_gamelift_game_session_queue": resourceAwsGameliftGameSessionQueue(), + "aws_glacier_vault": resourceAwsGlacierVault(), + "aws_glacier_vault_lock": resourceAwsGlacierVaultLock(), + "aws_globalaccelerator_accelerator": resourceAwsGlobalAcceleratorAccelerator(), + "aws_globalaccelerator_endpoint_group": resourceAwsGlobalAcceleratorEndpointGroup(), + "aws_globalaccelerator_listener": resourceAwsGlobalAcceleratorListener(), + "aws_glue_catalog_database": resourceAwsGlueCatalogDatabase(), + "aws_glue_catalog_table": resourceAwsGlueCatalogTable(), + "aws_glue_classifier": resourceAwsGlueClassifier(), + "aws_glue_connection": resourceAwsGlueConnection(), + "aws_glue_dev_endpoint": resourceAwsGlueDevEndpoint(), + "aws_glue_crawler": resourceAwsGlueCrawler(), + "aws_glue_data_catalog_encryption_settings": resourceAwsGlueDataCatalogEncryptionSettings(), + "aws_glue_job": resourceAwsGlueJob(), + "aws_glue_ml_transform": resourceAwsGlueMLTransform(), + "aws_glue_partition": resourceAwsGluePartition(), + "aws_glue_registry": resourceAwsGlueRegistry(), + "aws_glue_resource_policy": resourceAwsGlueResourcePolicy(), + "aws_glue_schema": resourceAwsGlueSchema(), + "aws_glue_security_configuration": resourceAwsGlueSecurityConfiguration(), + "aws_glue_trigger": resourceAwsGlueTrigger(), + "aws_glue_user_defined_function": resourceAwsGlueUserDefinedFunction(), + "aws_glue_workflow": resourceAwsGlueWorkflow(), + "aws_guardduty_detector": resourceAwsGuardDutyDetector(), + "aws_guardduty_filter": resourceAwsGuardDutyFilter(), + "aws_guardduty_invite_accepter": resourceAwsGuardDutyInviteAccepter(), + "aws_guardduty_ipset": resourceAwsGuardDutyIpset(), + "aws_guardduty_member": resourceAwsGuardDutyMember(), + "aws_guardduty_organization_admin_account": resourceAwsGuardDutyOrganizationAdminAccount(), + "aws_guardduty_organization_configuration": resourceAwsGuardDutyOrganizationConfiguration(), + "aws_guardduty_publishing_destination": resourceAwsGuardDutyPublishingDestination(), + "aws_guardduty_threatintelset": resourceAwsGuardDutyThreatintelset(), + "aws_iam_access_key": resourceAwsIamAccessKey(), + "aws_iam_account_alias": resourceAwsIamAccountAlias(), + "aws_iam_account_password_policy": resourceAwsIamAccountPasswordPolicy(), + "aws_iam_group_policy": resourceAwsIamGroupPolicy(), + "aws_iam_group": resourceAwsIamGroup(), + "aws_iam_group_membership": resourceAwsIamGroupMembership(), + "aws_iam_group_policy_attachment": resourceAwsIamGroupPolicyAttachment(), + "aws_iam_instance_profile": resourceAwsIamInstanceProfile(), + "aws_iam_openid_connect_provider": resourceAwsIamOpenIDConnectProvider(), + "aws_iam_policy": resourceAwsIamPolicy(), + "aws_iam_policy_attachment": resourceAwsIamPolicyAttachment(), + "aws_iam_role_policy_attachment": resourceAwsIamRolePolicyAttachment(), + "aws_iam_role_policy": resourceAwsIamRolePolicy(), + "aws_iam_role": resourceAwsIamRole(), + "aws_iam_saml_provider": resourceAwsIamSamlProvider(), + "aws_iam_server_certificate": resourceAwsIAMServerCertificate(), + "aws_iam_service_linked_role": resourceAwsIamServiceLinkedRole(), + "aws_iam_user_group_membership": resourceAwsIamUserGroupMembership(), + "aws_iam_user_policy_attachment": resourceAwsIamUserPolicyAttachment(), + "aws_iam_user_policy": resourceAwsIamUserPolicy(), + "aws_iam_user_ssh_key": resourceAwsIamUserSshKey(), + "aws_iam_user": resourceAwsIamUser(), + "aws_iam_user_login_profile": resourceAwsIamUserLoginProfile(), + "aws_imagebuilder_component": resourceAwsImageBuilderComponent(), + "aws_imagebuilder_distribution_configuration": resourceAwsImageBuilderDistributionConfiguration(), + "aws_imagebuilder_image": resourceAwsImageBuilderImage(), + "aws_imagebuilder_image_pipeline": resourceAwsImageBuilderImagePipeline(), + "aws_imagebuilder_image_recipe": resourceAwsImageBuilderImageRecipe(), + "aws_imagebuilder_infrastructure_configuration": resourceAwsImageBuilderInfrastructureConfiguration(), + "aws_inspector_assessment_target": resourceAWSInspectorAssessmentTarget(), + "aws_inspector_assessment_template": resourceAWSInspectorAssessmentTemplate(), + "aws_inspector_resource_group": resourceAWSInspectorResourceGroup(), + "aws_instance": resourceAwsInstance(), + "aws_internet_gateway": resourceAwsInternetGateway(), + "aws_iot_certificate": resourceAwsIotCertificate(), + "aws_iot_policy": resourceAwsIotPolicy(), + "aws_iot_policy_attachment": resourceAwsIotPolicyAttachment(), + "aws_iot_thing": resourceAwsIotThing(), + "aws_iot_thing_principal_attachment": resourceAwsIotThingPrincipalAttachment(), + "aws_iot_thing_type": resourceAwsIotThingType(), + "aws_iot_topic_rule": resourceAwsIotTopicRule(), + "aws_iot_role_alias": resourceAwsIotRoleAlias(), + "aws_key_pair": resourceAwsKeyPair(), + "aws_kinesis_analytics_application": resourceAwsKinesisAnalyticsApplication(), + "aws_kinesisanalyticsv2_application": resourceAwsKinesisAnalyticsV2Application(), + "aws_kinesisanalyticsv2_application_snapshot": resourceAwsKinesisAnalyticsV2ApplicationSnapshot(), + "aws_kinesis_firehose_delivery_stream": resourceAwsKinesisFirehoseDeliveryStream(), + "aws_kinesis_stream": resourceAwsKinesisStream(), + "aws_kinesis_stream_consumer": resourceAwsKinesisStreamConsumer(), + "aws_kinesis_video_stream": resourceAwsKinesisVideoStream(), + "aws_kms_alias": resourceAwsKmsAlias(), + "aws_kms_external_key": resourceAwsKmsExternalKey(), + "aws_kms_grant": resourceAwsKmsGrant(), + "aws_kms_key": resourceAwsKmsKey(), + "aws_kms_ciphertext": resourceAwsKmsCiphertext(), + "aws_lakeformation_data_lake_settings": resourceAwsLakeFormationDataLakeSettings(), + "aws_lakeformation_permissions": resourceAwsLakeFormationPermissions(), + "aws_lakeformation_resource": resourceAwsLakeFormationResource(), + "aws_lambda_alias": resourceAwsLambdaAlias(), + "aws_lambda_code_signing_config": resourceAwsLambdaCodeSigningConfig(), + "aws_lambda_event_source_mapping": resourceAwsLambdaEventSourceMapping(), + "aws_lambda_function_event_invoke_config": resourceAwsLambdaFunctionEventInvokeConfig(), + "aws_lambda_function": resourceAwsLambdaFunction(), + "aws_lambda_layer_version": resourceAwsLambdaLayerVersion(), + "aws_lambda_permission": resourceAwsLambdaPermission(), + "aws_lambda_provisioned_concurrency_config": resourceAwsLambdaProvisionedConcurrencyConfig(), + "aws_launch_configuration": resourceAwsLaunchConfiguration(), + "aws_launch_template": resourceAwsLaunchTemplate(), + "aws_lex_bot": resourceAwsLexBot(), + "aws_lex_bot_alias": resourceAwsLexBotAlias(), + "aws_lex_intent": resourceAwsLexIntent(), + "aws_lex_slot_type": resourceAwsLexSlotType(), + "aws_licensemanager_association": resourceAwsLicenseManagerAssociation(), + "aws_licensemanager_license_configuration": resourceAwsLicenseManagerLicenseConfiguration(), + "aws_lightsail_domain": resourceAwsLightsailDomain(), + "aws_lightsail_instance": resourceAwsLightsailInstance(), + "aws_lightsail_instance_public_ports": resourceAwsLightsailInstancePublicPorts(), + "aws_lightsail_key_pair": resourceAwsLightsailKeyPair(), + "aws_lightsail_static_ip": resourceAwsLightsailStaticIp(), + "aws_lightsail_static_ip_attachment": resourceAwsLightsailStaticIpAttachment(), + "aws_lb_cookie_stickiness_policy": resourceAwsLBCookieStickinessPolicy(), + "aws_load_balancer_policy": resourceAwsLoadBalancerPolicy(), + "aws_load_balancer_backend_server_policy": resourceAwsLoadBalancerBackendServerPolicies(), + "aws_load_balancer_listener_policy": resourceAwsLoadBalancerListenerPolicies(), + "aws_lb_ssl_negotiation_policy": resourceAwsLBSSLNegotiationPolicy(), + "aws_macie2_account": resourceAwsMacie2Account(), + "aws_macie2_classification_job": resourceAwsMacie2ClassificationJob(), + "aws_macie2_custom_data_identifier": resourceAwsMacie2CustomDataIdentifier(), + "aws_macie2_findings_filter": resourceAwsMacie2FindingsFilter(), + "aws_macie2_invitation_accepter": resourceAwsMacie2InvitationAccepter(), + "aws_macie2_member": resourceAwsMacie2Member(), + "aws_macie2_organization_admin_account": resourceAwsMacie2OrganizationAdminAccount(), + "aws_macie_member_account_association": resourceAwsMacieMemberAccountAssociation(), + "aws_macie_s3_bucket_association": resourceAwsMacieS3BucketAssociation(), + "aws_main_route_table_association": resourceAwsMainRouteTableAssociation(), + "aws_mq_broker": resourceAwsMqBroker(), + "aws_mq_configuration": resourceAwsMqConfiguration(), + "aws_media_convert_queue": resourceAwsMediaConvertQueue(), + "aws_media_package_channel": resourceAwsMediaPackageChannel(), + "aws_media_store_container": resourceAwsMediaStoreContainer(), + "aws_media_store_container_policy": resourceAwsMediaStoreContainerPolicy(), + "aws_msk_cluster": resourceAwsMskCluster(), + "aws_msk_configuration": resourceAwsMskConfiguration(), + "aws_msk_scram_secret_association": resourceAwsMskScramSecretAssociation(), + "aws_mwaa_environment": resourceAwsMwaaEnvironment(), + "aws_nat_gateway": resourceAwsNatGateway(), + "aws_network_acl": resourceAwsNetworkAcl(), + "aws_default_network_acl": resourceAwsDefaultNetworkAcl(), + "aws_neptune_cluster": resourceAwsNeptuneCluster(), + "aws_neptune_cluster_endpoint": resourceAwsNeptuneClusterEndpoint(), + "aws_neptune_cluster_instance": resourceAwsNeptuneClusterInstance(), + "aws_neptune_cluster_parameter_group": resourceAwsNeptuneClusterParameterGroup(), + "aws_neptune_cluster_snapshot": resourceAwsNeptuneClusterSnapshot(), + "aws_neptune_event_subscription": resourceAwsNeptuneEventSubscription(), + "aws_neptune_parameter_group": resourceAwsNeptuneParameterGroup(), + "aws_neptune_subnet_group": resourceAwsNeptuneSubnetGroup(), + "aws_network_acl_rule": resourceAwsNetworkAclRule(), + "aws_network_interface": resourceAwsNetworkInterface(), + "aws_network_interface_attachment": resourceAwsNetworkInterfaceAttachment(), + "aws_networkfirewall_firewall": resourceAwsNetworkFirewallFirewall(), + "aws_networkfirewall_firewall_policy": resourceAwsNetworkFirewallFirewallPolicy(), + "aws_networkfirewall_logging_configuration": resourceAwsNetworkFirewallLoggingConfiguration(), + "aws_networkfirewall_resource_policy": resourceAwsNetworkFirewallResourcePolicy(), + "aws_networkfirewall_rule_group": resourceAwsNetworkFirewallRuleGroup(), + "aws_opsworks_application": resourceAwsOpsworksApplication(), + "aws_opsworks_stack": resourceAwsOpsworksStack(), + "aws_opsworks_java_app_layer": resourceAwsOpsworksJavaAppLayer(), + "aws_opsworks_haproxy_layer": resourceAwsOpsworksHaproxyLayer(), + "aws_opsworks_static_web_layer": resourceAwsOpsworksStaticWebLayer(), + "aws_opsworks_php_app_layer": resourceAwsOpsworksPhpAppLayer(), + "aws_opsworks_rails_app_layer": resourceAwsOpsworksRailsAppLayer(), + "aws_opsworks_nodejs_app_layer": resourceAwsOpsworksNodejsAppLayer(), + "aws_opsworks_memcached_layer": resourceAwsOpsworksMemcachedLayer(), + "aws_opsworks_mysql_layer": resourceAwsOpsworksMysqlLayer(), + "aws_opsworks_ganglia_layer": resourceAwsOpsworksGangliaLayer(), + "aws_opsworks_custom_layer": resourceAwsOpsworksCustomLayer(), + "aws_opsworks_instance": resourceAwsOpsworksInstance(), + "aws_opsworks_user_profile": resourceAwsOpsworksUserProfile(), + "aws_opsworks_permission": resourceAwsOpsworksPermission(), + "aws_opsworks_rds_db_instance": resourceAwsOpsworksRdsDbInstance(), + "aws_organizations_organization": resourceAwsOrganizationsOrganization(), + "aws_organizations_account": resourceAwsOrganizationsAccount(), + "aws_organizations_delegated_administrator": resourceAwsOrganizationsDelegatedAdministrator(), + "aws_organizations_policy": resourceAwsOrganizationsPolicy(), + "aws_organizations_policy_attachment": resourceAwsOrganizationsPolicyAttachment(), + "aws_organizations_organizational_unit": resourceAwsOrganizationsOrganizationalUnit(), + "aws_placement_group": resourceAwsPlacementGroup(), + "aws_prometheus_workspace": resourceAwsPrometheusWorkspace(), + "aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(), + "aws_qldb_ledger": resourceAwsQLDBLedger(), + "aws_quicksight_group": resourceAwsQuickSightGroup(), + "aws_quicksight_group_membership": resourceAwsQuickSightGroupMembership(), + "aws_quicksight_user": resourceAwsQuickSightUser(), + "aws_ram_principal_association": resourceAwsRamPrincipalAssociation(), + "aws_ram_resource_association": resourceAwsRamResourceAssociation(), + "aws_ram_resource_share": resourceAwsRamResourceShare(), + "aws_ram_resource_share_accepter": resourceAwsRamResourceShareAccepter(), + "aws_rds_cluster": resourceAwsRDSCluster(), + "aws_rds_cluster_endpoint": resourceAwsRDSClusterEndpoint(), + "aws_rds_cluster_instance": resourceAwsRDSClusterInstance(), + "aws_rds_cluster_parameter_group": resourceAwsRDSClusterParameterGroup(), + "aws_rds_cluster_role_association": resourceAwsRDSClusterRoleAssociation(), + "aws_rds_global_cluster": resourceAwsRDSGlobalCluster(), + "aws_redshift_cluster": resourceAwsRedshiftCluster(), + "aws_redshift_security_group": resourceAwsRedshiftSecurityGroup(), + "aws_redshift_parameter_group": resourceAwsRedshiftParameterGroup(), + "aws_redshift_subnet_group": resourceAwsRedshiftSubnetGroup(), + "aws_redshift_snapshot_copy_grant": resourceAwsRedshiftSnapshotCopyGrant(), + "aws_redshift_snapshot_schedule": resourceAwsRedshiftSnapshotSchedule(), + "aws_redshift_snapshot_schedule_association": resourceAwsRedshiftSnapshotScheduleAssociation(), + "aws_redshift_event_subscription": resourceAwsRedshiftEventSubscription(), + "aws_resourcegroups_group": resourceAwsResourceGroupsGroup(), + "aws_route53_delegation_set": resourceAwsRoute53DelegationSet(), + "aws_route53_hosted_zone_dnssec": resourceAwsRoute53HostedZoneDnssec(), + "aws_route53_key_signing_key": resourceAwsRoute53KeySigningKey(), + "aws_route53_query_log": resourceAwsRoute53QueryLog(), + "aws_route53_record": resourceAwsRoute53Record(), + "aws_route53_zone_association": resourceAwsRoute53ZoneAssociation(), + "aws_route53_vpc_association_authorization": resourceAwsRoute53VPCAssociationAuthorization(), + "aws_route53_zone": resourceAwsRoute53Zone(), + "aws_route53_health_check": resourceAwsRoute53HealthCheck(), + "aws_route53_resolver_dnssec_config": resourceAwsRoute53ResolverDnssecConfig(), + "aws_route53_resolver_endpoint": resourceAwsRoute53ResolverEndpoint(), + "aws_route53_resolver_firewall_config": resourceAwsRoute53ResolverFirewallConfig(), + "aws_route53_resolver_firewall_domain_list": resourceAwsRoute53ResolverFirewallDomainList(), + "aws_route53_resolver_firewall_rule": resourceAwsRoute53ResolverFirewallRule(), + "aws_route53_resolver_firewall_rule_group": resourceAwsRoute53ResolverFirewallRuleGroup(), + "aws_route53_resolver_firewall_rule_group_association": resourceAwsRoute53ResolverFirewallRuleGroupAssociation(), + "aws_route53_resolver_query_log_config": resourceAwsRoute53ResolverQueryLogConfig(), + "aws_route53_resolver_query_log_config_association": resourceAwsRoute53ResolverQueryLogConfigAssociation(), + "aws_route53_resolver_rule_association": resourceAwsRoute53ResolverRuleAssociation(), + "aws_route53_resolver_rule": resourceAwsRoute53ResolverRule(), + "aws_route53recoverycontrolconfig_cluster": resourceAwsRoute53RecoveryControlConfigCluster(), + "aws_route53recoverycontrolconfig_control_panel": resourceAwsRoute53RecoveryControlConfigControlPanel(), + "aws_route53recoverycontrolconfig_routing_control": resourceAwsRoute53RecoveryControlConfigRoutingControl(), + "aws_route53recoverycontrolconfig_safety_rule": resourceAwsRoute53RecoveryControlConfigSafetyRule(), + "aws_route53recoveryreadiness_cell": resourceAwsRoute53RecoveryReadinessCell(), + "aws_route53recoveryreadiness_readiness_check": resourceAwsRoute53RecoveryReadinessReadinessCheck(), + "aws_route53recoveryreadiness_recovery_group": resourceAwsRoute53RecoveryReadinessRecoveryGroup(), + "aws_route53recoveryreadiness_resource_set": resourceAwsRoute53RecoveryReadinessResourceSet(), "aws_route": resourceAwsRoute(), "aws_route_table": resourceAwsRouteTable(), "aws_default_route_table": resourceAwsDefaultRouteTable(), diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go new file mode 100644 index 00000000000..165b4824e30 --- /dev/null +++ b/aws/resource_aws_connect_instance.go @@ -0,0 +1,284 @@ +package aws + +import ( + "context" + "fmt" + "log" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/connect" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/connect/waiter" +) + +var resourceConnectInstanceAttributesMapping = map[string]string{ + connect.InstanceAttributeTypeInboundCalls: "inbound_calls_enabled", + connect.InstanceAttributeTypeOutboundCalls: "outbound_calls_enabled", + connect.InstanceAttributeTypeContactflowLogs: "contact_flow_logs_enabled", + connect.InstanceAttributeTypeContactLens: "contact_lens_enabled", + connect.InstanceAttributeTypeAutoResolveBestVoices: "auto_resolve_best_voices", + connect.InstanceAttributeTypeUseCustomTtsVoices: "use_custom_tts_voices", + connect.InstanceAttributeTypeEarlyMedia: "early_media_enabled", +} + +func resourceAwsConnectInstance() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceAwsConnectInstanceCreate, + ReadContext: resourceAwsConnectInstanceRead, + UpdateContext: resourceAwsConnectInstanceUpdate, + DeleteContext: resourceAwsConnectInstanceDelete, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "identity_management_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: connect.DirectoryTypeConnectManaged, + ValidateFunc: validation.StringInSlice([]string{ + connect.DirectoryTypeSaml, + connect.DirectoryTypeConnectManaged, + connect.DirectoryTypeExistingDirectory, + }, false), + }, + "directory_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(12, 12), + }, + "instance_alias": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 64), + }, + "inbound_calls_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "outbound_calls_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "early_media_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "contact_flow_logs_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "contact_lens_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "auto_resolve_best_voices": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "use_custom_tts_voices": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "created_time": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "service_role": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceAwsConnectInstanceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).connectconn + + input := &connect.CreateInstanceInput{ + ClientToken: aws.String(resource.UniqueId()), + IdentityManagementType: aws.String(d.Get("identity_management_type").(string)), + InstanceAlias: aws.String(d.Get("instance_alias").(string)), + InboundCallsEnabled: aws.Bool(d.Get("inbound_calls_enabled").(bool)), + OutboundCallsEnabled: aws.Bool(d.Get("outbound_calls_enabled").(bool)), + } + + if _, ok := d.GetOk("directory_id"); ok { + input.DirectoryId = aws.String(d.Get("directory_id").(string)) + } + + log.Printf("[DEBUG] Creating Connect Instance %s", input) + + output, err := conn.CreateInstanceWithContext(ctx, input) + + if err != nil { + return diag.FromErr(fmt.Errorf("error reading Connect Instance (%s): %s", d.Id(), err)) + } + + d.SetId(aws.StringValue(output.Id)) + + if _, err := waiter.InstanceCreated(ctx, conn, d.Id()); err != nil { + return diag.FromErr(fmt.Errorf("error waiting for Connect instance creation (%s): %s", d.Id(), err)) + } + + for att := range resourceConnectInstanceAttributesMapping { + rKey := resourceConnectInstanceAttributesMapping[att] + val := d.Get(rKey) + err := resourceAwsConnectInstanceUpdateAttribute(ctx, conn, d.Id(), att, strconv.FormatBool(val.(bool))) + if err != nil { + return diag.FromErr(fmt.Errorf("error setting Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) + } + } + + return resourceAwsConnectInstanceRead(ctx, d, meta) +} + +func resourceAwsConnectInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).connectconn + + for att := range resourceConnectInstanceAttributesMapping { + rKey := resourceConnectInstanceAttributesMapping[att] + if d.HasChange(rKey) { + _, n := d.GetChange(rKey) + err := resourceAwsConnectInstanceUpdateAttribute(ctx, conn, d.Id(), att, strconv.FormatBool(n.(bool))) + if err != nil { + return diag.FromErr(fmt.Errorf("error updating Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) + } + } + } + + return nil +} +func resourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).connectconn + + input := connect.DescribeInstanceInput{ + InstanceId: aws.String(d.Id()), + } + + log.Printf("[DEBUG] Reading Connect Instance %s", d.Id()) + + output, err := conn.DescribeInstanceWithContext(ctx, &input) + + if isAWSErr(err, connect.ErrCodeResourceNotFoundException, "") { + log.Printf("[WARN] Connect Instance (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return diag.FromErr(fmt.Errorf("error reading Connect Instance (%s): %s", d.Id(), err)) + } + + instance := output.Instance + + d.SetId(aws.StringValue(instance.Id)) + + d.Set("arn", instance.Arn) + d.Set("created_time", instance.CreatedTime.Format(time.RFC3339)) + d.Set("identity_management_type", instance.IdentityManagementType) + d.Set("instance_alias", instance.InstanceAlias) + d.Set("inbound_calls_enabled", instance.InboundCallsEnabled) + d.Set("outbound_calls_enabled", instance.OutboundCallsEnabled) + d.Set("status", instance.InstanceStatus) + d.Set("service_role", instance.ServiceRole) + + for att := range resourceConnectInstanceAttributesMapping { + value, err := resourceAwsConnectInstanceReadAttribute(ctx, conn, d.Id(), att) + if err != nil { + return diag.FromErr(fmt.Errorf("error reading Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) + } + d.Set(resourceConnectInstanceAttributesMapping[att], value) + } + + return nil +} + +func resourceAwsConnectInstanceDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*AWSClient).connectconn + + input := &connect.DeleteInstanceInput{ + InstanceId: aws.String(d.Id()), + } + + log.Printf("[DEBUG] Deleting Connect Instance %s", d.Id()) + + _, err := conn.DeleteInstance(input) + + if err != nil { + return diag.FromErr(fmt.Errorf("error deleting Connect Instance (%s): %s", d.Id(), err)) + } + + // For using an existing directory, + // There is no proper way. If the Connect instance was unregistered from the attached directory. + // We don't have a PENDING_DELETION or DELETED for the Connect instance. + // Deleting the directory immediately after removing the connect instance + // will cause an error because it is still has authorized applications. + // There is no specific wait time for this check, so we'll wait a few seconds + // to make sure the Connect instance will deregister. + + imt := d.Get("identity_management_type") + + if imt.(string) == connect.DirectoryTypeExistingDirectory { + log.Print("[INFO] Waiting for Connect to deregister from the Directory Service") + time.Sleep(30 * time.Second) + } + + return nil +} + +func resourceAwsConnectInstanceUpdateAttribute(ctx context.Context, conn *connect.Connect, instanceID string, attributeType string, value string) error { + input := &connect.UpdateInstanceAttributeInput{ + InstanceId: aws.String(instanceID), + AttributeType: aws.String(attributeType), + Value: aws.String(value), + } + + _, err := conn.UpdateInstanceAttributeWithContext(ctx, input) + + if err != nil { + return err + } + + return nil +} + +func resourceAwsConnectInstanceReadAttribute(ctx context.Context, conn *connect.Connect, instanceID string, attributeType string) (bool, error) { + input := &connect.DescribeInstanceAttributeInput{ + InstanceId: aws.String(instanceID), + AttributeType: aws.String(attributeType), + } + + output, err := conn.DescribeInstanceAttributeWithContext(ctx, input) + + if err != nil { + return false, err + } + + result, parseerr := strconv.ParseBool(*output.Attribute.Value) + return result, parseerr +} diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go new file mode 100644 index 00000000000..04a71c8a68f --- /dev/null +++ b/aws/resource_aws_connect_instance_test.go @@ -0,0 +1,346 @@ +package aws + +import ( + "context" + "fmt" + "log" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/connect" + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func init() { + resource.AddTestSweepers("aws_connect_instance", &resource.Sweeper{ + Name: "aws_connect_instance", + F: testSweepConnectInstance, + }) +} + +func testSweepConnectInstance(region string) error { + client, err := sharedClientForRegion(region) + if err != nil { + return fmt.Errorf("error getting client: %s", err) + } + conn := client.(*AWSClient).connectconn + ctx := context.Background() + // MaxResults: Maximum value of 10. https://docs.aws.amazon.com/connect/latest/APIReference/API_ListInstances.html + input := &connect.ListInstancesInput{MaxResults: aws.Int64(10)} + var sweeperErrs *multierror.Error + for { + listOutput, err := conn.ListInstances(input) + if err != nil { + if testSweepSkipSweepError(err) { + log.Printf("[WARN] Skipping Connect Instance sweep for %s: %s", region, err) + return nil + } + return fmt.Errorf("Error retrieving Connect Instance: %s", err) + } + for _, instance := range listOutput.InstanceSummaryList { + id := aws.StringValue(instance.Id) + r := resourceAwsConnectInstance() + d := r.Data(nil) + d.SetId(id) + + diags := r.DeleteContext(ctx, d, client) + for i := range diags { + if diags[i].Severity == diag.Error { + log.Printf("[ERROR] %s", diags[i].Summary) + sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf(diags[i].Summary)) + continue + } + } + } + if aws.StringValue(listOutput.NextToken) == "" { + break + } + input.NextToken = listOutput.NextToken + } + return sweeperErrs.ErrorOrNil() +} +func TestAccAwsConnectInstance_basic(t *testing.T) { + var v connect.DescribeInstanceOutput + rInt := acctest.RandInt() + resourceName := "aws_connect_instance.foo" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsConnectInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsConnectInstanceConfigBasic(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsConnectInstanceExists(resourceName, &v), + resource.TestCheckResourceAttrSet(resourceName, "id"), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), + resource.TestCheckResourceAttrSet(resourceName, "instance_alias"), + resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices", "true"), + resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices", "false"), + resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), + resource.TestCheckResourceAttrSet(resourceName, "service_role"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAwsConnectInstance_custom(t *testing.T) { + var v connect.DescribeInstanceOutput + rInt := acctest.RandInt() + resourceName := "aws_connect_instance.foo" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsConnectInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsConnectInstanceConfigCustom(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsConnectInstanceExists(resourceName, &v), + resource.TestCheckResourceAttrSet(resourceName, "id"), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), + resource.TestCheckResourceAttrSet(resourceName, "instance_alias"), + resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices", "false"), + resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices", "true"), + resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), + resource.TestCheckResourceAttrSet(resourceName, "service_role"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAwsConnectInstance_directory(t *testing.T) { + var v connect.DescribeInstanceOutput + rInt := acctest.RandInt() + resourceName := "aws_connect_instance.foo" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsConnectInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsConnectInstanceConfigDirectory(rInt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeExistingDirectory), + testAccCheckAwsConnectInstanceExists(resourceName, &v), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"directory_id"}, + }, + }, + }) +} + +func testAccCheckAwsConnectInstanceExists(resourceName string, function *connect.DescribeInstanceOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Connect instance not found: %s", resourceName) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("Connect instance ID not set") + } + + conn := testAccProvider.Meta().(*AWSClient).connectconn + + input := &connect.DescribeInstanceInput{ + InstanceId: aws.String(rs.Primary.ID), + } + + getFunction, err := conn.DescribeInstance(input) + if err != nil { + return err + } + + *function = *getFunction + + return nil + } +} + +func TestAccAwsConnectInstance_saml(t *testing.T) { + var v connect.DescribeInstanceOutput + rInt := acctest.RandInt() + resourceName := "aws_connect_instance.foo" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsConnectInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsConnectInstanceConfigSAML(rInt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeSaml), + testAccCheckAwsConnectInstanceExists(resourceName, &v), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} +func testAccCheckAwsConnectInstanceDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_connect_instance" { + continue + } + + conn := testAccProvider.Meta().(*AWSClient).connectconn + + instanceID := rs.Primary.ID + + input := &connect.DescribeInstanceInput{ + InstanceId: aws.String(instanceID), + } + + _, connectErr := conn.DescribeInstance(input) + // Verify the error is what we want + if connectErr != nil { + if awsErr, ok := connectErr.(awserr.Error); ok && awsErr.Code() == "ResourceNotFoundException" { + continue + } + return connectErr + } + } + return nil +} + +func testAccAwsConnectInstanceConfigBasic(rInt int) string { + return fmt.Sprintf(` +resource "aws_connect_instance" "foo" { + identity_management_type = "CONNECT_MANAGED" + instance_alias = "resource-test-terraform-%d" + inbound_calls_enabled = true + outbound_calls_enabled = true +} +`, rInt) +} + +func testAccAwsConnectInstanceConfigCustom(rInt int) string { + return fmt.Sprintf(` +resource "aws_connect_instance" "foo" { + identity_management_type = "CONNECT_MANAGED" + instance_alias = "resource-test-terraform-%d" + inbound_calls_enabled = false + outbound_calls_enabled = true + early_media_enabled = false + contact_flow_logs_enabled = true + contact_lens_enabled = false + auto_resolve_best_voices = false + use_custom_tts_voices = true +} +`, rInt) +} + +func testAccAwsConnectInstanceConfigDirectory(rInt int) string { + return fmt.Sprintf(` +data "aws_availability_zones" "available" { + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_vpc" "test" { + cidr_block = "10.0.0.0/16" + tags = { + Name = "terraform-testacc-directory-service-directory-tags" + } +} + +resource "aws_subnet" "test1" { + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[0] + cidr_block = "10.0.1.0/24" + tags = { + Name = "tf-acc-directory-service-directory-foo" + } +} + +resource "aws_subnet" "test2" { + vpc_id = aws_vpc.test.id + availability_zone = data.aws_availability_zones.available.names[1] + cidr_block = "10.0.2.0/24" + tags = { + Name = "tf-acc-directory-service-directory-test" + } +} + +resource "aws_directory_service_directory" "test" { + name = "corp.notexample.com" + password = "SuperSecretPassw0rd" + size = "Small" + + vpc_settings { + vpc_id = aws_vpc.test.id + subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id] + } +} + +resource "aws_connect_instance" "foo" { + directory_id = aws_directory_service_directory.test.id + identity_management_type = "EXISTING_DIRECTORY" + instance_alias = "resource-test-terraform-%d" + inbound_calls_enabled = true + outbound_calls_enabled = true + + depends_on = [aws_directory_service_directory.test] +} +`, rInt) +} + +func testAccAwsConnectInstanceConfigSAML(rInt int) string { + return fmt.Sprintf(` +resource "aws_connect_instance" "foo" { + identity_management_type = "SAML" + instance_alias = "resource-test-terraform-%d" + inbound_calls_enabled = true + outbound_calls_enabled = true +} +`, rInt) +} diff --git a/website/docs/d/connect_instance.html.markdown b/website/docs/d/connect_instance.html.markdown new file mode 100644 index 00000000000..a15fdb27248 --- /dev/null +++ b/website/docs/d/connect_instance.html.markdown @@ -0,0 +1,55 @@ +--- +subcategory: "Connect" +layout: "aws" +page_title: "AWS: aws_connect_instance" +description: |- + Provides details about a specific Connect Instance. +--- + +# Data Source: aws_connect_instance + +Provides details about a specific Amazon Connect Instance. + +## Example Usage +By instance_alias + +```hcl +data "aws_connect_instance" "foo" { + instance_alias = "foo" +} +``` + +By instance_id + +```hcl +data "aws_connect_instance" "foo" { + instance_id = "97afc98d-101a-ba98-ab97-ae114fc115ec" +} +``` + +## Argument Reference + +~> **NOTE:** One of either `instance_id` or `instance_alias` is required. + +The following arguments are supported: + +* `instance_id` - (Optional) Returns information on a specific connect instance by id + +* `instance_alias` - (Optional) Returns information on a specific connect instance by alias + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `created_time` - Specifies When the instance was created. +* `arn` - The Amazon Resource Name (ARN) of the instance. +* `identity_management_type` - Specifies The identity management type attached to the instance. +* `inbound_calls_enabled` - Specifies Whether inbound calls are enabled. +* `outbound_calls_enabled` - Specifies Whether outbound calls are enabled. +* `early_media_enabled` - Specifies Whether early media for outbound calls is enabled . +* `contact_flow_logs_enabled` - Specifies Whether contact flow logs are enabled. +* `contact_lens_enabled` - Specifies Whether contact lens is enabled. +* `auto_resolve_best_voices` - Specifies Whether auto resolve best voices is enabled. +* `use_custom_tts_voices` - Specifies Whether use custom tts voices is enabled. +* `status` - Specifies The state of the instance. +* `service_role` - The service role of the instance. diff --git a/website/docs/r/connect_instance.html.markdown b/website/docs/r/connect_instance.html.markdown new file mode 100644 index 00000000000..39f73ab6ecd --- /dev/null +++ b/website/docs/r/connect_instance.html.markdown @@ -0,0 +1,54 @@ +--- +subcategory: "Connect" +layout: "aws" +page_title: "AWS: aws_connect_instance" +description: |- + Provides details about a specific Connect Instance. +--- + +# Resource: aws_connect_instance + +Provides an Amazon Connect instance resource. For more information see +[Amazon Connect: Getting Started](https://docs.aws.amazon.com/connect/latest/adminguide/amazon-connect-get-started.html) + +## Example Usage + +```hcl +resource "aws_connect_instance" "foo" { + identity_management_type = "CONNECT_MANAGED" + instance_alias = "resource-test-terraform-connect" + inbound_calls_enabled = true + outbound_calls_enabled = true +} +``` + +## Argument Reference + + +The following arguments are supported: + +* `identity_management_type` - (Optional) Specifies The identity management type attached to the instance. Defaults to `CONNECT_MANAGED`. Allowed Values are: `SAML`, `CONNECT_MANAGED`, `EXISTING_DIRECTORY`. +* `directory_id` - (Optional) The identifier for the directory if identity_management_type is `EXISTING_DIRECTORY`. +* `instance_alias` - (Optional) Specifies the name of the instance +* `inbound_calls_enabled` - (Optional) Specifies Whether inbound calls are enabled. Defaults to `true` +* `outbound_calls_enabled` - (Optional) Specifies Whether outbound calls are enabled. * `inbound_calls_enabled` - (Optional) Specifies Whether inbound calls are enabled. Defaults to `true` +* `early_media_enabled` - (Optional) Specifies Whether early media for outbound calls is enabled . Defaults to `true` if outbound calls is enabled +* `contact_flow_logs_enabled` - (Optional) Specifies Whether contact flow logs are enabled. Defaults to `false` +* `contact_lens_enabled` - (Optional) Specifies Whether contact lens is enabled. Defaults to `true` +* `auto_resolve_best_voices` - (Optional) Specifies Whether auto resolve best voices is enabled. Defaults to `true` +* `use_custom_tts_voices` - (Optional) Specifies Whether use custom tts voices is enabled. Defaults to `false` + +### Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 5 mins) Used when creating the instance. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `created_time` - Specifies When the instance was created. +* `arn` - The Amazon Resource Name (ARN) of the instance. +* `status` - Specifies The state of the instance. +* `service_role` - The service role of the instance. From 6ef35c532f2fa6b0cc9d420e5786c414fcb0d4a4 Mon Sep 17 00:00:00 2001 From: Ahmed Bebars Date: Sat, 27 Feb 2021 23:08:36 -0500 Subject: [PATCH 02/22] Code review --- aws/data_source_aws_connect_instance_test.go | 30 +++++------ aws/resource_aws_connect_instance.go | 26 +++++----- aws/resource_aws_connect_instance_test.go | 54 ++++++++++---------- 3 files changed, 54 insertions(+), 56 deletions(-) diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index 2a4ed392c25..0ffd958a16b 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -10,7 +10,7 @@ import ( ) func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { - rInt := acctest.RandInt() + rName := acctest.RandomWithPrefix("datasource-test-terraform") resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -25,13 +25,12 @@ func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { ExpectError: regexp.MustCompile(`error finding Connect Instance by instance_alias`), }, { - Config: testAccAwsConnectInstanceDataSourceConfigBasic(rInt), + Config: testAccAwsConnectInstanceDataSourceConfigBasic(rName), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet(resourceName, "id"), - resource.TestCheckResourceAttrSet(resourceName, "arn"), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), resource.TestCheckResourceAttrSet(resourceName, "created_time"), resource.TestCheckResourceAttrSet(resourceName, "identity_management_type"), - resource.TestCheckResourceAttrSet(resourceName, "instance_alias"), + resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), resource.TestCheckResourceAttrSet(resourceName, "inbound_calls_enabled"), resource.TestCheckResourceAttrSet(resourceName, "outbound_calls_enabled"), resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), @@ -48,20 +47,19 @@ func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { } func TestAccAwsConnectInstanceDataSource_alias(t *testing.T) { - rInt := acctest.RandInt() + rName := acctest.RandomWithPrefix("datasource-test-terraform") resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccAwsConnectInstanceDataSourceConfigAlias(rInt), + Config: testAccAwsConnectInstanceDataSourceConfigAlias(rName), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttrSet(resourceName, "id"), - resource.TestCheckResourceAttrSet(resourceName, "arn"), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), resource.TestCheckResourceAttrSet(resourceName, "created_time"), resource.TestCheckResourceAttrSet(resourceName, "identity_management_type"), - resource.TestCheckResourceAttrSet(resourceName, "instance_alias"), + resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), resource.TestCheckResourceAttrSet(resourceName, "inbound_calls_enabled"), resource.TestCheckResourceAttrSet(resourceName, "outbound_calls_enabled"), resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), @@ -89,26 +87,26 @@ data "aws_connect_instance" "foo" { } ` -func testAccAwsConnectInstanceDataSourceConfigBasic(rInt int) string { +func testAccAwsConnectInstanceDataSourceConfigBasic(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "foo" { - instance_alias = "datasource-test-terraform-%d" + instance_alias = %[1]q } data "aws_connect_instance" "foo" { instance_id = aws_connect_instance.foo.id } -`, rInt) +`, rName) } -func testAccAwsConnectInstanceDataSourceConfigAlias(rInt int) string { +func testAccAwsConnectInstanceDataSourceConfigAlias(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "foo" { - instance_alias = "datasource-test-terraform-%d" + instance_alias = %[1]q } data "aws_connect_instance" "foo" { instance_alias = aws_connect_instance.foo.instance_alias } -`, rInt) +`, rName) } diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go index 165b4824e30..4ee272ecc88 100644 --- a/aws/resource_aws_connect_instance.go +++ b/aws/resource_aws_connect_instance.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "regexp" "strconv" "time" @@ -39,15 +40,11 @@ func resourceAwsConnectInstance() *schema.Resource { Schema: map[string]*schema.Schema{ "identity_management_type": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: connect.DirectoryTypeConnectManaged, - ValidateFunc: validation.StringInSlice([]string{ - connect.DirectoryTypeSaml, - connect.DirectoryTypeConnectManaged, - connect.DirectoryTypeExistingDirectory, - }, false), + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: connect.DirectoryTypeConnectManaged, + ValidateFunc: validation.StringInSlice(connect.DirectoryType_Values(), false), }, "directory_id": { Type: schema.TypeString, @@ -56,10 +53,13 @@ func resourceAwsConnectInstance() *schema.Resource { ValidateFunc: validation.StringLenBetween(12, 12), }, "instance_alias": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 64), + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 64), + validation.StringMatch(regexp.MustCompile(`^(?!d-)([\da-zA-Z]+)([-]*[\da-zA-Z])*$`), "must contain only alphanumeric hyphen and underscore characters"), + ), }, "inbound_calls_enabled": { Type: schema.TypeBool, diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 04a71c8a68f..3304a29c04c 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -66,7 +67,7 @@ func testSweepConnectInstance(region string) error { } func TestAccAwsConnectInstance_basic(t *testing.T) { var v connect.DescribeInstanceOutput - rInt := acctest.RandInt() + rName := acctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ @@ -75,14 +76,14 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccAwsConnectInstanceConfigBasic(rInt), + Config: testAccAwsConnectInstanceConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsConnectInstanceExists(resourceName, &v), - resource.TestCheckResourceAttrSet(resourceName, "id"), resource.TestCheckResourceAttrSet(resourceName, "arn"), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), resource.TestCheckResourceAttrSet(resourceName, "created_time"), resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), - resource.TestCheckResourceAttrSet(resourceName, "instance_alias"), + resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "false"), @@ -91,7 +92,7 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices", "false"), resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), - resource.TestCheckResourceAttrSet(resourceName, "service_role"), + testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), ), }, { @@ -105,7 +106,7 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { func TestAccAwsConnectInstance_custom(t *testing.T) { var v connect.DescribeInstanceOutput - rInt := acctest.RandInt() + rName := acctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ @@ -114,14 +115,13 @@ func TestAccAwsConnectInstance_custom(t *testing.T) { CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccAwsConnectInstanceConfigCustom(rInt), + Config: testAccAwsConnectInstanceConfigCustom(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsConnectInstanceExists(resourceName, &v), - resource.TestCheckResourceAttrSet(resourceName, "id"), - resource.TestCheckResourceAttrSet(resourceName, "arn"), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), resource.TestCheckResourceAttrSet(resourceName, "created_time"), resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), - resource.TestCheckResourceAttrSet(resourceName, "instance_alias"), + resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), @@ -130,7 +130,7 @@ func TestAccAwsConnectInstance_custom(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices", "true"), resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), - resource.TestCheckResourceAttrSet(resourceName, "service_role"), + testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), ), }, { @@ -144,7 +144,7 @@ func TestAccAwsConnectInstance_custom(t *testing.T) { func TestAccAwsConnectInstance_directory(t *testing.T) { var v connect.DescribeInstanceOutput - rInt := acctest.RandInt() + rName := acctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ @@ -153,7 +153,7 @@ func TestAccAwsConnectInstance_directory(t *testing.T) { CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccAwsConnectInstanceConfigDirectory(rInt), + Config: testAccAwsConnectInstanceConfigDirectory(rName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeExistingDirectory), testAccCheckAwsConnectInstanceExists(resourceName, &v), @@ -199,7 +199,7 @@ func testAccCheckAwsConnectInstanceExists(resourceName string, function *connect func TestAccAwsConnectInstance_saml(t *testing.T) { var v connect.DescribeInstanceOutput - rInt := acctest.RandInt() + rName := acctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ @@ -208,7 +208,7 @@ func TestAccAwsConnectInstance_saml(t *testing.T) { CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccAwsConnectInstanceConfigSAML(rInt), + Config: testAccAwsConnectInstanceConfigSAML(rName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeSaml), testAccCheckAwsConnectInstanceExists(resourceName, &v), @@ -248,22 +248,22 @@ func testAccCheckAwsConnectInstanceDestroy(s *terraform.State) error { return nil } -func testAccAwsConnectInstanceConfigBasic(rInt int) string { +func testAccAwsConnectInstanceConfigBasic(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "foo" { identity_management_type = "CONNECT_MANAGED" - instance_alias = "resource-test-terraform-%d" + instance_alias = %[1]q inbound_calls_enabled = true outbound_calls_enabled = true } -`, rInt) +`, rName) } -func testAccAwsConnectInstanceConfigCustom(rInt int) string { +func testAccAwsConnectInstanceConfigCustom(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "foo" { identity_management_type = "CONNECT_MANAGED" - instance_alias = "resource-test-terraform-%d" + instance_alias = %[1]q inbound_calls_enabled = false outbound_calls_enabled = true early_media_enabled = false @@ -272,10 +272,10 @@ resource "aws_connect_instance" "foo" { auto_resolve_best_voices = false use_custom_tts_voices = true } -`, rInt) +`, rName) } -func testAccAwsConnectInstanceConfigDirectory(rInt int) string { +func testAccAwsConnectInstanceConfigDirectory(rName string) string { return fmt.Sprintf(` data "aws_availability_zones" "available" { state = "available" @@ -325,22 +325,22 @@ resource "aws_directory_service_directory" "test" { resource "aws_connect_instance" "foo" { directory_id = aws_directory_service_directory.test.id identity_management_type = "EXISTING_DIRECTORY" - instance_alias = "resource-test-terraform-%d" + instance_alias = %[1]q inbound_calls_enabled = true outbound_calls_enabled = true depends_on = [aws_directory_service_directory.test] } -`, rInt) +`, rName) } -func testAccAwsConnectInstanceConfigSAML(rInt int) string { +func testAccAwsConnectInstanceConfigSAML(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "foo" { identity_management_type = "SAML" - instance_alias = "resource-test-terraform-%d" + instance_alias = %[1]q inbound_calls_enabled = true outbound_calls_enabled = true } -`, rInt) +`, rName) } From bc1cd06c05d71cdefb2e5a47755f2d05014d3cc7 Mon Sep 17 00:00:00 2001 From: Ahmed Bebars Date: Sat, 27 Feb 2021 23:09:53 -0500 Subject: [PATCH 03/22] Code review --- aws/resource_aws_connect_instance_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 3304a29c04c..d462995ba67 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -79,7 +79,6 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { Config: testAccAwsConnectInstanceConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsConnectInstanceExists(resourceName, &v), - resource.TestCheckResourceAttrSet(resourceName, "arn"), testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), resource.TestCheckResourceAttrSet(resourceName, "created_time"), resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), From 1d8b346eaeb4b6f2520292953d6568f427057615 Mon Sep 17 00:00:00 2001 From: Ahmed Bebars Date: Sun, 28 Feb 2021 16:26:22 -0500 Subject: [PATCH 04/22] Fix regex --- aws/resource_aws_connect_instance.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go index 4ee272ecc88..c54a0903a93 100644 --- a/aws/resource_aws_connect_instance.go +++ b/aws/resource_aws_connect_instance.go @@ -58,7 +58,8 @@ func resourceAwsConnectInstance() *schema.Resource { ForceNew: true, ValidateFunc: validation.All( validation.StringLenBetween(1, 64), - validation.StringMatch(regexp.MustCompile(`^(?!d-)([\da-zA-Z]+)([-]*[\da-zA-Z])*$`), "must contain only alphanumeric hyphen and underscore characters"), + validation.StringMatch(regexp.MustCompile(`^([\da-zA-Z]+)([\da-zA-Z-]+)$`), "must contain only alphanumeric hyphen and underscore characters"), + validation.StringDoesNotMatch(regexp.MustCompile(`^(d-).+$`), "can not start with d-"), ), }, "inbound_calls_enabled": { From 0b686fc995c54193293c4b148684ea93c2e94a02 Mon Sep 17 00:00:00 2001 From: Ahmed Bebars <1381372+abebars@users.noreply.github.com> Date: Fri, 23 Apr 2021 04:44:15 +0000 Subject: [PATCH 05/22] Add Error Check --- aws/data_source_aws_connect_instance_test.go | 2 ++ aws/resource_aws_connect_instance_test.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index 0ffd958a16b..b1493ae7033 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -14,6 +14,7 @@ func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), Providers: testAccProviders, Steps: []resource.TestStep{ { @@ -51,6 +52,7 @@ func TestAccAwsConnectInstanceDataSource_alias(t *testing.T) { resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), Providers: testAccProviders, Steps: []resource.TestStep{ { diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index d462995ba67..47b250338f1 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -72,6 +72,7 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ @@ -110,6 +111,7 @@ func TestAccAwsConnectInstance_custom(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ @@ -148,6 +150,7 @@ func TestAccAwsConnectInstance_directory(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ @@ -203,6 +206,7 @@ func TestAccAwsConnectInstance_saml(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ From c5f5209b824621f3505718988d5dd2638c1d56f6 Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Thu, 22 Jul 2021 13:01:55 -0400 Subject: [PATCH 06/22] Format changes `make fmt` --- aws/data_source_aws_connect_instance_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index b1493ae7033..748895b9c96 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -13,9 +13,9 @@ func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { rName := acctest.RandomWithPrefix("datasource-test-terraform") resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), - Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), + Providers: testAccProviders, Steps: []resource.TestStep{ { Config: testAccAwsConnectInstanceDataSourceConfig_nonExistentId, @@ -51,9 +51,9 @@ func TestAccAwsConnectInstanceDataSource_alias(t *testing.T) { rName := acctest.RandomWithPrefix("datasource-test-terraform") resourceName := "aws_connect_instance.foo" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), - Providers: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), + Providers: testAccProviders, Steps: []resource.TestStep{ { Config: testAccAwsConnectInstanceDataSourceConfigAlias(rName), From 6e5c378f8f435f250fea7741dc24bb56d72d13aa Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Sat, 31 Jul 2021 12:30:11 -0400 Subject: [PATCH 07/22] Refactoring Connect Instance Code reworking --- aws/data_source_aws_connect_instance_test.go | 1 + aws/resource_aws_connect_instance.go | 82 ++++++++++---------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index 748895b9c96..4a4dc0fa21d 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -5,6 +5,7 @@ import ( "regexp" "testing" + "github.com/aws/aws-sdk-go/service/connect" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go index c54a0903a93..21efd0893d5 100644 --- a/aws/resource_aws_connect_instance.go +++ b/aws/resource_aws_connect_instance.go @@ -39,40 +39,11 @@ func resourceAwsConnectInstance() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "identity_management_type": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: connect.DirectoryTypeConnectManaged, - ValidateFunc: validation.StringInSlice(connect.DirectoryType_Values(), false), - }, - "directory_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringLenBetween(12, 12), - }, - "instance_alias": { + "arn": { Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 64), - validation.StringMatch(regexp.MustCompile(`^([\da-zA-Z]+)([\da-zA-Z-]+)$`), "must contain only alphanumeric hyphen and underscore characters"), - validation.StringDoesNotMatch(regexp.MustCompile(`^(d-).+$`), "can not start with d-"), - ), - }, - "inbound_calls_enabled": { - Type: schema.TypeBool, - Optional: true, - Default: true, - }, - "outbound_calls_enabled": { - Type: schema.TypeBool, - Optional: true, - Default: true, + Computed: true, }, - "early_media_enabled": { + "auto_resolve_best_voices": { Type: schema.TypeBool, Optional: true, Default: true, @@ -87,21 +58,49 @@ func resourceAwsConnectInstance() *schema.Resource { Optional: true, Default: true, }, - "auto_resolve_best_voices": { + "created_time": { + Type: schema.TypeString, + Computed: true, + }, + "directory_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(12, 12), + }, + "early_media_enabled": { Type: schema.TypeBool, Optional: true, Default: true, }, - "use_custom_tts_voices": { + "identity_management_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: connect.DirectoryTypeConnectManaged, + ValidateFunc: validation.StringInSlice(connect.DirectoryType_Values(), false), + }, + "inbound_calls_enabled": { Type: schema.TypeBool, Optional: true, - Default: false, + Default: true, }, - "arn": { + "instance_alias": { Type: schema.TypeString, - Computed: true, + Optional: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 64), + validation.StringMatch(regexp.MustCompile(`^([\da-zA-Z]+)([\da-zA-Z-]+)$`), "must contain only alphanumeric hyphen and underscore characters"), + validation.StringDoesNotMatch(regexp.MustCompile(`^(d-).+$`), "can not start with d-"), + ), }, - "created_time": { + "outbound_calls_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "service_role": { Type: schema.TypeString, Computed: true, }, @@ -109,9 +108,10 @@ func resourceAwsConnectInstance() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "service_role": { - Type: schema.TypeString, - Computed: true, + "use_custom_tts_voices": { + Type: schema.TypeBool, + Optional: true, + Default: false, }, }, } From 313bd21a89ba2f0f1af6e57fca026e7e658649be Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Sat, 31 Jul 2021 14:51:14 -0400 Subject: [PATCH 08/22] WIP - refactoring. Need to add Create/Delete wait checks and fix AccTests. --- aws/data_source_aws_connect_instance.go | 65 +++++++++----------- aws/data_source_aws_connect_instance_test.go | 8 +-- aws/internal/service/connect/enum.go | 15 +++++ aws/internal/service/connect/errors.go | 7 +++ aws/resource_aws_connect_instance.go | 53 ++++++++-------- aws/resource_aws_connect_instance_test.go | 12 ++-- 6 files changed, 87 insertions(+), 73 deletions(-) create mode 100644 aws/internal/service/connect/enum.go create mode 100644 aws/internal/service/connect/errors.go diff --git a/aws/data_source_aws_connect_instance.go b/aws/data_source_aws_connect_instance.go index 1583fa6c381..05f8bc33356 100644 --- a/aws/data_source_aws_connect_instance.go +++ b/aws/data_source_aws_connect_instance.go @@ -12,69 +12,56 @@ import ( "github.com/aws/aws-sdk-go/service/connect" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + tfconnect "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/connect" ) -var dataResourceConnectInstanceAttributesMapping = map[string]string{ - connect.InstanceAttributeTypeInboundCalls: "inbound_calls_enabled", - connect.InstanceAttributeTypeOutboundCalls: "outbound_calls_enabled", - connect.InstanceAttributeTypeContactflowLogs: "contact_flow_logs_enabled", - connect.InstanceAttributeTypeContactLens: "contact_lens_enabled", - connect.InstanceAttributeTypeAutoResolveBestVoices: "auto_resolve_best_voices", - connect.InstanceAttributeTypeUseCustomTtsVoices: "use_custom_tts_voices", - connect.InstanceAttributeTypeEarlyMedia: "early_media_enabled", -} - func dataSourceAwsConnectInstance() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceAwsConnectInstanceRead, Schema: map[string]*schema.Schema{ - "instance_id": { + "arn": { Type: schema.TypeString, - Optional: true, Computed: true, }, - "instance_alias": { - Type: schema.TypeString, - Optional: true, + "auto_resolve_best_voices_enabled": { + Type: schema.TypeBool, Computed: true, }, - "created_time": { - Type: schema.TypeString, + "contact_flow_logs_enabled": { + Type: schema.TypeBool, Computed: true, }, - "arn": { - Type: schema.TypeString, + "contact_lens_enabled": { + Type: schema.TypeBool, Computed: true, }, - "identity_management_type": { + "created_time": { Type: schema.TypeString, Computed: true, }, - "inbound_calls_enabled": { - Type: schema.TypeBool, - Computed: true, - }, - "outbound_calls_enabled": { + "early_media_enabled": { Type: schema.TypeBool, Computed: true, }, - "early_media_enabled": { - Type: schema.TypeBool, + "identity_management_type": { + Type: schema.TypeString, Computed: true, }, - "contact_flow_logs_enabled": { + "inbound_calls_enabled": { Type: schema.TypeBool, Computed: true, }, - "contact_lens_enabled": { - Type: schema.TypeBool, + "instance_alias": { + Type: schema.TypeString, + Optional: true, Computed: true, }, - "auto_resolve_best_voices": { - Type: schema.TypeBool, + "instance_id": { + Type: schema.TypeString, + Optional: true, Computed: true, }, - "use_custom_tts_voices": { + "outbound_calls_enabled": { Type: schema.TypeBool, Computed: true, }, @@ -86,6 +73,10 @@ func dataSourceAwsConnectInstance() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "use_custom_tts_voices_enabled": { + Type: schema.TypeBool, + Computed: true, + }, }, } } @@ -152,18 +143,18 @@ func dataSourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceDat d.Set("arn", matchedInstance.Arn) d.Set("created_time", matchedInstance.CreatedTime.Format(time.RFC3339)) d.Set("identity_management_type", matchedInstance.IdentityManagementType) - d.Set("instance_alias", matchedInstance.InstanceAlias) d.Set("inbound_calls_enabled", matchedInstance.InboundCallsEnabled) + d.Set("instance_alias", matchedInstance.InstanceAlias) d.Set("outbound_calls_enabled", matchedInstance.OutboundCallsEnabled) - d.Set("status", matchedInstance.InstanceStatus) d.Set("service_role", matchedInstance.ServiceRole) + d.Set("status", matchedInstance.InstanceStatus) - for att := range dataResourceConnectInstanceAttributesMapping { + for att := range tfconnect.InstanceAttributeMapping() { value, err := dataResourceAwsConnectInstanceReadAttribute(ctx, conn, d.Id(), att) if err != nil { return diag.FromErr(fmt.Errorf("error reading Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) } - d.Set(resourceConnectInstanceAttributesMapping[att], value) + d.Set(tfconnect.InstanceAttributeMapping()[att], value) } return nil } diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index 4a4dc0fa21d..c119b53b8f2 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -37,8 +37,8 @@ func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "outbound_calls_enabled"), resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), resource.TestCheckResourceAttrSet(resourceName, "contact_lens_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices"), - resource.TestCheckResourceAttrSet(resourceName, "use_custom_tts_voices"), + resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "use_custom_tts_voices_enabled"), resource.TestCheckResourceAttrSet(resourceName, "early_media_enabled"), resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "service_role"), @@ -67,8 +67,8 @@ func TestAccAwsConnectInstanceDataSource_alias(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "outbound_calls_enabled"), resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), resource.TestCheckResourceAttrSet(resourceName, "contact_lens_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices"), - resource.TestCheckResourceAttrSet(resourceName, "use_custom_tts_voices"), + resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices_enabled"), + resource.TestCheckResourceAttrSet(resourceName, "use_custom_tts_voices_enabled"), resource.TestCheckResourceAttrSet(resourceName, "early_media_enabled"), resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "service_role"), diff --git a/aws/internal/service/connect/enum.go b/aws/internal/service/connect/enum.go new file mode 100644 index 00000000000..25df80bccb1 --- /dev/null +++ b/aws/internal/service/connect/enum.go @@ -0,0 +1,15 @@ +package connect + +import "github.com/aws/aws-sdk-go/service/connect" + +func InstanceAttributeMapping() map[string]string { + return map[string]string{ + connect.InstanceAttributeTypeAutoResolveBestVoices: "auto_resolve_best_voices_enabled", + connect.InstanceAttributeTypeContactflowLogs: "contact_flow_logs_enabled", + connect.InstanceAttributeTypeContactLens: "contact_lens_enabled", + connect.InstanceAttributeTypeEarlyMedia: "early_media_enabled", + connect.InstanceAttributeTypeInboundCalls: "inbound_calls_enabled", + connect.InstanceAttributeTypeOutboundCalls: "outbound_calls_enabled", + connect.InstanceAttributeTypeUseCustomTtsVoices: "use_custom_tts_voices_enabled", + } +} diff --git a/aws/internal/service/connect/errors.go b/aws/internal/service/connect/errors.go new file mode 100644 index 00000000000..7a30fcc2ce8 --- /dev/null +++ b/aws/internal/service/connect/errors.go @@ -0,0 +1,7 @@ +package connect + +// Error code constants missing from AWS Go SDK: +// https://docs.aws.amazon.com/sdk-for-go/api/service/connect/#pkg-constants +const ( + ErrCodeAccessDeniedException = "AccessDeniedException" +) diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go index 21efd0893d5..76ebe23d5ee 100644 --- a/aws/resource_aws_connect_instance.go +++ b/aws/resource_aws_connect_instance.go @@ -10,23 +10,15 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/connect" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + tfconnect "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/connect" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/connect/waiter" ) -var resourceConnectInstanceAttributesMapping = map[string]string{ - connect.InstanceAttributeTypeInboundCalls: "inbound_calls_enabled", - connect.InstanceAttributeTypeOutboundCalls: "outbound_calls_enabled", - connect.InstanceAttributeTypeContactflowLogs: "contact_flow_logs_enabled", - connect.InstanceAttributeTypeContactLens: "contact_lens_enabled", - connect.InstanceAttributeTypeAutoResolveBestVoices: "auto_resolve_best_voices", - connect.InstanceAttributeTypeUseCustomTtsVoices: "use_custom_tts_voices", - connect.InstanceAttributeTypeEarlyMedia: "early_media_enabled", -} - func resourceAwsConnectInstance() *schema.Resource { return &schema.Resource{ CreateContext: resourceAwsConnectInstanceCreate, @@ -43,7 +35,7 @@ func resourceAwsConnectInstance() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "auto_resolve_best_voices": { + "auto_resolve_best_voices_enabled": { Type: schema.TypeBool, Optional: true, Default: true, @@ -108,7 +100,7 @@ func resourceAwsConnectInstance() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "use_custom_tts_voices": { + "use_custom_tts_voices_enabled": { Type: schema.TypeBool, Optional: true, Default: false, @@ -146,13 +138,19 @@ func resourceAwsConnectInstanceCreate(ctx context.Context, d *schema.ResourceDat return diag.FromErr(fmt.Errorf("error waiting for Connect instance creation (%s): %s", d.Id(), err)) } - for att := range resourceConnectInstanceAttributesMapping { - rKey := resourceConnectInstanceAttributesMapping[att] - val := d.Get(rKey) - err := resourceAwsConnectInstanceUpdateAttribute(ctx, conn, d.Id(), att, strconv.FormatBool(val.(bool))) - if err != nil { - return diag.FromErr(fmt.Errorf("error setting Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) + for att := range tfconnect.InstanceAttributeMapping() { + rKey := tfconnect.InstanceAttributeMapping()[att] + + if v, ok := d.GetOk(rKey); ok { + err := resourceAwsConnectInstanceUpdateAttribute(ctx, conn, d.Id(), att, strconv.FormatBool(v.(bool))) + //Pre-release attribute, user/account/instance now allow-listed + if err != nil && tfawserr.ErrCodeEquals(err, tfconnect.ErrCodeAccessDeniedException) || tfawserr.ErrMessageContains(err, tfconnect.ErrCodeAccessDeniedException, "not authorized to update") { + log.Printf("[WARN] error setting Connect instance (%s) attribute (%s): %s", d.Id(), att, err) + } else if err != nil { + return diag.FromErr(fmt.Errorf("error setting Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) + } } + } return resourceAwsConnectInstanceRead(ctx, d, meta) @@ -161,13 +159,16 @@ func resourceAwsConnectInstanceCreate(ctx context.Context, d *schema.ResourceDat func resourceAwsConnectInstanceUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*AWSClient).connectconn - for att := range resourceConnectInstanceAttributesMapping { - rKey := resourceConnectInstanceAttributesMapping[att] + for att := range tfconnect.InstanceAttributeMapping() { + rKey := tfconnect.InstanceAttributeMapping()[att] if d.HasChange(rKey) { _, n := d.GetChange(rKey) err := resourceAwsConnectInstanceUpdateAttribute(ctx, conn, d.Id(), att, strconv.FormatBool(n.(bool))) - if err != nil { - return diag.FromErr(fmt.Errorf("error updating Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) + //Pre-release attribute, user/account/instance now allow-listed + if err != nil && tfawserr.ErrCodeEquals(err, tfconnect.ErrCodeAccessDeniedException) || tfawserr.ErrMessageContains(err, tfconnect.ErrCodeAccessDeniedException, "not authorized to update") { + log.Printf("[WARN] error setting Connect instance (%s) attribute (%s): %s", d.Id(), att, err) + } else if err != nil { + return diag.FromErr(fmt.Errorf("error setting Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) } } } @@ -202,18 +203,18 @@ func resourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceData, d.Set("arn", instance.Arn) d.Set("created_time", instance.CreatedTime.Format(time.RFC3339)) d.Set("identity_management_type", instance.IdentityManagementType) - d.Set("instance_alias", instance.InstanceAlias) d.Set("inbound_calls_enabled", instance.InboundCallsEnabled) + d.Set("instance_alias", instance.InstanceAlias) d.Set("outbound_calls_enabled", instance.OutboundCallsEnabled) - d.Set("status", instance.InstanceStatus) d.Set("service_role", instance.ServiceRole) + d.Set("status", instance.InstanceStatus) - for att := range resourceConnectInstanceAttributesMapping { + for att := range tfconnect.InstanceAttributeMapping() { value, err := resourceAwsConnectInstanceReadAttribute(ctx, conn, d.Id(), att) if err != nil { return diag.FromErr(fmt.Errorf("error reading Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) } - d.Set(resourceConnectInstanceAttributesMapping[att], value) + d.Set(tfconnect.InstanceAttributeMapping()[att], value) } return nil diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 47b250338f1..6c8471f8fb6 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -88,8 +88,8 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices", "true"), - resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices", "false"), + resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), @@ -127,8 +127,8 @@ func TestAccAwsConnectInstance_custom(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices", "false"), - resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices", "true"), + resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), @@ -272,8 +272,8 @@ resource "aws_connect_instance" "foo" { early_media_enabled = false contact_flow_logs_enabled = true contact_lens_enabled = false - auto_resolve_best_voices = false - use_custom_tts_voices = true + auto_resolve_best_voices_enabled = false + use_custom_tts_voices_enabled = true } `, rName) } From 1254465099c273bfbb8b52eb7bcf56acc404f127 Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Wed, 4 Aug 2021 19:25:27 -0400 Subject: [PATCH 09/22] WIP refactored to match default API values, AccTest_Basic working. --- aws/internal/service/connect/enum.go | 2 + aws/internal/service/connect/waiter/status.go | 12 +- aws/internal/service/connect/waiter/waiter.go | 26 ++- aws/resource_aws_connect_instance.go | 56 +++---- aws/resource_aws_connect_instance_test.go | 153 ++++++++++-------- 5 files changed, 139 insertions(+), 110 deletions(-) diff --git a/aws/internal/service/connect/enum.go b/aws/internal/service/connect/enum.go index 25df80bccb1..26c2470d663 100644 --- a/aws/internal/service/connect/enum.go +++ b/aws/internal/service/connect/enum.go @@ -2,6 +2,8 @@ package connect import "github.com/aws/aws-sdk-go/service/connect" +const InstanceStatusStatusNotFound = "ResourceNotFoundException" + func InstanceAttributeMapping() map[string]string { return map[string]string{ connect.InstanceAttributeTypeAutoResolveBestVoices: "auto_resolve_best_voices_enabled", diff --git a/aws/internal/service/connect/waiter/status.go b/aws/internal/service/connect/waiter/status.go index 06e88977955..3db9398033f 100644 --- a/aws/internal/service/connect/waiter/status.go +++ b/aws/internal/service/connect/waiter/status.go @@ -5,7 +5,9 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/connect" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + tfconnect "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/connect" ) func InstanceStatus(ctx context.Context, conn *connect.Connect, instanceId string) resource.StateRefreshFunc { @@ -16,12 +18,14 @@ func InstanceStatus(ctx context.Context, conn *connect.Connect, instanceId strin output, err := conn.DescribeInstanceWithContext(ctx, input) - if err != nil { - return nil, connect.ErrCodeResourceNotFoundException, err + if tfawserr.ErrCodeEquals(err, tfconnect.InstanceStatusStatusNotFound) { + return output, tfconnect.InstanceStatusStatusNotFound, nil } - state := aws.StringValue(output.Instance.InstanceStatus) + if err != nil { + return nil, "", err + } - return output, state, nil + return output, aws.StringValue(output.Instance.InstanceStatus), nil } } diff --git a/aws/internal/service/connect/waiter/waiter.go b/aws/internal/service/connect/waiter/waiter.go index cfc41f94a2c..c5cf5365ccb 100644 --- a/aws/internal/service/connect/waiter/waiter.go +++ b/aws/internal/service/connect/waiter/waiter.go @@ -6,11 +6,13 @@ import ( "github.com/aws/aws-sdk-go/service/connect" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + tfconnect "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/connect" ) const ( // ConnectInstanceCreateTimeout Timeout for connect instance creation - ConnectInstanceCreateTimeout = 5 * time.Minute + ConnectInstanceCreatedTimeout = 5 * time.Minute + ConnectInstanceDeletedTimeout = 2 * time.Minute ) func InstanceCreated(ctx context.Context, conn *connect.Connect, instanceId string) (*connect.DescribeInstanceOutput, error) { @@ -18,7 +20,27 @@ func InstanceCreated(ctx context.Context, conn *connect.Connect, instanceId stri Pending: []string{connect.InstanceStatusCreationInProgress}, Target: []string{connect.InstanceStatusActive}, Refresh: InstanceStatus(ctx, conn, instanceId), - Timeout: ConnectInstanceCreateTimeout, + Timeout: ConnectInstanceCreatedTimeout, + } + + outputRaw, err := stateConf.WaitForState() + + if v, ok := outputRaw.(*connect.DescribeInstanceOutput); ok { + return v, err + } + + return nil, err +} + +// We don't have a PENDING_DELETION or DELETED for the Connect instance. +// If the Connect Instance has an associated EXISTING DIRECTORY, removing the connect instance +// will cause an error because it is still has authorized applications. +func InstanceDeleted(ctx context.Context, conn *connect.Connect, instanceId string) (*connect.DescribeInstanceOutput, error) { + stateConf := &resource.StateChangeConf{ + Pending: []string{connect.InstanceStatusActive}, + Target: []string{tfconnect.InstanceStatusStatusNotFound}, + Refresh: InstanceStatus(ctx, conn, instanceId), + Timeout: ConnectInstanceDeletedTimeout, } outputRaw, err := stateConf.WaitForState() diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go index 76ebe23d5ee..ecd8b5e912d 100644 --- a/aws/resource_aws_connect_instance.go +++ b/aws/resource_aws_connect_instance.go @@ -38,17 +38,17 @@ func resourceAwsConnectInstance() *schema.Resource { "auto_resolve_best_voices_enabled": { Type: schema.TypeBool, Optional: true, - Default: true, + Default: true, //verified default result from ListInstanceAttributes() }, "contact_flow_logs_enabled": { Type: schema.TypeBool, Optional: true, - Default: false, + Default: false, //verified default result from ListInstanceAttributes() }, "contact_lens_enabled": { Type: schema.TypeBool, Optional: true, - Default: true, + Default: true, //verified default result from ListInstanceAttributes() }, "created_time": { Type: schema.TypeString, @@ -59,28 +59,28 @@ func resourceAwsConnectInstance() *schema.Resource { Optional: true, ForceNew: true, ValidateFunc: validation.StringLenBetween(12, 12), + AtLeastOneOf: []string{"directory_id", "instance_alias"}, }, "early_media_enabled": { Type: schema.TypeBool, Optional: true, - Default: true, + Default: true, //verified default result from ListInstanceAttributes() }, "identity_management_type": { Type: schema.TypeString, - Optional: true, + Required: true, ForceNew: true, - Default: connect.DirectoryTypeConnectManaged, ValidateFunc: validation.StringInSlice(connect.DirectoryType_Values(), false), }, "inbound_calls_enabled": { Type: schema.TypeBool, - Optional: true, - Default: true, + Required: true, }, "instance_alias": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, + Type: schema.TypeString, + Optional: true, + ForceNew: true, + AtLeastOneOf: []string{"directory_id", "instance_alias"}, ValidateFunc: validation.All( validation.StringLenBetween(1, 64), validation.StringMatch(regexp.MustCompile(`^([\da-zA-Z]+)([\da-zA-Z-]+)$`), "must contain only alphanumeric hyphen and underscore characters"), @@ -89,8 +89,7 @@ func resourceAwsConnectInstance() *schema.Resource { }, "outbound_calls_enabled": { Type: schema.TypeBool, - Optional: true, - Default: true, + Required: true, }, "service_role": { Type: schema.TypeString, @@ -103,7 +102,7 @@ func resourceAwsConnectInstance() *schema.Resource { "use_custom_tts_voices_enabled": { Type: schema.TypeBool, Optional: true, - Default: false, + Default: false, //verified default result from ListInstanceAttributes() }, }, } @@ -115,7 +114,6 @@ func resourceAwsConnectInstanceCreate(ctx context.Context, d *schema.ResourceDat input := &connect.CreateInstanceInput{ ClientToken: aws.String(resource.UniqueId()), IdentityManagementType: aws.String(d.Get("identity_management_type").(string)), - InstanceAlias: aws.String(d.Get("instance_alias").(string)), InboundCallsEnabled: aws.Bool(d.Get("inbound_calls_enabled").(bool)), OutboundCallsEnabled: aws.Bool(d.Get("outbound_calls_enabled").(bool)), } @@ -123,9 +121,11 @@ func resourceAwsConnectInstanceCreate(ctx context.Context, d *schema.ResourceDat if _, ok := d.GetOk("directory_id"); ok { input.DirectoryId = aws.String(d.Get("directory_id").(string)) } + if _, ok := d.GetOk("instance_alias"); ok { + input.InstanceAlias = aws.String(d.Get("instance_alias").(string)) + } log.Printf("[DEBUG] Creating Connect Instance %s", input) - output, err := conn.CreateInstanceWithContext(ctx, input) if err != nil { @@ -150,7 +150,6 @@ func resourceAwsConnectInstanceCreate(ctx context.Context, d *schema.ResourceDat return diag.FromErr(fmt.Errorf("error setting Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) } } - } return resourceAwsConnectInstanceRead(ctx, d, meta) @@ -183,7 +182,6 @@ func resourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceData, } log.Printf("[DEBUG] Reading Connect Instance %s", d.Id()) - output, err := conn.DescribeInstanceWithContext(ctx, &input) if isAWSErr(err, connect.ErrCodeResourceNotFoundException, "") { @@ -199,7 +197,6 @@ func resourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceData, instance := output.Instance d.SetId(aws.StringValue(instance.Id)) - d.Set("arn", instance.Arn) d.Set("created_time", instance.CreatedTime.Format(time.RFC3339)) d.Set("identity_management_type", instance.IdentityManagementType) @@ -230,26 +227,13 @@ func resourceAwsConnectInstanceDelete(ctx context.Context, d *schema.ResourceDat log.Printf("[DEBUG] Deleting Connect Instance %s", d.Id()) _, err := conn.DeleteInstance(input) - if err != nil { return diag.FromErr(fmt.Errorf("error deleting Connect Instance (%s): %s", d.Id(), err)) } - // For using an existing directory, - // There is no proper way. If the Connect instance was unregistered from the attached directory. - // We don't have a PENDING_DELETION or DELETED for the Connect instance. - // Deleting the directory immediately after removing the connect instance - // will cause an error because it is still has authorized applications. - // There is no specific wait time for this check, so we'll wait a few seconds - // to make sure the Connect instance will deregister. - - imt := d.Get("identity_management_type") - - if imt.(string) == connect.DirectoryTypeExistingDirectory { - log.Print("[INFO] Waiting for Connect to deregister from the Directory Service") - time.Sleep(30 * time.Second) + if _, err := waiter.InstanceDeleted(ctx, conn, d.Id()); err != nil { + return diag.FromErr(fmt.Errorf("error waiting for Connect Instance deletion (%s): %s", d.Id(), err)) } - return nil } @@ -261,11 +245,9 @@ func resourceAwsConnectInstanceUpdateAttribute(ctx context.Context, conn *connec } _, err := conn.UpdateInstanceAttributeWithContext(ctx, input) - if err != nil { return err } - return nil } @@ -276,11 +258,9 @@ func resourceAwsConnectInstanceReadAttribute(ctx context.Context, conn *connect. } output, err := conn.DescribeInstanceAttributeWithContext(ctx, input) - if err != nil { return false, err } - result, parseerr := strconv.ParseBool(*output.Attribute.Value) return result, parseerr } diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 6c8471f8fb6..40d4ce78c31 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -68,7 +68,7 @@ func testSweepConnectInstance(region string) error { func TestAccAwsConnectInstance_basic(t *testing.T) { var v connect.DescribeInstanceOutput rName := acctest.RandomWithPrefix("resource-test-terraform") - resourceName := "aws_connect_instance.foo" + resourceName := "aws_connect_instance.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -81,57 +81,18 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAwsConnectInstanceExists(resourceName, &v), testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), + resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "true"), //verified default result from ListInstanceAttributes() + resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "false"), //verified default result from ListInstanceAttributes() + resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "true"), //verified default result from ListInstanceAttributes() resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "true"), //verified default result from ListInstanceAttributes() resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), - resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), - testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccAwsConnectInstance_custom(t *testing.T) { - var v connect.DescribeInstanceOutput - rName := acctest.RandomWithPrefix("resource-test-terraform") - resourceName := "aws_connect_instance.foo" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), - Providers: testAccProviders, - CheckDestroy: testAccCheckAwsConnectInstanceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAwsConnectInstanceConfigCustom(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAwsConnectInstanceExists(resourceName, &v), - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), - resource.TestCheckResourceAttrSet(resourceName, "created_time"), - resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), - resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), + resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), + resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "false"), //verified default result from ListInstanceAttributes() ), }, { @@ -143,10 +104,49 @@ func TestAccAwsConnectInstance_custom(t *testing.T) { }) } +//func TestAccAwsConnectInstance_custom(t *testing.T) { +// var v connect.DescribeInstanceOutput +// rName := acctest.RandomWithPrefix("resource-test-terraform") +// resourceName := "aws_connect_instance.test" +// +// resource.ParallelTest(t, resource.TestCase{ +// PreCheck: func() { testAccPreCheck(t) }, +// ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), +// Providers: testAccProviders, +// CheckDestroy: testAccCheckAwsConnectInstanceDestroy, +// Steps: []resource.TestStep{ +// { +// Config: testAccAwsConnectInstanceConfigCustom(rName), +// Check: resource.ComposeTestCheckFunc( +// testAccCheckAwsConnectInstanceExists(resourceName, &v), +// testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), +// resource.TestCheckResourceAttrSet(resourceName, "created_time"), +// resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), +// resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), +// resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "false"), +// resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), +// resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), +// resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "false"), +// resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "false"), +// resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "true"), +// resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), +// resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), +// testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), +// ), +// }, +// { +// ResourceName: resourceName, +// ImportState: true, +// ImportStateVerify: true, +// }, +// }, +// }) +//} + func TestAccAwsConnectInstance_directory(t *testing.T) { var v connect.DescribeInstanceOutput rName := acctest.RandomWithPrefix("resource-test-terraform") - resourceName := "aws_connect_instance.foo" + resourceName := "aws_connect_instance.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -171,7 +171,7 @@ func TestAccAwsConnectInstance_directory(t *testing.T) { }) } -func testAccCheckAwsConnectInstanceExists(resourceName string, function *connect.DescribeInstanceOutput) resource.TestCheckFunc { +func testAccCheckAwsConnectInstanceExists(resourceName string, instance *connect.DescribeInstanceOutput) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] if !ok { @@ -188,12 +188,15 @@ func testAccCheckAwsConnectInstanceExists(resourceName string, function *connect InstanceId: aws.String(rs.Primary.ID), } - getFunction, err := conn.DescribeInstance(input) + output, err := conn.DescribeInstance(input) if err != nil { return err } + if output == nil { + return fmt.Errorf("Connect instance %q does not exist", rs.Primary.ID) + } - *function = *getFunction + *instance = *output return nil } @@ -202,7 +205,7 @@ func testAccCheckAwsConnectInstanceExists(resourceName string, function *connect func TestAccAwsConnectInstance_saml(t *testing.T) { var v connect.DescribeInstanceOutput rName := acctest.RandomWithPrefix("resource-test-terraform") - resourceName := "aws_connect_instance.foo" + resourceName := "aws_connect_instance.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -253,27 +256,45 @@ func testAccCheckAwsConnectInstanceDestroy(s *terraform.State) error { func testAccAwsConnectInstanceConfigBasic(rName string) string { return fmt.Sprintf(` -resource "aws_connect_instance" "foo" { +resource "aws_connect_instance" "test" { + identity_management_type = "CONNECT_MANAGED" + inbound_calls_enabled = true + instance_alias = %[1]q + outbound_calls_enabled = true +} +`, rName) +} + +func testAccAwsConnectInstanceConfigInboundEnabledOutboundDisabled(rName string) string { + return fmt.Sprintf(` +resource "aws_connect_instance" "test" { identity_management_type = "CONNECT_MANAGED" - instance_alias = %[1]q inbound_calls_enabled = true + instance_alias = %[1]q + outbound_calls_enabled = false +} +`, rName) +} + +func testAccAwsConnectInstanceConfigInboundDisabledOutboundEnabled(rName string) string { + return fmt.Sprintf(` +resource "aws_connect_instance" "test" { + identity_management_type = "CONNECT_MANAGED" + inbound_calls_enabled = false + instance_alias = %[1]q outbound_calls_enabled = true } `, rName) } -func testAccAwsConnectInstanceConfigCustom(rName string) string { +func testAccAwsConnectInstanceConfigAttributeEarlyMedia(rName string) string { return fmt.Sprintf(` -resource "aws_connect_instance" "foo" { - identity_management_type = "CONNECT_MANAGED" - instance_alias = %[1]q - inbound_calls_enabled = false - outbound_calls_enabled = true - early_media_enabled = false - contact_flow_logs_enabled = true - contact_lens_enabled = false - auto_resolve_best_voices_enabled = false - use_custom_tts_voices_enabled = true +resource "aws_connect_instance" "test" { + identity_management_type = "CONNECT_MANAGED" + inbound_calls_enabled = true + instance_alias = %[1]q + outbound_calls_enabled = true + early_media_enabled = true } `, rName) } @@ -325,7 +346,7 @@ resource "aws_directory_service_directory" "test" { } } -resource "aws_connect_instance" "foo" { +resource "aws_connect_instance" "test" { directory_id = aws_directory_service_directory.test.id identity_management_type = "EXISTING_DIRECTORY" instance_alias = %[1]q @@ -339,7 +360,7 @@ resource "aws_connect_instance" "foo" { func testAccAwsConnectInstanceConfigSAML(rName string) string { return fmt.Sprintf(` -resource "aws_connect_instance" "foo" { +resource "aws_connect_instance" "test" { identity_management_type = "SAML" instance_alias = %[1]q inbound_calls_enabled = true From f2d12564f206aa38031cbaa5bd308a97e45bea0f Mon Sep 17 00:00:00 2001 From: drewmullen Date: Thu, 5 Aug 2021 15:24:24 -0400 Subject: [PATCH 10/22] fix data source acc tests --- aws/data_source_aws_connect_instance_test.go | 26 ++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index c119b53b8f2..20758720550 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -12,7 +12,7 @@ import ( func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { rName := acctest.RandomWithPrefix("datasource-test-terraform") - resourceName := "aws_connect_instance.foo" + resourceName := "aws_connect_instance.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), @@ -50,7 +50,7 @@ func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { func TestAccAwsConnectInstanceDataSource_alias(t *testing.T) { rName := acctest.RandomWithPrefix("datasource-test-terraform") - resourceName := "aws_connect_instance.foo" + resourceName := "aws_connect_instance.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), @@ -79,37 +79,43 @@ func TestAccAwsConnectInstanceDataSource_alias(t *testing.T) { } const testAccAwsConnectInstanceDataSourceConfig_nonExistentId = ` -data "aws_connect_instance" "foo" { +data "aws_connect_instance" "test" { instance_id = "97afc98d-101a-ba98-ab97-ae114fc115ec" } ` const testAccAwsConnectInstanceDataSourceConfig_nonExistentAlias = ` -data "aws_connect_instance" "foo" { +data "aws_connect_instance" "test" { instance_alias = "tf-acc-test-does-not-exist" } ` func testAccAwsConnectInstanceDataSourceConfigBasic(rName string) string { return fmt.Sprintf(` -resource "aws_connect_instance" "foo" { +resource "aws_connect_instance" "test" { instance_alias = %[1]q + identity_management_type = "CONNECT_MANAGED" + inbound_calls_enabled = true + outbound_calls_enabled = true } -data "aws_connect_instance" "foo" { - instance_id = aws_connect_instance.foo.id +data "aws_connect_instance" "test" { + instance_id = aws_connect_instance.test.id } `, rName) } func testAccAwsConnectInstanceDataSourceConfigAlias(rName string) string { return fmt.Sprintf(` -resource "aws_connect_instance" "foo" { +resource "aws_connect_instance" "test" { instance_alias = %[1]q + identity_management_type = "CONNECT_MANAGED" + inbound_calls_enabled = true + outbound_calls_enabled = true } -data "aws_connect_instance" "foo" { - instance_alias = aws_connect_instance.foo.instance_alias +data "aws_connect_instance" "test" { + instance_alias = aws_connect_instance.test.instance_alias } `, rName) } From be0647a561dbf62358b6287e936bc549998a724b Mon Sep 17 00:00:00 2001 From: drewmullen Date: Thu, 5 Aug 2021 16:50:36 -0400 Subject: [PATCH 11/22] acc test for all attrs --- aws/resource_aws_connect_instance_test.go | 119 ++++++++++++++-------- 1 file changed, 77 insertions(+), 42 deletions(-) diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 40d4ce78c31..88846607b67 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -104,44 +104,63 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { }) } -//func TestAccAwsConnectInstance_custom(t *testing.T) { -// var v connect.DescribeInstanceOutput -// rName := acctest.RandomWithPrefix("resource-test-terraform") -// resourceName := "aws_connect_instance.test" -// -// resource.ParallelTest(t, resource.TestCase{ -// PreCheck: func() { testAccPreCheck(t) }, -// ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), -// Providers: testAccProviders, -// CheckDestroy: testAccCheckAwsConnectInstanceDestroy, -// Steps: []resource.TestStep{ -// { -// Config: testAccAwsConnectInstanceConfigCustom(rName), -// Check: resource.ComposeTestCheckFunc( -// testAccCheckAwsConnectInstanceExists(resourceName, &v), -// testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), -// resource.TestCheckResourceAttrSet(resourceName, "created_time"), -// resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), -// resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), -// resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "false"), -// resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), -// resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), -// resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "false"), -// resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "false"), -// resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "true"), -// resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), -// resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), -// testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), -// ), -// }, -// { -// ResourceName: resourceName, -// ImportState: true, -// ImportStateVerify: true, -// }, -// }, -// }) -//} +func TestAccAwsConnectInstance_custom(t *testing.T) { + var v connect.DescribeInstanceOutput + rName := acctest.RandomWithPrefix("resource-test-terraform") + resourceName := "aws_connect_instance.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsConnectInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsConnectInstanceConfigCustom(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsConnectInstanceExists(resourceName, &v), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), + resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), + resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), + resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), + testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAwsConnectInstanceConfigBasic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsConnectInstanceExists(resourceName, &v), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), + resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "true"), //verified default result from ListInstanceAttributes() + resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "false"), //verified default result from ListInstanceAttributes() + resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "true"), //verified default result from ListInstanceAttributes() + resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "true"), //verified default result from ListInstanceAttributes() + resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), + resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "true"), + resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), + resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), + testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), + resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), + resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "false"), //verified default result from ListInstanceAttributes() + ), + }, + }, + }) +} func TestAccAwsConnectInstance_directory(t *testing.T) { var v connect.DescribeInstanceOutput @@ -259,18 +278,34 @@ func testAccAwsConnectInstanceConfigBasic(rName string) string { resource "aws_connect_instance" "test" { identity_management_type = "CONNECT_MANAGED" inbound_calls_enabled = true - instance_alias = %[1]q + instance_alias = %[1]q outbound_calls_enabled = true } `, rName) } +func testAccAwsConnectInstanceConfigCustom(rName string) string { + return fmt.Sprintf(` +resource "aws_connect_instance" "test" { + identity_management_type = "CONNECT_MANAGED" + inbound_calls_enabled = false + instance_alias = %[1]q + outbound_calls_enabled = false + auto_resolve_best_voices_enabled = false + contact_flow_logs_enabled = true + contact_lens_enabled = false + early_media_enabled = false + use_custom_tts_voices_enabled = true +} +`, rName) +} + func testAccAwsConnectInstanceConfigInboundEnabledOutboundDisabled(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "test" { identity_management_type = "CONNECT_MANAGED" inbound_calls_enabled = true - instance_alias = %[1]q + instance_alias = %[1]q outbound_calls_enabled = false } `, rName) @@ -281,7 +316,7 @@ func testAccAwsConnectInstanceConfigInboundDisabledOutboundEnabled(rName string) resource "aws_connect_instance" "test" { identity_management_type = "CONNECT_MANAGED" inbound_calls_enabled = false - instance_alias = %[1]q + instance_alias = %[1]q outbound_calls_enabled = true } `, rName) @@ -292,7 +327,7 @@ func testAccAwsConnectInstanceConfigAttributeEarlyMedia(rName string) string { resource "aws_connect_instance" "test" { identity_management_type = "CONNECT_MANAGED" inbound_calls_enabled = true - instance_alias = %[1]q + instance_alias = %[1]q outbound_calls_enabled = true early_media_enabled = true } From 1e93156b39d06a9fce924208bf3d110637ee4fac Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Wed, 1 Sep 2021 16:27:32 -0400 Subject: [PATCH 12/22] Removed use_custom_tts_voices_enabled as it's a pre-release feature and can change before GA. --- aws/internal/service/connect/enum.go | 3 ++- aws/resource_aws_connect_instance.go | 11 ++++++----- aws/resource_aws_connect_instance_test.go | 4 ---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/aws/internal/service/connect/enum.go b/aws/internal/service/connect/enum.go index 26c2470d663..5f39559ffc9 100644 --- a/aws/internal/service/connect/enum.go +++ b/aws/internal/service/connect/enum.go @@ -12,6 +12,7 @@ func InstanceAttributeMapping() map[string]string { connect.InstanceAttributeTypeEarlyMedia: "early_media_enabled", connect.InstanceAttributeTypeInboundCalls: "inbound_calls_enabled", connect.InstanceAttributeTypeOutboundCalls: "outbound_calls_enabled", - connect.InstanceAttributeTypeUseCustomTtsVoices: "use_custom_tts_voices_enabled", + // Pre-release feature requiring allow-list from AWS. Removing all functionality until feature is GA + //connect.InstanceAttributeTypeUseCustomTtsVoices: "use_custom_tts_voices_enabled", } } diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go index ecd8b5e912d..82c067eb5d3 100644 --- a/aws/resource_aws_connect_instance.go +++ b/aws/resource_aws_connect_instance.go @@ -99,11 +99,12 @@ func resourceAwsConnectInstance() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "use_custom_tts_voices_enabled": { - Type: schema.TypeBool, - Optional: true, - Default: false, //verified default result from ListInstanceAttributes() - }, + // Pre-release feature requiring allow-list from AWS. Removing all functionality until feature is GA + // "use_custom_tts_voices_enabled": { + // Type: schema.TypeBool, + // Optional: true, + // Default: false, //verified default result from ListInstanceAttributes() + // }, }, } } diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 88846607b67..929d621ba38 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -92,7 +92,6 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), - resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "false"), //verified default result from ListInstanceAttributes() ), }, { @@ -128,7 +127,6 @@ func TestAccAwsConnectInstance_custom(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "true"), resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), @@ -155,7 +153,6 @@ func TestAccAwsConnectInstance_custom(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), - resource.TestCheckResourceAttr(resourceName, "use_custom_tts_voices_enabled", "false"), //verified default result from ListInstanceAttributes() ), }, }, @@ -295,7 +292,6 @@ resource "aws_connect_instance" "test" { contact_flow_logs_enabled = true contact_lens_enabled = false early_media_enabled = false - use_custom_tts_voices_enabled = true } `, rName) } From 5865150d602b30ce4a3fa4d45a1f7a98517cfb2e Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Thu, 2 Sep 2021 16:59:54 -0400 Subject: [PATCH 13/22] Combining AccTests to save resources. Fixed Formatting. --- aws/data_source_aws_connect_instance.go | 3 +- aws/data_source_aws_connect_instance_test.go | 4 +- aws/internal/service/connect/enum.go | 4 + aws/resource_aws_connect_instance_test.go | 137 ++++-------------- website/docs/r/connect_instance.html.markdown | 4 +- 5 files changed, 40 insertions(+), 112 deletions(-) diff --git a/aws/data_source_aws_connect_instance.go b/aws/data_source_aws_connect_instance.go index 05f8bc33356..6610a38a122 100644 --- a/aws/data_source_aws_connect_instance.go +++ b/aws/data_source_aws_connect_instance.go @@ -165,8 +165,7 @@ func dataSourceAwsConnectGetAllConnectInstanceSummaries(ctx context.Context, con for { input := &connect.ListInstancesInput{ - // MaxResults Valid Range: Minimum value of 1. Maximum value of 60 - MaxResults: aws.Int64(int64(60)), + MaxResults: aws.Int64(int64(tfconnect.ListInstancesMaxResults)), } if nextToken != "" { input.NextToken = aws.String(nextToken) diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index 20758720550..3991a5a32e8 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -93,7 +93,7 @@ data "aws_connect_instance" "test" { func testAccAwsConnectInstanceDataSourceConfigBasic(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "test" { - instance_alias = %[1]q + instance_alias = %[1]q identity_management_type = "CONNECT_MANAGED" inbound_calls_enabled = true outbound_calls_enabled = true @@ -108,7 +108,7 @@ data "aws_connect_instance" "test" { func testAccAwsConnectInstanceDataSourceConfigAlias(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "test" { - instance_alias = %[1]q + instance_alias = %[1]q identity_management_type = "CONNECT_MANAGED" inbound_calls_enabled = true outbound_calls_enabled = true diff --git a/aws/internal/service/connect/enum.go b/aws/internal/service/connect/enum.go index 5f39559ffc9..bb5177160cc 100644 --- a/aws/internal/service/connect/enum.go +++ b/aws/internal/service/connect/enum.go @@ -4,6 +4,10 @@ import "github.com/aws/aws-sdk-go/service/connect" const InstanceStatusStatusNotFound = "ResourceNotFoundException" +const ( + ListInstancesMaxResults = 10 +) + func InstanceAttributeMapping() map[string]string { return map[string]string{ connect.InstanceAttributeTypeAutoResolveBestVoices: "auto_resolve_best_voices_enabled", diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 929d621ba38..318141db8a4 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -99,11 +99,27 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccAwsConnectInstanceConfigBasicFlipped(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsConnectInstanceExists(resourceName, &v), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), + resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "false"), + resource.TestCheckResourceAttrSet(resourceName, "created_time"), + resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "false"), + resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), + resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), + ), + }, }, }) } -func TestAccAwsConnectInstance_custom(t *testing.T) { +func TestAccAwsConnectInstance_directory(t *testing.T) { var v connect.DescribeInstanceOutput rName := acctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_instance.test" @@ -115,51 +131,24 @@ func TestAccAwsConnectInstance_custom(t *testing.T) { CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccAwsConnectInstanceConfigCustom(rName), + Config: testAccAwsConnectInstanceConfigDirectory(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsConnectInstanceExists(resourceName, &v), - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), - resource.TestCheckResourceAttrSet(resourceName, "created_time"), - resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), - resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), - resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "false"), - resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeExistingDirectory), resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), - testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccAwsConnectInstanceConfigBasic(rName), - Check: resource.ComposeTestCheckFunc( - testAccCheckAwsConnectInstanceExists(resourceName, &v), - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), - resource.TestCheckResourceAttr(resourceName, "auto_resolve_best_voices_enabled", "true"), //verified default result from ListInstanceAttributes() - resource.TestCheckResourceAttr(resourceName, "contact_flow_logs_enabled", "false"), //verified default result from ListInstanceAttributes() - resource.TestCheckResourceAttr(resourceName, "contact_lens_enabled", "true"), //verified default result from ListInstanceAttributes() - resource.TestCheckResourceAttrSet(resourceName, "created_time"), - resource.TestCheckResourceAttr(resourceName, "early_media_enabled", "true"), //verified default result from ListInstanceAttributes() - resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeConnectManaged), - resource.TestCheckResourceAttr(resourceName, "inbound_calls_enabled", "true"), - resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), - resource.TestCheckResourceAttr(resourceName, "outbound_calls_enabled", "true"), - testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/connect.amazonaws.com/.+`)), - resource.TestCheckResourceAttr(resourceName, "status", connect.InstanceStatusActive), - ), + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"directory_id"}, }, }, }) } -func TestAccAwsConnectInstance_directory(t *testing.T) { +func TestAccAwsConnectInstance_saml(t *testing.T) { var v connect.DescribeInstanceOutput rName := acctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_instance.test" @@ -171,17 +160,16 @@ func TestAccAwsConnectInstance_directory(t *testing.T) { CheckDestroy: testAccCheckAwsConnectInstanceDestroy, Steps: []resource.TestStep{ { - Config: testAccAwsConnectInstanceConfigDirectory(rName), + Config: testAccAwsConnectInstanceConfigSAML(rName), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeExistingDirectory), + resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeSaml), testAccCheckAwsConnectInstanceExists(resourceName, &v), ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"directory_id"}, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, }, }, }) @@ -218,32 +206,6 @@ func testAccCheckAwsConnectInstanceExists(resourceName string, instance *connect } } -func TestAccAwsConnectInstance_saml(t *testing.T) { - var v connect.DescribeInstanceOutput - rName := acctest.RandomWithPrefix("resource-test-terraform") - resourceName := "aws_connect_instance.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), - Providers: testAccProviders, - CheckDestroy: testAccCheckAwsConnectInstanceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAwsConnectInstanceConfigSAML(rName), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "identity_management_type", connect.DirectoryTypeSaml), - testAccCheckAwsConnectInstanceExists(resourceName, &v), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} func testAccCheckAwsConnectInstanceDestroy(s *terraform.State) error { for _, rs := range s.RootModule().Resources { if rs.Type != "aws_connect_instance" { @@ -281,7 +243,7 @@ resource "aws_connect_instance" "test" { `, rName) } -func testAccAwsConnectInstanceConfigCustom(rName string) string { +func testAccAwsConnectInstanceConfigBasicFlipped(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "test" { identity_management_type = "CONNECT_MANAGED" @@ -290,42 +252,7 @@ resource "aws_connect_instance" "test" { outbound_calls_enabled = false auto_resolve_best_voices_enabled = false contact_flow_logs_enabled = true - contact_lens_enabled = false - early_media_enabled = false -} -`, rName) -} - -func testAccAwsConnectInstanceConfigInboundEnabledOutboundDisabled(rName string) string { - return fmt.Sprintf(` -resource "aws_connect_instance" "test" { - identity_management_type = "CONNECT_MANAGED" - inbound_calls_enabled = true - instance_alias = %[1]q - outbound_calls_enabled = false -} -`, rName) -} - -func testAccAwsConnectInstanceConfigInboundDisabledOutboundEnabled(rName string) string { - return fmt.Sprintf(` -resource "aws_connect_instance" "test" { - identity_management_type = "CONNECT_MANAGED" - inbound_calls_enabled = false - instance_alias = %[1]q - outbound_calls_enabled = true -} -`, rName) -} - -func testAccAwsConnectInstanceConfigAttributeEarlyMedia(rName string) string { - return fmt.Sprintf(` -resource "aws_connect_instance" "test" { - identity_management_type = "CONNECT_MANAGED" - inbound_calls_enabled = true - instance_alias = %[1]q - outbound_calls_enabled = true - early_media_enabled = true + early_media_enabled = false } `, rName) } @@ -383,8 +310,6 @@ resource "aws_connect_instance" "test" { instance_alias = %[1]q inbound_calls_enabled = true outbound_calls_enabled = true - - depends_on = [aws_directory_service_directory.test] } `, rName) } diff --git a/website/docs/r/connect_instance.html.markdown b/website/docs/r/connect_instance.html.markdown index 39f73ab6ecd..3336e415c0a 100644 --- a/website/docs/r/connect_instance.html.markdown +++ b/website/docs/r/connect_instance.html.markdown @@ -13,8 +13,8 @@ Provides an Amazon Connect instance resource. For more information see ## Example Usage -```hcl -resource "aws_connect_instance" "foo" { +```terraform +resource "aws_connect_instance" "test" { identity_management_type = "CONNECT_MANAGED" instance_alias = "resource-test-terraform-connect" inbound_calls_enabled = true From 8e107c89c123c83e79a86ca48e70076d1070654b Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Fri, 3 Sep 2021 17:21:59 -0400 Subject: [PATCH 14/22] Removed us_voices and finshed stacking AccTests --- aws/data_source_aws_connect_instance.go | 10 +++++----- aws/data_source_aws_connect_instance_test.go | 19 +++++-------------- aws/resource_aws_connect_instance.go | 2 +- aws/resource_aws_connect_instance_test.go | 7 ++++--- website/docs/r/connect_instance.html.markdown | 2 +- 5 files changed, 16 insertions(+), 24 deletions(-) diff --git a/aws/data_source_aws_connect_instance.go b/aws/data_source_aws_connect_instance.go index 6610a38a122..bdc62c21323 100644 --- a/aws/data_source_aws_connect_instance.go +++ b/aws/data_source_aws_connect_instance.go @@ -73,10 +73,10 @@ func dataSourceAwsConnectInstance() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "use_custom_tts_voices_enabled": { - Type: schema.TypeBool, - Computed: true, - }, + // "use_custom_tts_voices_enabled": { + // Type: schema.TypeBool, + // Computed: true, + // }, }, } } @@ -165,7 +165,7 @@ func dataSourceAwsConnectGetAllConnectInstanceSummaries(ctx context.Context, con for { input := &connect.ListInstancesInput{ - MaxResults: aws.Int64(int64(tfconnect.ListInstancesMaxResults)), + MaxResults: aws.Int64(tfconnect.ListInstancesMaxResults), } if nextToken != "" { input.NextToken = aws.String(nextToken) diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index 3991a5a32e8..cdb63ce5901 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -38,24 +38,16 @@ func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), resource.TestCheckResourceAttrSet(resourceName, "contact_lens_enabled"), resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "use_custom_tts_voices_enabled"), resource.TestCheckResourceAttrSet(resourceName, "early_media_enabled"), resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "service_role"), ), }, - }, - }) -} - -func TestAccAwsConnectInstanceDataSource_alias(t *testing.T) { - rName := acctest.RandomWithPrefix("datasource-test-terraform") - resourceName := "aws_connect_instance.test" - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ErrorCheck: testAccErrorCheck(t, connect.EndpointsID), - Providers: testAccProviders, - Steps: []resource.TestStep{ + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccAwsConnectInstanceDataSourceConfigAlias(rName), Check: resource.ComposeAggregateTestCheckFunc( @@ -68,7 +60,6 @@ func TestAccAwsConnectInstanceDataSource_alias(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), resource.TestCheckResourceAttrSet(resourceName, "contact_lens_enabled"), resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "use_custom_tts_voices_enabled"), resource.TestCheckResourceAttrSet(resourceName, "early_media_enabled"), resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "service_role"), diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go index 82c067eb5d3..e3c66d793d4 100644 --- a/aws/resource_aws_connect_instance.go +++ b/aws/resource_aws_connect_instance.go @@ -130,7 +130,7 @@ func resourceAwsConnectInstanceCreate(ctx context.Context, d *schema.ResourceDat output, err := conn.CreateInstanceWithContext(ctx, input) if err != nil { - return diag.FromErr(fmt.Errorf("error reading Connect Instance (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error creating Connect Instance (%s): %s", d.Id(), err)) } d.SetId(aws.StringValue(output.Id)) diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 318141db8a4..82f04c28b1c 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -246,13 +246,14 @@ resource "aws_connect_instance" "test" { func testAccAwsConnectInstanceConfigBasicFlipped(rName string) string { return fmt.Sprintf(` resource "aws_connect_instance" "test" { + auto_resolve_best_voices_enabled = false + contact_flow_logs_enabled = true + contact_lens_enabled = false + early_media_enabled = false identity_management_type = "CONNECT_MANAGED" inbound_calls_enabled = false instance_alias = %[1]q outbound_calls_enabled = false - auto_resolve_best_voices_enabled = false - contact_flow_logs_enabled = true - early_media_enabled = false } `, rName) } diff --git a/website/docs/r/connect_instance.html.markdown b/website/docs/r/connect_instance.html.markdown index 3336e415c0a..c57fad9e3d3 100644 --- a/website/docs/r/connect_instance.html.markdown +++ b/website/docs/r/connect_instance.html.markdown @@ -36,7 +36,7 @@ The following arguments are supported: * `contact_flow_logs_enabled` - (Optional) Specifies Whether contact flow logs are enabled. Defaults to `false` * `contact_lens_enabled` - (Optional) Specifies Whether contact lens is enabled. Defaults to `true` * `auto_resolve_best_voices` - (Optional) Specifies Whether auto resolve best voices is enabled. Defaults to `true` -* `use_custom_tts_voices` - (Optional) Specifies Whether use custom tts voices is enabled. Defaults to `false` + ### Timeouts From b011e48fc41a8fe0cc9289196f0351d3bbbfdf8f Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Fri, 3 Sep 2021 17:33:00 -0400 Subject: [PATCH 15/22] fixed spacing for linting --- aws/resource_aws_connect_instance_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 82f04c28b1c..6d3b6b718b2 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + tfconnect "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/connect" ) func init() { @@ -32,7 +33,7 @@ func testSweepConnectInstance(region string) error { conn := client.(*AWSClient).connectconn ctx := context.Background() // MaxResults: Maximum value of 10. https://docs.aws.amazon.com/connect/latest/APIReference/API_ListInstances.html - input := &connect.ListInstancesInput{MaxResults: aws.Int64(10)} + input := &connect.ListInstancesInput{MaxResults: aws.Int64(tfconnect.ListInstancesMaxResults)} var sweeperErrs *multierror.Error for { listOutput, err := conn.ListInstances(input) @@ -248,7 +249,7 @@ func testAccAwsConnectInstanceConfigBasicFlipped(rName string) string { resource "aws_connect_instance" "test" { auto_resolve_best_voices_enabled = false contact_flow_logs_enabled = true - contact_lens_enabled = false + contact_lens_enabled = false early_media_enabled = false identity_management_type = "CONNECT_MANAGED" inbound_calls_enabled = false From 406c9e81f6702dd9e67eefa755295585fde294a4 Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Fri, 17 Sep 2021 09:09:51 -0400 Subject: [PATCH 16/22] Updated documentation, exposed Timeouts. --- aws/internal/service/connect/waiter/waiter.go | 2 +- aws/resource_aws_connect_instance.go | 6 ++- website/docs/r/connect_instance.html.markdown | 53 ++++++++++++++----- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/aws/internal/service/connect/waiter/waiter.go b/aws/internal/service/connect/waiter/waiter.go index c5cf5365ccb..499a3b04fd5 100644 --- a/aws/internal/service/connect/waiter/waiter.go +++ b/aws/internal/service/connect/waiter/waiter.go @@ -12,7 +12,7 @@ import ( const ( // ConnectInstanceCreateTimeout Timeout for connect instance creation ConnectInstanceCreatedTimeout = 5 * time.Minute - ConnectInstanceDeletedTimeout = 2 * time.Minute + ConnectInstanceDeletedTimeout = 5 * time.Minute ) func InstanceCreated(ctx context.Context, conn *connect.Connect, instanceId string) (*connect.DescribeInstanceOutput, error) { diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go index e3c66d793d4..d985d6a75a3 100644 --- a/aws/resource_aws_connect_instance.go +++ b/aws/resource_aws_connect_instance.go @@ -25,11 +25,13 @@ func resourceAwsConnectInstance() *schema.Resource { ReadContext: resourceAwsConnectInstanceRead, UpdateContext: resourceAwsConnectInstanceUpdate, DeleteContext: resourceAwsConnectInstanceDelete, - Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, - + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(waiter.ConnectInstanceCreatedTimeout), + Delete: schema.DefaultTimeout(waiter.ConnectInstanceDeletedTimeout), + }, Schema: map[string]*schema.Schema{ "arn": { Type: schema.TypeString, diff --git a/website/docs/r/connect_instance.html.markdown b/website/docs/r/connect_instance.html.markdown index c57fad9e3d3..eb5a4e35999 100644 --- a/website/docs/r/connect_instance.html.markdown +++ b/website/docs/r/connect_instance.html.markdown @@ -11,44 +11,69 @@ description: |- Provides an Amazon Connect instance resource. For more information see [Amazon Connect: Getting Started](https://docs.aws.amazon.com/connect/latest/adminguide/amazon-connect-get-started.html) +!> **WARN:** There are limits to the number of Connect Instances that can be created in a specific AWS account, and those limits span the life of the account, not just active Instances. Minimize the number of times you create/delete an instance. + ## Example Usage -```terraform +```hcl resource "aws_connect_instance" "test" { identity_management_type = "CONNECT_MANAGED" - instance_alias = "resource-test-terraform-connect" inbound_calls_enabled = true + instance_alias = "friendly-name-connect" outbound_calls_enabled = true } ``` -## Argument Reference +## Example Usage with Existing Active Directory + +```hcl +resource "aws_connect_instance" "test" { + directory_id = aws_directory_service_directory.test.id + identity_management_type = "EXISTING_DIRECTORY" + inbound_calls_enabled = true + instance_alias = "friendly-name-connect" + outbound_calls_enabled = true +} +``` +## Example Usage with SAML + +```hcl +resource "aws_connect_instance" "test" { + identity_management_type = "SAML" + inbound_calls_enabled = true + instance_alias = "friendly-name-connect" + outbound_calls_enabled = true +} +``` + +## Argument Reference The following arguments are supported: -* `identity_management_type` - (Optional) Specifies The identity management type attached to the instance. Defaults to `CONNECT_MANAGED`. Allowed Values are: `SAML`, `CONNECT_MANAGED`, `EXISTING_DIRECTORY`. +* `auto_resolve_best_voices_enabled` - (Optional) Specifies whether auto resolve best voices is enabled. Defaults to `true` +* `contact_flow_logs_enabled` - (Optional) Specifies whether contact flow logs are enabled. Defaults to `false` +* `contact_lens_enabled` - (Optional) Specifies whether contact lens is enabled. Defaults to `true` * `directory_id` - (Optional) The identifier for the directory if identity_management_type is `EXISTING_DIRECTORY`. +* `early_media_enabled` - (Optional) Specifies whether early media for outbound calls is enabled . Defaults to `true` if outbound calls is enabled +* `identity_management_type` - Specifies the identity management type attached to the instance. Allowed Values are: `SAML`, `CONNECT_MANAGED`, `EXISTING_DIRECTORY`. +* `inbound_calls_enabled` - Specifies whether inbound calls are enabled. * `instance_alias` - (Optional) Specifies the name of the instance -* `inbound_calls_enabled` - (Optional) Specifies Whether inbound calls are enabled. Defaults to `true` -* `outbound_calls_enabled` - (Optional) Specifies Whether outbound calls are enabled. * `inbound_calls_enabled` - (Optional) Specifies Whether inbound calls are enabled. Defaults to `true` -* `early_media_enabled` - (Optional) Specifies Whether early media for outbound calls is enabled . Defaults to `true` if outbound calls is enabled -* `contact_flow_logs_enabled` - (Optional) Specifies Whether contact flow logs are enabled. Defaults to `false` -* `contact_lens_enabled` - (Optional) Specifies Whether contact lens is enabled. Defaults to `true` -* `auto_resolve_best_voices` - (Optional) Specifies Whether auto resolve best voices is enabled. Defaults to `true` +* `outbound_calls_enabled` - Specifies whether outbound calls are enabled. ### Timeouts -The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: +`aws_connect_instance` provides the following [Timeouts](https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts) configuration options: * `create` - (Defaults to 5 mins) Used when creating the instance. +* `delete` - (Defaults to 5 mins) Used when deleting the instance. ## Attributes Reference In addition to all arguments above, the following attributes are exported: -* `created_time` - Specifies When the instance was created. -* `arn` - The Amazon Resource Name (ARN) of the instance. -* `status` - Specifies The state of the instance. +* `arn` - Amazon Resource Name (ARN) of the instance. +* `created_time` - Specifies when the instance was created. * `service_role` - The service role of the instance. +* `status` - The state of the instance. From d4f3b001dcf182125e923d18fbaa8280b5c71dc2 Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Fri, 17 Sep 2021 09:22:21 -0400 Subject: [PATCH 17/22] Fixing linting issues in Connect docs. --- website/docs/r/connect_instance.html.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/website/docs/r/connect_instance.html.markdown b/website/docs/r/connect_instance.html.markdown index eb5a4e35999..f16aa33a102 100644 --- a/website/docs/r/connect_instance.html.markdown +++ b/website/docs/r/connect_instance.html.markdown @@ -51,15 +51,15 @@ resource "aws_connect_instance" "test" { The following arguments are supported: -* `auto_resolve_best_voices_enabled` - (Optional) Specifies whether auto resolve best voices is enabled. Defaults to `true` -* `contact_flow_logs_enabled` - (Optional) Specifies whether contact flow logs are enabled. Defaults to `false` -* `contact_lens_enabled` - (Optional) Specifies whether contact lens is enabled. Defaults to `true` +* `auto_resolve_best_voices_enabled` - (Optional) Specifies whether auto resolve best voices is enabled. Defaults to `true`. +* `contact_flow_logs_enabled` - (Optional) Specifies whether contact flow logs are enabled. Defaults to `false`. +* `contact_lens_enabled` - (Optional) Specifies whether contact lens is enabled. Defaults to `true`. * `directory_id` - (Optional) The identifier for the directory if identity_management_type is `EXISTING_DIRECTORY`. -* `early_media_enabled` - (Optional) Specifies whether early media for outbound calls is enabled . Defaults to `true` if outbound calls is enabled +* `early_media_enabled` - (Optional) Specifies whether early media for outbound calls is enabled . Defaults to `true` if outbound calls is enabled. * `identity_management_type` - Specifies the identity management type attached to the instance. Allowed Values are: `SAML`, `CONNECT_MANAGED`, `EXISTING_DIRECTORY`. * `inbound_calls_enabled` - Specifies whether inbound calls are enabled. -* `instance_alias` - (Optional) Specifies the name of the instance -* `outbound_calls_enabled` - Specifies whether outbound calls are enabled. +* `instance_alias` - (Optional) Specifies the name of the instance. +* `outbound_calls_enabled` - Specifies whether outbound calls are enabled. ### Timeouts From f71a97dd8cd62cc38c12cb95c7d33f66841d1cd7 Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Fri, 17 Sep 2021 09:30:50 -0400 Subject: [PATCH 18/22] Fixed hcl -> terraform --- website/docs/r/connect_instance.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/r/connect_instance.html.markdown b/website/docs/r/connect_instance.html.markdown index f16aa33a102..da103b782b1 100644 --- a/website/docs/r/connect_instance.html.markdown +++ b/website/docs/r/connect_instance.html.markdown @@ -15,7 +15,7 @@ Provides an Amazon Connect instance resource. For more information see ## Example Usage -```hcl +```terraform resource "aws_connect_instance" "test" { identity_management_type = "CONNECT_MANAGED" inbound_calls_enabled = true @@ -26,7 +26,7 @@ resource "aws_connect_instance" "test" { ## Example Usage with Existing Active Directory -```hcl +```terraform resource "aws_connect_instance" "test" { directory_id = aws_directory_service_directory.test.id identity_management_type = "EXISTING_DIRECTORY" @@ -38,7 +38,7 @@ resource "aws_connect_instance" "test" { ## Example Usage with SAML -```hcl +```terraform resource "aws_connect_instance" "test" { identity_management_type = "SAML" inbound_calls_enabled = true From 44009877c357731a98f861b8caad607af006aed1 Mon Sep 17 00:00:00 2001 From: Tyler Lynch Date: Mon, 20 Sep 2021 14:58:55 -0400 Subject: [PATCH 19/22] Added Amazon Connect Instance changelog --- .changelog/16709.txt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changelog/16709.txt diff --git a/.changelog/16709.txt b/.changelog/16709.txt new file mode 100644 index 00000000000..a0bc051c44c --- /dev/null +++ b/.changelog/16709.txt @@ -0,0 +1,8 @@ +```release-note:new-resource +aws_connect_instance +``` + +```release-note:new-data-source +aws_connect_instance +``` + From c313e27738decbab844a5a784d05ab081d74051e Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 22 Sep 2021 20:31:00 -0400 Subject: [PATCH 20/22] add plan-time requirement for exactly-on-of argument; use pagination where possible --- aws/data_source_aws_connect_instance.go | 123 ++++++++++--------- aws/data_source_aws_connect_instance_test.go | 5 - 2 files changed, 64 insertions(+), 64 deletions(-) diff --git a/aws/data_source_aws_connect_instance.go b/aws/data_source_aws_connect_instance.go index bdc62c21323..89c80492751 100644 --- a/aws/data_source_aws_connect_instance.go +++ b/aws/data_source_aws_connect_instance.go @@ -2,7 +2,6 @@ package aws import ( "context" - "errors" "fmt" "log" "strconv" @@ -52,14 +51,16 @@ func dataSourceAwsConnectInstance() *schema.Resource { Computed: true, }, "instance_alias": { - Type: schema.TypeString, - Optional: true, - Computed: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ExactlyOneOf: []string{"instance_alias", "instance_id"}, }, "instance_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ExactlyOneOf: []string{"instance_id", "instance_alias"}, }, "outbound_calls_enabled": { Type: schema.TypeBool, @@ -86,16 +87,11 @@ func dataSourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceDat var matchedInstance *connect.Instance - instanceId, instanceIdOk := d.GetOk("instance_id") - instanceAlias, instanceAliasOk := d.GetOk("instance_alias") - - if !instanceIdOk && !instanceAliasOk { - return diag.FromErr(errors.New("error one instance_id or instance_alias of must be assigned")) - } + if v, ok := d.GetOk("instance_id"); ok { + instanceId := v.(string) - if instanceIdOk { input := connect.DescribeInstanceInput{ - InstanceId: aws.String(instanceId.(string)), + InstanceId: aws.String(instanceId), } log.Printf("[DEBUG] Reading Connect Instance by instance_id: %s", input) @@ -103,39 +99,43 @@ func dataSourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceDat output, err := conn.DescribeInstance(&input) if err != nil { - return diag.FromErr(fmt.Errorf("error getting Connect Instance by instance_id (%s): %s", instanceId, err)) + return diag.FromErr(fmt.Errorf("error getting Connect Instance by instance_id (%s): %w", instanceId, err)) + } + + if output == nil { + return diag.FromErr(fmt.Errorf("error getting Connect Instance by instance_id (%s): empty output", instanceId)) } matchedInstance = output.Instance - } else if instanceAliasOk { - instanceSummaryList, err := dataSourceAwsConnectGetAllConnectInstanceSummaries(ctx, conn) + } else if v, ok := d.GetOk("instance_alias"); ok { + instanceAlias := v.(string) + + instanceSummary, err := dataSourceAwsConnectGetConnectInstanceSummaryByInstanceAlias(ctx, conn, instanceAlias) + if err != nil { - return diag.FromErr(fmt.Errorf("error listing Connect Instances: %s", err)) + return diag.FromErr(fmt.Errorf("error finding Connect Instance Summary by instance_alias (%s): %w", instanceAlias, err)) } - for _, instanceSummary := range instanceSummaryList { - log.Printf("[DEBUG] Connect Instance summary: %s", instanceSummary) - if aws.StringValue(instanceSummary.InstanceAlias) == instanceAlias.(string) { - - matchedInstance = &connect.Instance{ - Arn: instanceSummary.Arn, - CreatedTime: instanceSummary.CreatedTime, - Id: instanceSummary.Id, - IdentityManagementType: instanceSummary.IdentityManagementType, - InboundCallsEnabled: instanceSummary.InboundCallsEnabled, - InstanceAlias: instanceSummary.InstanceAlias, - InstanceStatus: instanceSummary.InstanceStatus, - OutboundCallsEnabled: instanceSummary.OutboundCallsEnabled, - ServiceRole: instanceSummary.ServiceRole, - } - break - } + if instanceSummary == nil { + return diag.FromErr(fmt.Errorf("error finding Connect Instance Summary by instance_alias (%s): not found", instanceAlias)) + } + + matchedInstance = &connect.Instance{ + Arn: instanceSummary.Arn, + CreatedTime: instanceSummary.CreatedTime, + Id: instanceSummary.Id, + IdentityManagementType: instanceSummary.IdentityManagementType, + InboundCallsEnabled: instanceSummary.InboundCallsEnabled, + InstanceAlias: instanceSummary.InstanceAlias, + InstanceStatus: instanceSummary.InstanceStatus, + OutboundCallsEnabled: instanceSummary.OutboundCallsEnabled, + ServiceRole: instanceSummary.ServiceRole, } } if matchedInstance == nil { - return diag.FromErr(fmt.Errorf("error finding Connect Instance by instance_alias: %s", instanceAlias)) + return diag.FromErr(fmt.Errorf("no Connect Instance found for query, try adjusting your search criteria")) } d.SetId(aws.StringValue(matchedInstance.Id)) @@ -152,40 +152,45 @@ func dataSourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceDat for att := range tfconnect.InstanceAttributeMapping() { value, err := dataResourceAwsConnectInstanceReadAttribute(ctx, conn, d.Id(), att) if err != nil { - return diag.FromErr(fmt.Errorf("error reading Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) + return diag.FromErr(fmt.Errorf("error reading Connect Instance (%s) attribute (%s): %w", d.Id(), att, err)) } d.Set(tfconnect.InstanceAttributeMapping()[att], value) } + return nil } -func dataSourceAwsConnectGetAllConnectInstanceSummaries(ctx context.Context, conn *connect.Connect) ([]*connect.InstanceSummary, error) { - var instances []*connect.InstanceSummary - var nextToken string +func dataSourceAwsConnectGetConnectInstanceSummaryByInstanceAlias(ctx context.Context, conn *connect.Connect, instanceAlias string) (*connect.InstanceSummary, error) { + var result *connect.InstanceSummary - for { - input := &connect.ListInstancesInput{ - MaxResults: aws.Int64(tfconnect.ListInstancesMaxResults), - } - if nextToken != "" { - input.NextToken = aws.String(nextToken) + input := &connect.ListInstancesInput{ + MaxResults: aws.Int64(tfconnect.ListInstancesMaxResults), + } + + err := conn.ListInstancesPagesWithContext(ctx, input, func(page *connect.ListInstancesOutput, lastPage bool) bool { + if page == nil { + return !lastPage } - log.Printf("[DEBUG] Listing Connect Instances: %s", input) + for _, is := range page.InstanceSummaryList { + if is == nil { + continue + } - output, err := conn.ListInstancesWithContext(ctx, input) - if err != nil { - return instances, err + if aws.StringValue(is.InstanceAlias) == instanceAlias { + result = is + return false + } } - instances = append(instances, output.InstanceSummaryList...) - if output.NextToken == nil { - break - } - nextToken = aws.StringValue(output.NextToken) + return !lastPage + }) + + if err != nil { + return nil, err } - return instances, nil + return result, nil } func dataResourceAwsConnectInstanceReadAttribute(ctx context.Context, conn *connect.Connect, instanceID string, attributeType string) (bool, error) { @@ -200,6 +205,6 @@ func dataResourceAwsConnectInstanceReadAttribute(ctx context.Context, conn *conn return false, err } - result, parseerr := strconv.ParseBool(*out.Attribute.Value) - return result, parseerr + result, parseErr := strconv.ParseBool(*out.Attribute.Value) + return result, parseErr } diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index cdb63ce5901..03aee63353e 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -43,11 +43,6 @@ func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "service_role"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, { Config: testAccAwsConnectInstanceDataSourceConfigAlias(rName), Check: resource.ComposeAggregateTestCheckFunc( From 08b6773b940d181b496ece0bc68d312f209a41a8 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 22 Sep 2021 20:35:09 -0400 Subject: [PATCH 21/22] CR updates; serialize tests since max of 2 can be run in parallel --- aws/resource_aws_connect_instance.go | 21 +++-- aws/resource_aws_connect_instance_test.go | 83 ++++++++++++------- website/docs/r/connect_instance.html.markdown | 29 ++++--- 3 files changed, 87 insertions(+), 46 deletions(-) diff --git a/aws/resource_aws_connect_instance.go b/aws/resource_aws_connect_instance.go index d985d6a75a3..41f4bedb05a 100644 --- a/aws/resource_aws_connect_instance.go +++ b/aws/resource_aws_connect_instance.go @@ -121,24 +121,24 @@ func resourceAwsConnectInstanceCreate(ctx context.Context, d *schema.ResourceDat OutboundCallsEnabled: aws.Bool(d.Get("outbound_calls_enabled").(bool)), } - if _, ok := d.GetOk("directory_id"); ok { - input.DirectoryId = aws.String(d.Get("directory_id").(string)) + if v, ok := d.GetOk("directory_id"); ok { + input.DirectoryId = aws.String(v.(string)) } - if _, ok := d.GetOk("instance_alias"); ok { - input.InstanceAlias = aws.String(d.Get("instance_alias").(string)) + if v, ok := d.GetOk("instance_alias"); ok { + input.InstanceAlias = aws.String(v.(string)) } log.Printf("[DEBUG] Creating Connect Instance %s", input) output, err := conn.CreateInstanceWithContext(ctx, input) if err != nil { - return diag.FromErr(fmt.Errorf("error creating Connect Instance (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error creating Connect Instance (%s): %w", d.Id(), err)) } d.SetId(aws.StringValue(output.Id)) if _, err := waiter.InstanceCreated(ctx, conn, d.Id()); err != nil { - return diag.FromErr(fmt.Errorf("error waiting for Connect instance creation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error waiting for Connect instance creation (%s): %w", d.Id(), err)) } for att := range tfconnect.InstanceAttributeMapping() { @@ -150,7 +150,7 @@ func resourceAwsConnectInstanceCreate(ctx context.Context, d *schema.ResourceDat if err != nil && tfawserr.ErrCodeEquals(err, tfconnect.ErrCodeAccessDeniedException) || tfawserr.ErrMessageContains(err, tfconnect.ErrCodeAccessDeniedException, "not authorized to update") { log.Printf("[WARN] error setting Connect instance (%s) attribute (%s): %s", d.Id(), att, err) } else if err != nil { - return diag.FromErr(fmt.Errorf("error setting Connect instance (%s) attribute (%s): %s", d.Id(), att, err)) + return diag.FromErr(fmt.Errorf("error setting Connect instance (%s) attribute (%s): %w", d.Id(), att, err)) } } } @@ -187,7 +187,7 @@ func resourceAwsConnectInstanceRead(ctx context.Context, d *schema.ResourceData, log.Printf("[DEBUG] Reading Connect Instance %s", d.Id()) output, err := conn.DescribeInstanceWithContext(ctx, &input) - if isAWSErr(err, connect.ErrCodeResourceNotFoundException, "") { + if !d.IsNewResource() && isAWSErr(err, connect.ErrCodeResourceNotFoundException, "") { log.Printf("[WARN] Connect Instance (%s) not found, removing from state", d.Id()) d.SetId("") return nil @@ -230,6 +230,11 @@ func resourceAwsConnectInstanceDelete(ctx context.Context, d *schema.ResourceDat log.Printf("[DEBUG] Deleting Connect Instance %s", d.Id()) _, err := conn.DeleteInstance(input) + + if isAWSErr(err, connect.ErrCodeResourceNotFoundException, "") { + return nil + } + if err != nil { return diag.FromErr(fmt.Errorf("error deleting Connect Instance (%s): %s", d.Id(), err)) } diff --git a/aws/resource_aws_connect_instance_test.go b/aws/resource_aws_connect_instance_test.go index 6d3b6b718b2..614e9c55952 100644 --- a/aws/resource_aws_connect_instance_test.go +++ b/aws/resource_aws_connect_instance_test.go @@ -11,7 +11,6 @@ import ( "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/connect" "github.com/hashicorp/go-multierror" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" @@ -30,43 +29,71 @@ func testSweepConnectInstance(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } + conn := client.(*AWSClient).connectconn ctx := context.Background() + var errs *multierror.Error + sweepResources := make([]*testSweepResource, 0) + // MaxResults: Maximum value of 10. https://docs.aws.amazon.com/connect/latest/APIReference/API_ListInstances.html input := &connect.ListInstancesInput{MaxResults: aws.Int64(tfconnect.ListInstancesMaxResults)} - var sweeperErrs *multierror.Error - for { - listOutput, err := conn.ListInstances(input) - if err != nil { - if testSweepSkipSweepError(err) { - log.Printf("[WARN] Skipping Connect Instance sweep for %s: %s", region, err) - return nil - } - return fmt.Errorf("Error retrieving Connect Instance: %s", err) + + err = conn.ListInstancesPagesWithContext(ctx, input, func(page *connect.ListInstancesOutput, lastPage bool) bool { + if page == nil { + return !lastPage } - for _, instance := range listOutput.InstanceSummaryList { - id := aws.StringValue(instance.Id) + + for _, instanceSummary := range page.InstanceSummaryList { + if instanceSummary == nil { + continue + } + + id := aws.StringValue(instanceSummary.Id) + + log.Printf("[INFO] Deleting Connect Instance (%s)", id) r := resourceAwsConnectInstance() d := r.Data(nil) d.SetId(id) - diags := r.DeleteContext(ctx, d, client) - for i := range diags { - if diags[i].Severity == diag.Error { - log.Printf("[ERROR] %s", diags[i].Summary) - sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf(diags[i].Summary)) - continue - } - } + sweepResources = append(sweepResources, NewTestSweepResource(r, d, client)) } - if aws.StringValue(listOutput.NextToken) == "" { - break - } - input.NextToken = listOutput.NextToken + + return !lastPage + }) + + if err != nil { + errs = multierror.Append(errs, fmt.Errorf("error listing Connect Instances: %w", err)) + } + + if err = testSweepResourceOrchestrator(sweepResources); err != nil { + errs = multierror.Append(errs, fmt.Errorf("error sweeping Connect Instances for %s: %w", region, err)) + } + + if testSweepSkipSweepError(errs.ErrorOrNil()) { + log.Printf("[WARN] Skipping Connect Instances sweep for %s: %s", region, errs) + return nil } - return sweeperErrs.ErrorOrNil() + + return errs.ErrorOrNil() } -func TestAccAwsConnectInstance_basic(t *testing.T) { + +//Serialized acceptance tests due to Connect account limits (max 2 parallel tests) +func TestAccAwsConnectInstance_serial(t *testing.T) { + testCases := map[string]func(t *testing.T){ + "basic": testAccAwsConnectInstance_basic, + "directory": testAccAwsConnectInstance_directory, + "saml": testAccAwsConnectInstance_saml, + } + + for name, tc := range testCases { + tc := tc + t.Run(name, func(t *testing.T) { + tc(t) + }) + } +} + +func testAccAwsConnectInstance_basic(t *testing.T) { var v connect.DescribeInstanceOutput rName := acctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_instance.test" @@ -120,7 +147,7 @@ func TestAccAwsConnectInstance_basic(t *testing.T) { }) } -func TestAccAwsConnectInstance_directory(t *testing.T) { +func testAccAwsConnectInstance_directory(t *testing.T) { var v connect.DescribeInstanceOutput rName := acctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_instance.test" @@ -149,7 +176,7 @@ func TestAccAwsConnectInstance_directory(t *testing.T) { }) } -func TestAccAwsConnectInstance_saml(t *testing.T) { +func testAccAwsConnectInstance_saml(t *testing.T) { var v connect.DescribeInstanceOutput rName := acctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_instance.test" diff --git a/website/docs/r/connect_instance.html.markdown b/website/docs/r/connect_instance.html.markdown index da103b782b1..e7b81861bf4 100644 --- a/website/docs/r/connect_instance.html.markdown +++ b/website/docs/r/connect_instance.html.markdown @@ -56,12 +56,22 @@ The following arguments are supported: * `contact_lens_enabled` - (Optional) Specifies whether contact lens is enabled. Defaults to `true`. * `directory_id` - (Optional) The identifier for the directory if identity_management_type is `EXISTING_DIRECTORY`. * `early_media_enabled` - (Optional) Specifies whether early media for outbound calls is enabled . Defaults to `true` if outbound calls is enabled. -* `identity_management_type` - Specifies the identity management type attached to the instance. Allowed Values are: `SAML`, `CONNECT_MANAGED`, `EXISTING_DIRECTORY`. -* `inbound_calls_enabled` - Specifies whether inbound calls are enabled. -* `instance_alias` - (Optional) Specifies the name of the instance. -* `outbound_calls_enabled` - Specifies whether outbound calls are enabled. +* `identity_management_type` - (Required) Specifies the identity management type attached to the instance. Allowed Values are: `SAML`, `CONNECT_MANAGED`, `EXISTING_DIRECTORY`. +* `inbound_calls_enabled` - (Required) Specifies whether inbound calls are enabled. +* `instance_alias` - (Optional) Specifies the name of the instance. Required if `directory_id` not specified. +* `outbound_calls_enabled` - (Required) Specifies whether outbound calls are enabled. +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The identifier of the instance. +* `arn` - Amazon Resource Name (ARN) of the instance. +* `created_time` - Specifies when the instance was created. +* `service_role` - The service role of the instance. +* `status` - The state of the instance. + ### Timeouts `aws_connect_instance` provides the following [Timeouts](https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts) configuration options: @@ -69,11 +79,10 @@ The following arguments are supported: * `create` - (Defaults to 5 mins) Used when creating the instance. * `delete` - (Defaults to 5 mins) Used when deleting the instance. -## Attributes Reference +## Import -In addition to all arguments above, the following attributes are exported: +Connect instances can be imported using the `id`, e.g. -* `arn` - Amazon Resource Name (ARN) of the instance. -* `created_time` - Specifies when the instance was created. -* `service_role` - The service role of the instance. -* `status` - The state of the instance. +``` +$ terraform import aws_connect_instance.example f1288a1f-6193-445a-b47e-af739b2 +``` From 823d1a7405b78bf0fdbd543e929093bef4137cc9 Mon Sep 17 00:00:00 2001 From: Angie Pinilla Date: Wed, 22 Sep 2021 21:24:31 -0400 Subject: [PATCH 22/22] update data source test to compare attributes with respective resource --- aws/data_source_aws_connect_instance_test.go | 51 ++++++++++---------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/aws/data_source_aws_connect_instance_test.go b/aws/data_source_aws_connect_instance_test.go index 03aee63353e..cb18c4b7944 100644 --- a/aws/data_source_aws_connect_instance_test.go +++ b/aws/data_source_aws_connect_instance_test.go @@ -12,6 +12,7 @@ import ( func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { rName := acctest.RandomWithPrefix("datasource-test-terraform") + dataSourceName := "data.aws_connect_instance.test" resourceName := "aws_connect_instance.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -24,40 +25,40 @@ func TestAccAwsConnectInstanceDataSource_basic(t *testing.T) { }, { Config: testAccAwsConnectInstanceDataSourceConfig_nonExistentAlias, - ExpectError: regexp.MustCompile(`error finding Connect Instance by instance_alias`), + ExpectError: regexp.MustCompile(`error finding Connect Instance Summary by instance_alias`), }, { Config: testAccAwsConnectInstanceDataSourceConfigBasic(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), - resource.TestCheckResourceAttrSet(resourceName, "created_time"), - resource.TestCheckResourceAttrSet(resourceName, "identity_management_type"), - resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), - resource.TestCheckResourceAttrSet(resourceName, "inbound_calls_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "outbound_calls_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "contact_lens_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "early_media_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "status"), - resource.TestCheckResourceAttrSet(resourceName, "service_role"), + resource.TestCheckResourceAttrPair(resourceName, "arn", dataSourceName, "arn"), + resource.TestCheckResourceAttrPair(resourceName, "created_time", dataSourceName, "created_time"), + resource.TestCheckResourceAttrPair(resourceName, "identity_management_type", dataSourceName, "identity_management_type"), + resource.TestCheckResourceAttrPair(resourceName, "instance_alias", dataSourceName, "instance_alias"), + resource.TestCheckResourceAttrPair(resourceName, "inbound_calls_enabled", dataSourceName, "inbound_calls_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "outbound_calls_enabled", dataSourceName, "outbound_calls_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "contact_flow_logs_enabled", dataSourceName, "contact_flow_logs_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "contact_lens_enabled", dataSourceName, "contact_lens_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "auto_resolve_best_voices_enabled", dataSourceName, "auto_resolve_best_voices_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "early_media_enabled", dataSourceName, "early_media_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "status", dataSourceName, "status"), + resource.TestCheckResourceAttrPair(resourceName, "service_role", dataSourceName, "service_role"), ), }, { Config: testAccAwsConnectInstanceDataSourceConfigAlias(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccMatchResourceAttrRegionalARN(resourceName, "arn", "connect", regexp.MustCompile(`instance/.+`)), - resource.TestCheckResourceAttrSet(resourceName, "created_time"), - resource.TestCheckResourceAttrSet(resourceName, "identity_management_type"), - resource.TestMatchResourceAttr(resourceName, "instance_alias", regexp.MustCompile(rName)), - resource.TestCheckResourceAttrSet(resourceName, "inbound_calls_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "outbound_calls_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "contact_flow_logs_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "contact_lens_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "auto_resolve_best_voices_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "early_media_enabled"), - resource.TestCheckResourceAttrSet(resourceName, "status"), - resource.TestCheckResourceAttrSet(resourceName, "service_role"), + resource.TestCheckResourceAttrPair(resourceName, "arn", dataSourceName, "arn"), + resource.TestCheckResourceAttrPair(resourceName, "created_time", dataSourceName, "created_time"), + resource.TestCheckResourceAttrPair(resourceName, "identity_management_type", dataSourceName, "identity_management_type"), + resource.TestCheckResourceAttrPair(resourceName, "instance_alias", dataSourceName, "instance_alias"), + resource.TestCheckResourceAttrPair(resourceName, "inbound_calls_enabled", dataSourceName, "inbound_calls_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "outbound_calls_enabled", dataSourceName, "outbound_calls_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "contact_flow_logs_enabled", dataSourceName, "contact_flow_logs_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "contact_lens_enabled", dataSourceName, "contact_lens_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "auto_resolve_best_voices_enabled", dataSourceName, "auto_resolve_best_voices_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "early_media_enabled", dataSourceName, "early_media_enabled"), + resource.TestCheckResourceAttrPair(resourceName, "status", dataSourceName, "status"), + resource.TestCheckResourceAttrPair(resourceName, "service_role", dataSourceName, "service_role"), ), }, },