diff --git a/.changelog/21097.txt b/.changelog/21097.txt new file mode 100644 index 00000000000..1bea9b9b9a8 --- /dev/null +++ b/.changelog/21097.txt @@ -0,0 +1,7 @@ +```release-note:new-data-source +aws_connect_bot_association +``` + +```release-note:new-resource +aws_connect_bot_association +``` diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 3891ed4d0de..e6998e3959a 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -394,8 +394,9 @@ func Provider() *schema.Provider { "aws_cognito_user_pools": cognitoidp.DataSourceUserPools(), - "aws_connect_contact_flow": connect.DataSourceContactFlow(), - "aws_connect_instance": connect.DataSourceInstance(), + "aws_connect_bot_association": connect.DataSourceBotAssociation(), + "aws_connect_contact_flow": connect.DataSourceContactFlow(), + "aws_connect_instance": connect.DataSourceInstance(), "aws_cur_report_definition": cur.DataSourceReportDefinition(), @@ -926,8 +927,9 @@ func Provider() *schema.Provider { "aws_config_organization_managed_rule": config.ResourceOrganizationManagedRule(), "aws_config_remediation_configuration": config.ResourceRemediationConfiguration(), - "aws_connect_contact_flow": connect.ResourceContactFlow(), - "aws_connect_instance": connect.ResourceInstance(), + "aws_connect_bot_association": connect.ResourceBotAssociation(), + "aws_connect_contact_flow": connect.ResourceContactFlow(), + "aws_connect_instance": connect.ResourceInstance(), "aws_cur_report_definition": cur.ResourceReportDefinition(), diff --git a/internal/service/connect/bot_association.go b/internal/service/connect/bot_association.go new file mode 100644 index 00000000000..23f14567fd9 --- /dev/null +++ b/internal/service/connect/bot_association.go @@ -0,0 +1,222 @@ +package connect + +import ( + "context" + "fmt" + "log" + + "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/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +func ResourceBotAssociation() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceBotAssociationCreate, + ReadContext: resourceBotAssociationRead, + DeleteContext: resourceBotAssociationDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "lex_bot": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "lex_region": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(2, 50), + }, + }, + }, + }, + /* We would need a schema like this to support a v1/v2 hybrid + "lex_v2_bot": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "alias_arn": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidARN, + ForceNew: true, + }, + }, + }, + }, + */ + }, + } +} + +func resourceBotAssociationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).ConnectConn + + instanceId := d.Get("instance_id").(string) + + input := &connect.AssociateBotInput{ + InstanceId: aws.String(instanceId), + } + + if v, ok := d.GetOk("lex_bot"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + lexBot := expandLexBot(v.([]interface{})) + if lexBot.LexRegion == nil { + lexBot.LexRegion = aws.String(meta.(*conns.AWSClient).Region) + } + input.LexBot = lexBot + } + + /* We would need something like this and additionally the opposite on the above + if v, ok := d.GetOk("lex_v2_bot"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + input.LexV2Bot = expandLexV2Bot(v.([]interface{})) + } + */ + + _, err := tfresource.RetryWhen( + connectBotAssociationCreateTimeout, + func() (interface{}, error) { + return conn.AssociateBotWithContext(ctx, input) + }, + func(err error) (bool, error) { + if tfawserr.ErrCodeEquals(err, connect.ErrCodeInvalidRequestException) { + return true, err + } + + return false, err + }, + ) + + lbaId := BotV1AssociationCreateResourceID(instanceId, aws.StringValue(input.LexBot.Name), aws.StringValue(input.LexBot.LexRegion)) + + if err != nil { + return diag.FromErr(fmt.Errorf("error creating Connect Bot Association (%s): %w", lbaId, err)) + } + + d.SetId(lbaId) + + return resourceBotAssociationRead(ctx, d, meta) +} + +func resourceBotAssociationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).ConnectConn + + instanceId, name, region, err := BotV1AssociationParseResourceID(d.Id()) + + if err != nil { + return diag.FromErr(err) + } + + lexBot, err := FindBotAssociationV1ByNameAndRegionWithContext(ctx, conn, instanceId, name, region) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] Connect Bot Association (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return diag.FromErr(fmt.Errorf("error reading Connect Bot Association (%s): %w", d.Id(), err)) + } + + if lexBot == nil { + return diag.FromErr(fmt.Errorf("error reading Connect Bot Association (%s): empty output", d.Id())) + } + + d.Set("instance_id", instanceId) + if err := d.Set("lex_bot", flattenLexBot(lexBot)); err != nil { + return diag.FromErr(fmt.Errorf("error setting lex_bot: %w", err)) + } + + return nil +} + +func resourceBotAssociationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).ConnectConn + + instanceID, name, region, err := BotV1AssociationParseResourceID(d.Id()) + + if err != nil { + return diag.FromErr(err) + } + + lexBot := &connect.LexBot{ + Name: aws.String(name), + LexRegion: aws.String(region), + } + + input := &connect.DisassociateBotInput{ + InstanceId: aws.String(instanceID), + LexBot: lexBot, + } + + _, err = conn.DisassociateBotWithContext(ctx, input) + + if tfawserr.ErrCodeEquals(err, connect.ErrCodeResourceNotFoundException) { + return nil + } + + if err != nil { + return diag.FromErr(fmt.Errorf("error deleting Connect Bot Association (%s): %w", d.Id(), err)) + } + + return nil +} + +func expandLexBot(l []interface{}) *connect.LexBot { + if len(l) == 0 || l[0] == nil { + return nil + } + + tfMap, ok := l[0].(map[string]interface{}) + if !ok { + return nil + } + + result := &connect.LexBot{ + Name: aws.String(tfMap["name"].(string)), + } + + if v, ok := tfMap["lex_region"].(string); ok && v != "" { + result.LexRegion = aws.String(v) + } + + return result +} + +func flattenLexBot(bot *connect.LexBot) []interface{} { + if bot == nil { + return []interface{}{} + } + + m := map[string]interface{}{ + "lex_region": bot.LexRegion, + "name": bot.Name, + } + + return []interface{}{m} +} diff --git a/internal/service/connect/bot_association_data_source.go b/internal/service/connect/bot_association_data_source.go new file mode 100644 index 00000000000..11add7385e5 --- /dev/null +++ b/internal/service/connect/bot_association_data_source.go @@ -0,0 +1,74 @@ +package connect + +import ( + "context" + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-aws/internal/conns" +) + +func DataSourceBotAssociation() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceBotAssociationRead, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + }, + "lex_bot": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "lex_region": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(2, 50), + }, + }, + }, + }, + }, + } +} + +func dataSourceBotAssociationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).ConnectConn + + instanceID := d.Get("instance_id").(string) + + var name, region string + if v, ok := d.GetOk("lex_bot"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + lexBot := expandLexBot(v.([]interface{})) + name = aws.StringValue(lexBot.Name) + region = aws.StringValue(lexBot.LexRegion) + } + + lexBot, err := FindBotAssociationV1ByNameAndRegionWithContext(ctx, conn, instanceID, name, region) + if err != nil { + return diag.FromErr(fmt.Errorf("error finding Connect Bot Association (%s,%s): %w", instanceID, name, err)) + } + + if lexBot == nil { + return diag.FromErr(fmt.Errorf("error finding Connect Bot Association (%s,%s) : not found", instanceID, name)) + } + + d.SetId(meta.(*conns.AWSClient).Region) + + d.Set("instance_id", instanceID) + if err := d.Set("lex_bot", flattenLexBot(lexBot)); err != nil { + return diag.FromErr(fmt.Errorf("error setting lex_bot: %w", err)) + } + + return nil +} diff --git a/internal/service/connect/bot_association_data_source_test.go b/internal/service/connect/bot_association_data_source_test.go new file mode 100644 index 00000000000..8ed66c3a1df --- /dev/null +++ b/internal/service/connect/bot_association_data_source_test.go @@ -0,0 +1,99 @@ +package connect_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/connect" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" +) + +func TestAccConnectBotAssociationDataSource_basic(t *testing.T) { + rName := sdkacctest.RandStringFromCharSet(8, sdkacctest.CharSetAlpha) + rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_connect_bot_association.test" + datasourceName := "data.aws_connect_bot_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, connect.EndpointsID), + Providers: acctest.Providers, + Steps: []resource.TestStep{ + { + Config: testAccBotAssociationDataSource_ConfigBasic(rName, rName2), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrPair(datasourceName, "instance_id", resourceName, "instance_id"), + resource.TestCheckResourceAttrPair(datasourceName, "lex_bot", resourceName, "lex_bot"), + ), + }, + }, + }) +} + +func testAccBotAssociationDataSource_BaseConfig(rName string, rName2 string) string { + return fmt.Sprintf(` +data "aws_region" "current" {} + +resource "aws_lex_intent" "test" { + create_version = true + name = %[1]q + fulfillment_activity { + type = "ReturnIntent" + } + sample_utterances = [ + "I would like to pick up flowers", + ] +} + +resource "aws_lex_bot" "test" { + abort_statement { + message { + content = "Sorry, I am not able to assist at this time" + content_type = "PlainText" + } + } + clarification_prompt { + max_attempts = 2 + message { + content = "I didn't understand you, what would you like to do?" + content_type = "PlainText" + } + } + intent { + intent_name = aws_lex_intent.test.name + intent_version = "1" + } + child_directed = false + name = %[1]q + process_behavior = "BUILD" +} + +resource "aws_connect_instance" "test" { + identity_management_type = "CONNECT_MANAGED" + inbound_calls_enabled = true + instance_alias = %[2]q + outbound_calls_enabled = true +} + +resource "aws_connect_bot_association" "test" { + instance_id = aws_connect_instance.test.id + lex_bot { + lex_region = data.aws_region.current.name + name = aws_lex_bot.test.name + } +} +`, rName, rName2) +} + +func testAccBotAssociationDataSource_ConfigBasic(rName string, rName2 string) string { + return fmt.Sprintf(testAccBotAssociationDataSource_BaseConfig(rName, rName2) + ` +data "aws_connect_bot_association" "test" { + instance_id = aws_connect_instance.test.id + lex_bot { + name = aws_connect_bot_association.test.lex_bot[0].name + } +} +`) +} diff --git a/internal/service/connect/bot_association_test.go b/internal/service/connect/bot_association_test.go new file mode 100644 index 00000000000..cfad1135b5b --- /dev/null +++ b/internal/service/connect/bot_association_test.go @@ -0,0 +1,209 @@ +package connect_test + +import ( + "context" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/connect" + sdkacctest "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" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfconnect "github.com/hashicorp/terraform-provider-aws/internal/service/connect" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +//Serialized acceptance tests due to Connect account limits (max 2 parallel tests) +func TestAccConnectBotAssociation_serial(t *testing.T) { + testCases := map[string]func(t *testing.T){ + "basic": testAccBotAssociation_basic, + "disappears": testAccBotAssociation_disappears, + } + + for name, tc := range testCases { + tc := tc + t.Run(name, func(t *testing.T) { + tc(t) + }) + } +} + +func testAccBotAssociation_basic(t *testing.T) { + rName := sdkacctest.RandStringFromCharSet(8, sdkacctest.CharSetAlpha) + rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_connect_bot_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, connect.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBotAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBotV1AssociationConfigBasic(rName, rName2), + Check: resource.ComposeTestCheckFunc( + testAccCheckBotAssociationExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "instance_id"), + resource.TestCheckResourceAttr(resourceName, "lex_bot.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "lex_bot.0.name", "aws_lex_bot.test", "name"), + resource.TestCheckResourceAttrSet(resourceName, "lex_bot.0.lex_region"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccBotAssociation_disappears(t *testing.T) { + rName := sdkacctest.RandStringFromCharSet(8, sdkacctest.CharSetAlpha) + rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_connect_bot_association.test" + instanceResourceName := "aws_connect_bot_association.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, connect.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckBotAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccBotV1AssociationConfigBasic(rName, rName2), + Check: resource.ComposeTestCheckFunc( + testAccCheckBotAssociationExists(resourceName), + acctest.CheckResourceDisappears(acctest.Provider, tfconnect.ResourceBotAssociation(), instanceResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckBotAssociationExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Connect Bot Association not found: %s", resourceName) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("Connect Bot Association ID not set") + } + instanceID, name, region, err := tfconnect.BotV1AssociationParseResourceID(rs.Primary.ID) + + if err != nil { + return err + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).ConnectConn + + lexBot, err := tfconnect.FindBotAssociationV1ByNameAndRegionWithContext(context.Background(), conn, instanceID, name, region) + + if err != nil { + return fmt.Errorf("error finding Connect Bot Association (%s): %w", rs.Primary.ID, err) + } + + if lexBot == nil { + return fmt.Errorf("error finding Connect Bot Association (%s): not found", rs.Primary.ID) + } + + return nil + } +} + +func testAccCheckBotAssociationDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_connect_bot_association" { + continue + } + + if rs.Primary.ID == "" { + return fmt.Errorf("Connect Connect Bot V1 Association ID not set") + } + + instanceID, name, region, err := tfconnect.BotV1AssociationParseResourceID(rs.Primary.ID) + if err != nil { + return err + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).ConnectConn + + lexBot, err := tfconnect.FindBotAssociationV1ByNameAndRegionWithContext(context.Background(), conn, instanceID, name, region) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return fmt.Errorf("error finding Connect Bot Association (%s): %w", rs.Primary.ID, err) + } + + if lexBot != nil { + return fmt.Errorf("Connect Bot Association (%s) still exists", rs.Primary.ID) + } + } + return nil +} + +func testAccBotV1AssociationConfigBase(rName, rName2 string) string { + return fmt.Sprintf(` +resource "aws_lex_intent" "test" { + create_version = true + name = %[1]q + fulfillment_activity { + type = "ReturnIntent" + } + sample_utterances = [ + "I would like to pick up flowers", + ] +} + +resource "aws_lex_bot" "test" { + abort_statement { + message { + content = "Sorry, I am not able to assist at this time" + content_type = "PlainText" + } + } + clarification_prompt { + max_attempts = 2 + message { + content = "I didn't understand you, what would you like to do?" + content_type = "PlainText" + } + } + intent { + intent_name = aws_lex_intent.test.name + intent_version = "1" + } + child_directed = false + name = %[1]q + process_behavior = "BUILD" +} + +resource "aws_connect_instance" "test" { + identity_management_type = "CONNECT_MANAGED" + inbound_calls_enabled = true + instance_alias = %[2]q + outbound_calls_enabled = true +} + `, rName, rName2) +} + +func testAccBotV1AssociationConfigBasic(rName, rName2 string) string { + return acctest.ConfigCompose( + testAccBotV1AssociationConfigBase(rName, rName2), + ` +resource "aws_connect_bot_association" "test" { + instance_id = aws_connect_instance.test.id + lex_bot { + name = aws_lex_bot.test.name + } +} +`) +} diff --git a/internal/service/connect/enum.go b/internal/service/connect/enum.go index cb3545f59ed..d55db621ac8 100644 --- a/internal/service/connect/enum.go +++ b/internal/service/connect/enum.go @@ -3,11 +3,14 @@ package connect import "github.com/aws/aws-sdk-go/service/connect" const InstanceStatusStatusNotFound = "ResourceNotFoundException" +const BotAssociationStatusNotFound = "ResourceNotFoundException" const ( ListInstancesMaxResults = 10 // MaxResults Valid Range: Minimum value of 1. Maximum value of 1000 ListContactFlowsMaxResults = 60 + // MaxResults Valid Range: Minimum value of 1. Maximum value of 25 + ListBotsMaxResults = 25 ) func InstanceAttributeMapping() map[string]string { diff --git a/internal/service/connect/find.go b/internal/service/connect/find.go new file mode 100644 index 00000000000..cac6169defa --- /dev/null +++ b/internal/service/connect/find.go @@ -0,0 +1,62 @@ +package connect + +import ( + "context" + + "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" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +func FindBotAssociationV1ByNameAndRegionWithContext(ctx context.Context, conn *connect.Connect, instanceID, name, region string) (*connect.LexBot, error) { + var result *connect.LexBot + + input := &connect.ListBotsInput{ + InstanceId: aws.String(instanceID), + LexVersion: aws.String(connect.LexVersionV1), + MaxResults: aws.Int64(ListBotsMaxResults), + } + + err := conn.ListBotsPagesWithContext(ctx, input, func(page *connect.ListBotsOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + for _, cf := range page.LexBots { + if cf == nil || cf.LexBot == nil { + continue + } + + if name != "" && aws.StringValue(cf.LexBot.Name) != name { + continue + } + + if region != "" && aws.StringValue(cf.LexBot.LexRegion) != region { + continue + } + + result = cf.LexBot + return false + } + + return !lastPage + }) + + if tfawserr.ErrCodeEquals(err, connect.ErrCodeResourceNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if result == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return result, nil +} diff --git a/internal/service/connect/id.go b/internal/service/connect/id.go new file mode 100644 index 00000000000..426e1784f7b --- /dev/null +++ b/internal/service/connect/id.go @@ -0,0 +1,25 @@ +package connect + +import ( + "fmt" + "strings" +) + +const botV1AssociationIDSeparator = ":" + +func BotV1AssociationParseResourceID(id string) (string, string, string, error) { + parts := strings.SplitN(id, botV1AssociationIDSeparator, 3) + + if len(parts) != 3 || parts[0] == "" || parts[1] == "" || parts[2] == "" { + return "", "", "", fmt.Errorf("unexpected format of Connect Bot V1 Association ID (%s), expected instanceID:name:region", id) + } + + return parts[0], parts[1], parts[2], nil +} + +func BotV1AssociationCreateResourceID(instanceID string, botName string, region string) string { + parts := []string{instanceID, botName, region} + id := strings.Join(parts, botV1AssociationIDSeparator) + + return id +} diff --git a/internal/service/connect/wait.go b/internal/service/connect/wait.go index eb5eb53f602..eeb89a72971 100644 --- a/internal/service/connect/wait.go +++ b/internal/service/connect/wait.go @@ -15,6 +15,8 @@ const ( connectContactFlowCreateTimeout = 5 * time.Minute connectContactFlowUpdateTimeout = 5 * time.Minute + + connectBotAssociationCreateTimeout = 5 * time.Minute ) func waitInstanceCreated(ctx context.Context, conn *connect.Connect, instanceId string) (*connect.DescribeInstanceOutput, error) { diff --git a/website/docs/d/connect_bot_association.markdown b/website/docs/d/connect_bot_association.markdown new file mode 100644 index 00000000000..4142393ab33 --- /dev/null +++ b/website/docs/d/connect_bot_association.markdown @@ -0,0 +1,38 @@ +--- +subcategory: "Connect" +layout: "aws" +page_title: "AWS: aws_connect_bot_association" +description: |- + Provides details about a specific Lex (V1) Bot associated with an Amazon Connect instance +--- + +# Data Source: aws_connect_bot_association + +Provides details about a specific Lex (V1) Bot associated with an Amazon Connect instance. + +## Example Usage + +### By name + +```terraform +data "aws_connect_bot_association" "example" { + instance_id = "aaaaaaaa-bbbb-cccc-dddd-111111111111" + lex_bot { + name = "Test" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `instance_id` - (Required) The identifier of the Amazon Connect instance. You can find the instanceId in the ARN of the instance. +* `lex_bot` - (Required) Configuration information of an Amazon Lex (V1) bot. Detailed below. + +### lex_bot + +The `lex_bot` configuration block supports the following: + +* `name` - (Required) The name of the Amazon Lex (V1) bot. +* `lex_region` - (Optional) The Region that the Amazon Lex (V1) bot was created in. diff --git a/website/docs/r/connect_bot_association.markdown b/website/docs/r/connect_bot_association.markdown new file mode 100644 index 00000000000..0a949818895 --- /dev/null +++ b/website/docs/r/connect_bot_association.markdown @@ -0,0 +1,106 @@ +--- +subcategory: "Connect" +layout: "aws" +page_title: "AWS: aws_connect_bot_association" +description: |- + Associates an Amazon Connect instance to an Amazon Lex (V1) bot +--- + +# Resource: aws_connect_bot_association + +Allows the specified Amazon Connect instance to access the specified Amazon Lex (V1) bot. For more information see +[Amazon Connect: Getting Started](https://docs.aws.amazon.com/connect/latest/adminguide/amazon-connect-get-started.html) and [Add an Amazon Lex bot](https://docs.aws.amazon.com/connect/latest/adminguide/amazon-lex.html). + +~> **NOTE:** This resource only currently supports Amazon Lex (V1) Associations. + +## Example Usage + +### Basic + +```terraform +resource "aws_connect_bot_association" "example" { + instance_id = aws_connect_instance.example.id + lex_bot { + lex_region = "us-west-2" + name = "Test" + + } +} +``` + +### Including a sample Lex bot + +```terraform +data "aws_region" "current" {} + +resource "aws_lex_intent" "example" { + create_version = true + name = "connect_lex_intent" + fulfillment_activity { + type = "ReturnIntent" + } + sample_utterances = [ + "I would like to pick up flowers.", + ] +} + +resource "aws_lex_bot" "example" { + abort_statement { + message { + content = "Sorry, I am not able to assist at this time." + content_type = "PlainText" + } + } + clarification_prompt { + max_attempts = 2 + message { + content = "I didn't understand you, what would you like to do?" + content_type = "PlainText" + } + } + intent { + intent_name = aws_lex_intent.example.name + intent_version = "1" + } + + child_directed = false + name = "connect_lex_bot" + process_behavior = "BUILD" +} + +resource "aws_connect_bot_association" "example" { + instance_id = aws_connect_instance.example.id + lex_bot { + lex_region = data.aws_region.current.name + name = aws_lex_bot.example.name + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `instance_id` - (Required) The identifier of the Amazon Connect instance. You can find the instanceId in the ARN of the instance. +* `lex_bot` - (Required) Configuration information of an Amazon Lex (V1) bot. Detailed below. + +### lex_bot + +The `lex_bot` configuration block supports the following: + +* `name` - (Required) The name of the Amazon Lex (V1) bot. +* `lex_region` - (Optional) The Region that the Amazon Lex (V1) bot was created in. Defaults to current region. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The Amazon Connect instance ID, Lex (V1) bot name, and Lex (V1) bot region separated by colons (`:`). + +## Import + +`aws_connect_bot_association` can be imported by using the Amazon Connect instance ID, Lex (V1) bot name, and Lex (V1) bot region separated by colons (`:`), e.g. + +``` +$ terraform import aws_connect_bot_association.example aaaaaaaa-bbbb-cccc-dddd-111111111111:Example:us-west-2 +```