diff --git a/aws/resource_aws_cognito_user_pool.go b/aws/resource_aws_cognito_user_pool.go index 0de8d1e2787..341ee3043f1 100644 --- a/aws/resource_aws_cognito_user_pool.go +++ b/aws/resource_aws_cognito_user_pool.go @@ -7,7 +7,6 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/cognitoidentityprovider" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -536,6 +535,33 @@ func resourceAwsCognitoUserPool() *schema.Resource { }, }, }, + "account_recovery_setting": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "recovery_mechanism": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(cognitoidentityprovider.RecoveryOptionNameType_Values(), false), + }, + "priority": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + }, + }, + }, }, } } @@ -556,12 +582,21 @@ func resourceAwsCognitoUserPoolCreate(d *schema.ResourceData, meta interface{}) } } + if v, ok := d.GetOk("account_recovery_setting"); ok { + configs := v.([]interface{}) + config, ok := configs[0].(map[string]interface{}) + + if ok && config != nil { + params.AccountRecoverySetting = expandCognitoUserPoolAccountRecoverySettingConfig(config) + } + } + if v, ok := d.GetOk("alias_attributes"); ok { - params.AliasAttributes = expandStringList(v.(*schema.Set).List()) + params.AliasAttributes = expandStringSet(v.(*schema.Set)) } if v, ok := d.GetOk("auto_verified_attributes"); ok { - params.AutoVerifiedAttributes = expandStringList(v.(*schema.Set).List()) + params.AutoVerifiedAttributes = expandStringSet(v.(*schema.Set)) } if v, ok := d.GetOk("email_configuration"); ok { @@ -722,10 +757,10 @@ func resourceAwsCognitoUserPoolCreate(d *schema.ResourceData, meta interface{}) resp, err = conn.CreateUserPool(params) } if err != nil { - return fmt.Errorf("Error creating Cognito User Pool: %s", err) + return fmt.Errorf("error creating Cognito User Pool: %w", err) } - d.SetId(*resp.UserPool.Id) + d.SetId(aws.StringValue(resp.UserPool.Id)) if v := d.Get("mfa_configuration").(string); v != cognitoidentityprovider.UserPoolMfaTypeOff { input := &cognitoidentityprovider.SetUserPoolMfaConfigInput{ @@ -796,21 +831,15 @@ func resourceAwsCognitoUserPoolRead(d *schema.ResourceData, meta interface{}) er } if err := d.Set("admin_create_user_config", flattenCognitoUserPoolAdminCreateUserConfig(resp.UserPool.AdminCreateUserConfig)); err != nil { - return fmt.Errorf("Failed setting admin_create_user_config: %s", err) + return fmt.Errorf("failed setting admin_create_user_config: %w", err) } if resp.UserPool.AliasAttributes != nil { - d.Set("alias_attributes", flattenStringList(resp.UserPool.AliasAttributes)) - } - arn := arn.ARN{ - Partition: meta.(*AWSClient).partition, - Region: meta.(*AWSClient).region, - Service: "cognito-idp", - AccountID: meta.(*AWSClient).accountid, - Resource: fmt.Sprintf("userpool/%s", d.Id()), + d.Set("alias_attributes", flattenStringSet(resp.UserPool.AliasAttributes)) } - d.Set("arn", arn.String()) + + d.Set("arn", resp.UserPool.Arn) d.Set("endpoint", fmt.Sprintf("%s/%s", meta.(*AWSClient).RegionalHostname("cognito-idp"), d.Id())) - d.Set("auto_verified_attributes", flattenStringList(resp.UserPool.AutoVerifiedAttributes)) + d.Set("auto_verified_attributes", flattenStringSet(resp.UserPool.AutoVerifiedAttributes)) if resp.UserPool.EmailVerificationSubject != nil { d.Set("email_verification_subject", resp.UserPool.EmailVerificationSubject) @@ -819,7 +848,7 @@ func resourceAwsCognitoUserPoolRead(d *schema.ResourceData, meta interface{}) er d.Set("email_verification_message", resp.UserPool.EmailVerificationMessage) } if err := d.Set("lambda_config", flattenCognitoUserPoolLambdaConfig(resp.UserPool.LambdaConfig)); err != nil { - return fmt.Errorf("Failed setting lambda_config: %s", err) + return fmt.Errorf("failed setting lambda_config: %w", err) } if resp.UserPool.SmsVerificationMessage != nil { d.Set("sms_verification_message", resp.UserPool.SmsVerificationMessage) @@ -829,18 +858,22 @@ func resourceAwsCognitoUserPoolRead(d *schema.ResourceData, meta interface{}) er } if err := d.Set("device_configuration", flattenCognitoUserPoolDeviceConfiguration(resp.UserPool.DeviceConfiguration)); err != nil { - return fmt.Errorf("Failed setting device_configuration: %s", err) + return fmt.Errorf("failed setting device_configuration: %w", err) + } + + if err := d.Set("account_recovery_setting", flattenCognitoUserPoolAccountRecoverySettingConfig(resp.UserPool.AccountRecoverySetting)); err != nil { + return fmt.Errorf("failed setting account_recovery_setting: %w", err) } if resp.UserPool.EmailConfiguration != nil { if err := d.Set("email_configuration", flattenCognitoUserPoolEmailConfiguration(resp.UserPool.EmailConfiguration)); err != nil { - return fmt.Errorf("Failed setting email_configuration: %s", err) + return fmt.Errorf("failed setting email_configuration: %w", err) } } if resp.UserPool.Policies != nil && resp.UserPool.Policies.PasswordPolicy != nil { if err := d.Set("password_policy", flattenCognitoUserPoolPasswordPolicy(resp.UserPool.Policies.PasswordPolicy)); err != nil { - return fmt.Errorf("Failed setting password_policy: %s", err) + return fmt.Errorf("failed setting password_policy: %w", err) } } @@ -849,11 +882,11 @@ func resourceAwsCognitoUserPoolRead(d *schema.ResourceData, meta interface{}) er configuredSchema = v.(*schema.Set).List() } if err := d.Set("schema", flattenCognitoUserPoolSchema(expandCognitoUserPoolSchema(configuredSchema), resp.UserPool.SchemaAttributes)); err != nil { - return fmt.Errorf("Failed setting schema: %s", err) + return fmt.Errorf("failed setting schema: %w", err) } if err := d.Set("sms_configuration", flattenCognitoSmsConfiguration(resp.UserPool.SmsConfiguration)); err != nil { - return fmt.Errorf("Failed setting sms_configuration: %s", err) + return fmt.Errorf("failed setting sms_configuration: %w", err) } if resp.UserPool.UsernameAttributes != nil { @@ -861,22 +894,22 @@ func resourceAwsCognitoUserPoolRead(d *schema.ResourceData, meta interface{}) er } if err := d.Set("username_configuration", flattenCognitoUserPoolUsernameConfiguration(resp.UserPool.UsernameConfiguration)); err != nil { - return fmt.Errorf("Failed setting username_configuration: %s", err) + return fmt.Errorf("failed setting username_configuration: %w", err) } if err := d.Set("user_pool_add_ons", flattenCognitoUserPoolUserPoolAddOns(resp.UserPool.UserPoolAddOns)); err != nil { - return fmt.Errorf("Failed setting user_pool_add_ons: %s", err) + return fmt.Errorf("failed setting user_pool_add_ons: %w", err) } if err := d.Set("verification_message_template", flattenCognitoUserPoolVerificationMessageTemplate(resp.UserPool.VerificationMessageTemplate)); err != nil { - return fmt.Errorf("Failed setting verification_message_template: %s", err) + return fmt.Errorf("failed setting verification_message_template: %w", err) } d.Set("creation_date", resp.UserPool.CreationDate.Format(time.RFC3339)) d.Set("last_modified_date", resp.UserPool.LastModifiedDate.Format(time.RFC3339)) d.Set("name", resp.UserPool.Name) if err := d.Set("tags", keyvaluetags.CognitoidentityKeyValueTags(resp.UserPool.UserPoolTags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { - return fmt.Errorf("error setting tags: %s", err) + return fmt.Errorf("error setting tags: %w", err) } input := &cognitoidentityprovider.GetUserPoolMfaConfigInput{ @@ -898,7 +931,7 @@ func resourceAwsCognitoUserPoolRead(d *schema.ResourceData, meta interface{}) er d.Set("mfa_configuration", output.MfaConfiguration) if err := d.Set("software_token_mfa_configuration", flattenCognitoSoftwareTokenMfaConfiguration(output.SoftwareTokenMfaConfiguration)); err != nil { - return fmt.Errorf("error setting software_token_mfa_configuration: %s", err) + return fmt.Errorf("error setting software_token_mfa_configuration: %w", err) } return nil @@ -981,6 +1014,7 @@ func resourceAwsCognitoUserPoolUpdate(d *schema.ResourceData, meta interface{}) "tags", "user_pool_add_ons", "verification_message_template", + "account_recovery_setting", ) { params := &cognitoidentityprovider.UpdateUserPoolInput{ UserPoolId: aws.String(d.Id()), @@ -996,7 +1030,16 @@ func resourceAwsCognitoUserPoolUpdate(d *schema.ResourceData, meta interface{}) } if v, ok := d.GetOk("auto_verified_attributes"); ok { - params.AutoVerifiedAttributes = expandStringList(v.(*schema.Set).List()) + params.AutoVerifiedAttributes = expandStringSet(v.(*schema.Set)) + } + + if v, ok := d.GetOk("account_recovery_setting"); ok { + configs := v.([]interface{}) + config, ok := configs[0].(map[string]interface{}) + + if ok && config != nil { + params.AccountRecoverySetting = expandCognitoUserPoolAccountRecoverySettingConfig(config) + } } if v, ok := d.GetOk("device_configuration"); ok { @@ -1239,3 +1282,54 @@ func flattenCognitoSoftwareTokenMfaConfiguration(apiObject *cognitoidentityprovi return []interface{}{tfMap} } + +func expandCognitoUserPoolAccountRecoverySettingConfig(config map[string]interface{}) *cognitoidentityprovider.AccountRecoverySettingType { + configs := &cognitoidentityprovider.AccountRecoverySettingType{} + + mechs := make([]*cognitoidentityprovider.RecoveryOptionType, 0) + + if v, ok := config["recovery_mechanism"]; ok { + data := v.(*schema.Set).List() + + for _, m := range data { + param := m.(map[string]interface{}) + opt := &cognitoidentityprovider.RecoveryOptionType{} + + if v, ok := param["name"]; ok { + opt.Name = aws.String(v.(string)) + } + + if v, ok := param["priority"]; ok { + opt.Priority = aws.Int64(int64(v.(int))) + } + + mechs = append(mechs, opt) + } + } + + configs.RecoveryMechanisms = mechs + + return configs +} + +func flattenCognitoUserPoolAccountRecoverySettingConfig(config *cognitoidentityprovider.AccountRecoverySettingType) []interface{} { + if config == nil { + return nil + } + + settings := map[string]interface{}{} + + mechanisms := make([]map[string]interface{}, 0) + + for _, conf := range config.RecoveryMechanisms { + mech := map[string]interface{}{ + "name": aws.StringValue(conf.Name), + "priority": aws.Int64Value(conf.Priority), + } + mechanisms = append(mechanisms, mech) + } + + settings["recovery_mechanism"] = mechanisms + + return []interface{}{settings} +} diff --git a/aws/resource_aws_cognito_user_pool_test.go b/aws/resource_aws_cognito_user_pool_test.go index 089817b85a2..7b7ac932aa2 100644 --- a/aws/resource_aws_cognito_user_pool_test.go +++ b/aws/resource_aws_cognito_user_pool_test.go @@ -9,7 +9,6 @@ import ( "testing" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/cognitoidentityprovider" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -30,7 +29,7 @@ func init() { func testSweepCognitoUserPools(region string) error { client, err := sharedClientForRegion(region) if err != nil { - return fmt.Errorf("Error getting client: %s", err) + return fmt.Errorf("error getting client: %w", err) } conn := client.(*AWSClient).cognitoidpconn @@ -90,6 +89,7 @@ func TestAccAWSCognitoUserPool_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "mfa_configuration", "OFF"), resource.TestCheckResourceAttr(resourceName, "sms_configuration.#", "0"), resource.TestCheckResourceAttr(resourceName, "software_token_mfa_configuration.#", "0"), + resource.TestCheckResourceAttr(resourceName, "account_recovery_setting.#", "0"), ), }, { @@ -101,8 +101,53 @@ func TestAccAWSCognitoUserPool_basic(t *testing.T) { }) } +func TestAccAWSCognitoUserPool_recovery(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_cognito_user_pool.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSCognitoIdentityProvider(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoUserPoolConfigAccountRecoverySingle(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoUserPoolExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "account_recovery_setting.#", "1"), + resource.TestCheckResourceAttr(resourceName, "account_recovery_setting.0.recovery_mechanism.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSCognitoUserPoolConfigAccountRecoveryMulti(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoUserPoolExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "account_recovery_setting.#", "1"), + resource.TestCheckResourceAttr(resourceName, "account_recovery_setting.0.recovery_mechanism.#", "2"), + ), + }, + { + Config: testAccAWSCognitoUserPoolConfigAccountRecoveryUpdate(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoUserPoolExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "account_recovery_setting.#", "1"), + resource.TestCheckResourceAttr(resourceName, "account_recovery_setting.0.recovery_mechanism.#", "1"), + ), + }, + }, + }) +} + func TestAccAWSCognitoUserPool_withAdminCreateUserConfiguration(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -111,7 +156,7 @@ func TestAccAWSCognitoUserPool_withAdminCreateUserConfiguration(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfiguration(name), + Config: testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfiguration(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "admin_create_user_config.0.allow_admin_create_user_only", "true"), @@ -126,7 +171,7 @@ func TestAccAWSCognitoUserPool_withAdminCreateUserConfiguration(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfigurationUpdated(name), + Config: testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfigurationUpdated(rName), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "admin_create_user_config.0.allow_admin_create_user_only", "false"), resource.TestCheckResourceAttr(resourceName, "admin_create_user_config.0.invite_message_template.0.email_message", "Your username is {username} and constant password is {####}. "), @@ -140,7 +185,7 @@ func TestAccAWSCognitoUserPool_withAdminCreateUserConfiguration(t *testing.T) { // Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/11858 func TestAccAWSCognitoUserPool_withAdminCreateUserConfigurationAndPasswordPolicy(t *testing.T) { - name := acctest.RandomWithPrefix("tf-acc-test") + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -149,7 +194,7 @@ func TestAccAWSCognitoUserPool_withAdminCreateUserConfigurationAndPasswordPolicy CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfigAndPasswordPolicy(name), + Config: testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfigAndPasswordPolicy(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "admin_create_user_config.0.allow_admin_create_user_only", "true"), @@ -203,7 +248,7 @@ func TestAccAWSCognitoUserPool_withAdvancedSecurityMode(t *testing.T) { } func TestAccAWSCognitoUserPool_withDeviceConfiguration(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -212,7 +257,7 @@ func TestAccAWSCognitoUserPool_withDeviceConfiguration(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withDeviceConfiguration(name), + Config: testAccAWSCognitoUserPoolConfig_withDeviceConfiguration(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "device_configuration.0.challenge_required_on_new_device", "true"), @@ -225,7 +270,7 @@ func TestAccAWSCognitoUserPool_withDeviceConfiguration(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withDeviceConfigurationUpdated(name), + Config: testAccAWSCognitoUserPoolConfig_withDeviceConfigurationUpdated(rName), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "device_configuration.0.challenge_required_on_new_device", "false"), resource.TestCheckResourceAttr(resourceName, "device_configuration.0.device_only_remembered_on_user_prompt", "true"), @@ -236,7 +281,7 @@ func TestAccAWSCognitoUserPool_withDeviceConfiguration(t *testing.T) { } func TestAccAWSCognitoUserPool_withEmailVerificationMessage(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") subject := acctest.RandString(10) updatedSubject := acctest.RandString(10) message := fmt.Sprintf("%s {####}", acctest.RandString(10)) @@ -249,7 +294,7 @@ func TestAccAWSCognitoUserPool_withEmailVerificationMessage(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withEmailVerificationMessage(name, subject, message), + Config: testAccAWSCognitoUserPoolConfig_withEmailVerificationMessage(rName, subject, message), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "email_verification_subject", subject), @@ -262,7 +307,7 @@ func TestAccAWSCognitoUserPool_withEmailVerificationMessage(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withEmailVerificationMessage(name, updatedSubject, upatedMessage), + Config: testAccAWSCognitoUserPoolConfig_withEmailVerificationMessage(rName, updatedSubject, upatedMessage), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "email_verification_subject", updatedSubject), resource.TestCheckResourceAttr(resourceName, "email_verification_message", upatedMessage), @@ -675,8 +720,8 @@ func TestAccAWSCognitoUserPool_SmsVerificationMessage(t *testing.T) { } func TestAccAWSCognitoUserPool_withEmailConfiguration(t *testing.T) { - name := acctest.RandString(5) - replyTo := fmt.Sprintf("tf-acc-reply-%s@terraformtesting.com", name) + rName := acctest.RandomWithPrefix("tf-acc-test") + replyTo := fmt.Sprintf("tf-acc-reply-%s@terraformtesting.com", rName) resourceName := "aws_cognito_user_pool.test" sourceARN, ok := os.LookupEnv("TEST_AWS_SES_VERIFIED_EMAIL_ARN") @@ -690,7 +735,7 @@ func TestAccAWSCognitoUserPool_withEmailConfiguration(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withEmailConfiguration(name, "", "", "", "COGNITO_DEFAULT"), + Config: testAccAWSCognitoUserPoolConfig_withEmailConfiguration(rName, "", "", "", "COGNITO_DEFAULT"), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "email_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "email_configuration.0.reply_to_email_address", ""), @@ -704,7 +749,7 @@ func TestAccAWSCognitoUserPool_withEmailConfiguration(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withEmailConfiguration(name, replyTo, sourceARN, "John Smith ", "DEVELOPER"), + Config: testAccAWSCognitoUserPoolConfig_withEmailConfiguration(rName, replyTo, sourceARN, "John Smith ", "DEVELOPER"), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "email_configuration.#", "1"), resource.TestCheckResourceAttr(resourceName, "email_configuration.0.reply_to_email_address", replyTo), @@ -718,7 +763,7 @@ func TestAccAWSCognitoUserPool_withEmailConfiguration(t *testing.T) { } func TestAccAWSCognitoUserPool_withTags(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -727,7 +772,7 @@ func TestAccAWSCognitoUserPool_withTags(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_Tags1(name, "key1", "value1"), + Config: testAccAWSCognitoUserPoolConfig_Tags1(rName, "key1", "value1"), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), @@ -740,7 +785,7 @@ func TestAccAWSCognitoUserPool_withTags(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_Tags2(name, "key1", "value1updated", "key2", "value2"), + Config: testAccAWSCognitoUserPoolConfig_Tags2(rName, "key1", "value1updated", "key2", "value2"), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), @@ -748,7 +793,7 @@ func TestAccAWSCognitoUserPool_withTags(t *testing.T) { ), }, { - Config: testAccAWSCognitoUserPoolConfig_Tags1(name, "key2", "value2"), + Config: testAccAWSCognitoUserPoolConfig_Tags1(rName, "key2", "value2"), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), @@ -760,7 +805,7 @@ func TestAccAWSCognitoUserPool_withTags(t *testing.T) { } func TestAccAWSCognitoUserPool_withAliasAttributes(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -769,7 +814,7 @@ func TestAccAWSCognitoUserPool_withAliasAttributes(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withAliasAttributes(name), + Config: testAccAWSCognitoUserPoolConfig_withAliasAttributes(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "alias_attributes.#", "1"), @@ -783,7 +828,7 @@ func TestAccAWSCognitoUserPool_withAliasAttributes(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withAliasAttributesUpdated(name), + Config: testAccAWSCognitoUserPoolConfig_withAliasAttributesUpdated(rName), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "alias_attributes.#", "2"), tfawsresource.TestCheckTypeSetElemAttr(resourceName, "alias_attributes.*", "email"), @@ -797,7 +842,7 @@ func TestAccAWSCognitoUserPool_withAliasAttributes(t *testing.T) { } func TestAccAWSCognitoUserPool_withPasswordPolicy(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -806,7 +851,7 @@ func TestAccAWSCognitoUserPool_withPasswordPolicy(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withPasswordPolicy(name), + Config: testAccAWSCognitoUserPoolConfig_withPasswordPolicy(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "password_policy.#", "1"), @@ -824,7 +869,7 @@ func TestAccAWSCognitoUserPool_withPasswordPolicy(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withPasswordPolicyUpdated(name), + Config: testAccAWSCognitoUserPoolConfig_withPasswordPolicyUpdated(rName), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "password_policy.#", "1"), resource.TestCheckResourceAttr(resourceName, "password_policy.0.minimum_length", "9"), @@ -840,7 +885,7 @@ func TestAccAWSCognitoUserPool_withPasswordPolicy(t *testing.T) { } func TestAccAWSCognitoUserPool_withUsernameConfiguration(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -849,7 +894,7 @@ func TestAccAWSCognitoUserPool_withUsernameConfiguration(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withUsernameConfiguration(name), + Config: testAccAWSCognitoUserPoolConfig_withUsernameConfiguration(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "username_configuration.#", "1"), @@ -862,7 +907,7 @@ func TestAccAWSCognitoUserPool_withUsernameConfiguration(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withUsernameConfigurationUpdated(name), + Config: testAccAWSCognitoUserPoolConfig_withUsernameConfigurationUpdated(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "username_configuration.#", "1"), @@ -874,7 +919,7 @@ func TestAccAWSCognitoUserPool_withUsernameConfiguration(t *testing.T) { } func TestAccAWSCognitoUserPool_withLambdaConfig(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -883,7 +928,7 @@ func TestAccAWSCognitoUserPool_withLambdaConfig(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withLambdaConfig(name), + Config: testAccAWSCognitoUserPoolConfig_withLambdaConfig(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "lambda_config.#", "1"), @@ -905,7 +950,7 @@ func TestAccAWSCognitoUserPool_withLambdaConfig(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withLambdaConfigUpdated(name), + Config: testAccAWSCognitoUserPoolConfig_withLambdaConfigUpdated(rName), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "lambda_config.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "lambda_config.0.create_auth_challenge"), @@ -925,7 +970,7 @@ func TestAccAWSCognitoUserPool_withLambdaConfig(t *testing.T) { } func TestAccAWSCognitoUserPool_withSchemaAttributes(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -934,7 +979,7 @@ func TestAccAWSCognitoUserPool_withSchemaAttributes(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withSchemaAttributes(name), + Config: testAccAWSCognitoUserPoolConfig_withSchemaAttributes(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "schema.#", "2"), @@ -966,7 +1011,7 @@ func TestAccAWSCognitoUserPool_withSchemaAttributes(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withSchemaAttributesUpdated(name), + Config: testAccAWSCognitoUserPoolConfig_withSchemaAttributesUpdated(rName), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "schema.#", "3"), tfawsresource.TestCheckTypeSetElemNestedAttrs(resourceName, "schema.*", map[string]string{ @@ -1014,7 +1059,7 @@ func TestAccAWSCognitoUserPool_withSchemaAttributes(t *testing.T) { } func TestAccAWSCognitoUserPool_withVerificationMessageTemplate(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_cognito_user_pool.test" resource.ParallelTest(t, resource.TestCase{ @@ -1023,7 +1068,7 @@ func TestAccAWSCognitoUserPool_withVerificationMessageTemplate(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_withVerificationMessageTemplate(name), + Config: testAccAWSCognitoUserPoolConfig_withVerificationMessageTemplate(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "verification_message_template.0.default_email_option", "CONFIRM_WITH_LINK"), @@ -1047,7 +1092,7 @@ func TestAccAWSCognitoUserPool_withVerificationMessageTemplate(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_withVerificationMessageTemplate_DefaultEmailOption(name), + Config: testAccAWSCognitoUserPoolConfig_withVerificationMessageTemplate_DefaultEmailOption(rName), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "verification_message_template.0.default_email_option", "CONFIRM_WITH_CODE"), resource.TestCheckResourceAttr(resourceName, "email_verification_message", "{####} Baz"), @@ -1067,7 +1112,7 @@ func TestAccAWSCognitoUserPool_withVerificationMessageTemplate(t *testing.T) { } func TestAccAWSCognitoUserPool_update(t *testing.T) { - name := acctest.RandString(5) + rName := acctest.RandomWithPrefix("tf-acc-test") optionalMfa := "OPTIONAL" offMfa := "OFF" authenticationMessage := fmt.Sprintf("%s {####}", acctest.RandString(10)) @@ -1080,7 +1125,7 @@ func TestAccAWSCognitoUserPool_update(t *testing.T) { CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSCognitoUserPoolConfig_update(name, optionalMfa, authenticationMessage), + Config: testAccAWSCognitoUserPoolConfig_update(rName, optionalMfa, authenticationMessage), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "auto_verified_attributes.#", "1"), @@ -1099,7 +1144,6 @@ func TestAccAWSCognitoUserPool_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "sms_configuration.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "sms_configuration.0.external_id"), resource.TestCheckResourceAttrSet(resourceName, "sms_configuration.0.sns_caller_arn"), - resource.TestCheckResourceAttr(resourceName, "tags.Name", "Foo"), ), }, { @@ -1108,7 +1152,7 @@ func TestAccAWSCognitoUserPool_update(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAWSCognitoUserPoolConfig_update(name, optionalMfa, updatedAuthenticationMessage), + Config: testAccAWSCognitoUserPoolConfig_update(rName, optionalMfa, updatedAuthenticationMessage), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "auto_verified_attributes.#", "1"), @@ -1127,11 +1171,10 @@ func TestAccAWSCognitoUserPool_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "sms_configuration.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "sms_configuration.0.external_id"), resource.TestCheckResourceAttrSet(resourceName, "sms_configuration.0.sns_caller_arn"), - resource.TestCheckResourceAttr(resourceName, "tags.Name", "Foo"), ), }, { - Config: testAccAWSCognitoUserPoolConfig_update(name, offMfa, updatedAuthenticationMessage), + Config: testAccAWSCognitoUserPoolConfig_update(rName, offMfa, updatedAuthenticationMessage), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSCognitoUserPoolExists(resourceName), resource.TestCheckResourceAttr(resourceName, "auto_verified_attributes.#", "1"), @@ -1150,13 +1193,33 @@ func TestAccAWSCognitoUserPool_update(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "sms_configuration.#", "1"), resource.TestCheckResourceAttrSet(resourceName, "sms_configuration.0.external_id"), resource.TestCheckResourceAttrSet(resourceName, "sms_configuration.0.sns_caller_arn"), - resource.TestCheckResourceAttr(resourceName, "tags.Name", "Foo"), ), }, }, }) } +func TestAccAWSCognitoUserPool_disappears(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_cognito_user_pool.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSCognitoIdentityProvider(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCognitoUserPoolDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCognitoUserPoolConfig_Name(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSCognitoUserPoolExists(resourceName), + testAccCheckResourceDisappears(testAccProvider, resourceAwsCognitoUserPool(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckAWSCognitoUserPoolDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).cognitoidpconn @@ -1172,7 +1235,7 @@ func testAccCheckAWSCognitoUserPoolDestroy(s *terraform.State) error { _, err := conn.DescribeUserPool(params) if err != nil { - if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == cognitoidentityprovider.ErrCodeResourceNotFoundException { + if isAWSErr(err, cognitoidentityprovider.ErrCodeResourceNotFoundException, "") { return nil } return err @@ -1271,10 +1334,60 @@ resource "aws_cognito_user_pool" "test" { `, rName) } -func testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfiguration(name string) string { +func testAccAWSCognitoUserPoolConfigAccountRecoverySingle(rName string) string { + return fmt.Sprintf(` +resource "aws_cognito_user_pool" "test" { + name = %[1]q + + account_recovery_setting { + recovery_mechanism { + name = "verified_email" + priority = 1 + } + } +} +`, rName) +} + +func testAccAWSCognitoUserPoolConfigAccountRecoveryMulti(rName string) string { + return fmt.Sprintf(` +resource "aws_cognito_user_pool" "test" { + name = %[1]q + + account_recovery_setting { + recovery_mechanism { + name = "verified_email" + priority = 1 + } + + recovery_mechanism { + name = "verified_phone_number" + priority = 2 + } + } +} +`, rName) +} + +func testAccAWSCognitoUserPoolConfigAccountRecoveryUpdate(rName string) string { + return fmt.Sprintf(` +resource "aws_cognito_user_pool" "test" { + name = %[1]q + + account_recovery_setting { + recovery_mechanism { + name = "verified_phone_number" + priority = 1 + } + } +} +`, rName) +} + +func testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfiguration(rName string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q admin_create_user_config { allow_admin_create_user_only = true @@ -1286,13 +1399,13 @@ resource "aws_cognito_user_pool" "test" { } } } -`, name) +`, rName) } -func testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfigurationUpdated(name string) string { +func testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfigurationUpdated(rName string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q admin_create_user_config { allow_admin_create_user_only = false @@ -1304,7 +1417,7 @@ resource "aws_cognito_user_pool" "test" { } } } -`, name) +`, rName) } func testAccAWSCognitoUserPoolConfig_AdvancedSecurityMode(rName string, advancedSecurityMode string) string { @@ -1319,44 +1432,44 @@ resource "aws_cognito_user_pool" "test" { `, rName, advancedSecurityMode) } -func testAccAWSCognitoUserPoolConfig_withDeviceConfiguration(name string) string { +func testAccAWSCognitoUserPoolConfig_withDeviceConfiguration(rName string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q device_configuration { challenge_required_on_new_device = true device_only_remembered_on_user_prompt = false } } -`, name) +`, rName) } -func testAccAWSCognitoUserPoolConfig_withDeviceConfigurationUpdated(name string) string { +func testAccAWSCognitoUserPoolConfig_withDeviceConfigurationUpdated(rName string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q device_configuration { challenge_required_on_new_device = false device_only_remembered_on_user_prompt = true } } -`, name) +`, rName) } -func testAccAWSCognitoUserPoolConfig_withEmailVerificationMessage(name, subject, message string) string { +func testAccAWSCognitoUserPoolConfig_withEmailVerificationMessage(rName, subject, message string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" - email_verification_subject = "%s" - email_verification_message = "%s" + name = %[1]q + email_verification_subject = "%[2]s" + email_verification_message = "%[3]s" verification_message_template { default_email_option = "CONFIRM_WITH_CODE" } } -`, name, subject, message) +`, rName, subject, message) } func testAccAWSCognitoUserPoolConfig_MfaConfiguration(rName string, mfaConfiguration string) string { @@ -1457,7 +1570,7 @@ resource "aws_cognito_user_pool" "test" { `, rName, smsVerificationMessage) } -func testAccAWSCognitoUserPoolConfig_Tags1(name, tagKey1, tagValue1 string) string { +func testAccAWSCognitoUserPoolConfig_Tags1(rName, tagKey1, tagValue1 string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { name = %[1]q @@ -1466,10 +1579,10 @@ resource "aws_cognito_user_pool" "test" { %[2]q = %[3]q } } -`, name, tagKey1, tagValue1) +`, rName, tagKey1, tagValue1) } -func testAccAWSCognitoUserPoolConfig_Tags2(name, tagKey1, tagValue1, tagKey2, tagValue2 string) string { +func testAccAWSCognitoUserPoolConfig_Tags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { name = %[1]q @@ -1479,13 +1592,13 @@ resource "aws_cognito_user_pool" "test" { %[4]q = %[5]q } } -`, name, tagKey1, tagValue1, tagKey2, tagValue2) +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) } -func testAccAWSCognitoUserPoolConfig_withEmailConfiguration(name, email, arn, from, account string) string { +func testAccAWSCognitoUserPoolConfig_withEmailConfiguration(rName, email, arn, from, account string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%[1]s" + name = %[1]q email_configuration { reply_to_email_address = %[2]q @@ -1494,28 +1607,28 @@ resource "aws_cognito_user_pool" "test" { email_sending_account = %[5]q } } -`, name, email, arn, from, account) +`, rName, email, arn, from, account) } -func testAccAWSCognitoUserPoolConfig_withAliasAttributes(name string) string { +func testAccAWSCognitoUserPoolConfig_withAliasAttributes(rName string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q alias_attributes = ["preferred_username"] } -`, name) +`, rName) } -func testAccAWSCognitoUserPoolConfig_withAliasAttributesUpdated(name string) string { +func testAccAWSCognitoUserPoolConfig_withAliasAttributesUpdated(rName string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q alias_attributes = ["email", "preferred_username"] auto_verified_attributes = ["email"] } -`, name) +`, rName) } func testAccAWSCognitoUserPoolConfig_withAdminCreateUserConfigAndPasswordPolicy(rName string) string { @@ -1542,7 +1655,7 @@ resource "aws_cognito_user_pool" "test" { func testAccAWSCognitoUserPoolConfig_withPasswordPolicy(name string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q password_policy { minimum_length = 7 @@ -1559,7 +1672,7 @@ resource "aws_cognito_user_pool" "test" { func testAccAWSCognitoUserPoolConfig_withPasswordPolicyUpdated(name string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q password_policy { minimum_length = 9 @@ -1576,7 +1689,7 @@ resource "aws_cognito_user_pool" "test" { func testAccAWSCognitoUserPoolConfig_withUsernameConfiguration(name string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q username_configuration { case_sensitive = true @@ -1588,7 +1701,7 @@ resource "aws_cognito_user_pool" "test" { func testAccAWSCognitoUserPoolConfig_withUsernameConfigurationUpdated(name string) string { return fmt.Sprintf(` resource "aws_cognito_user_pool" "test" { - name = "terraform-test-pool-%s" + name = %[1]q username_configuration { case_sensitive = false @@ -1600,7 +1713,7 @@ resource "aws_cognito_user_pool" "test" { func testAccAWSCognitoUserPoolConfig_withLambdaConfig(name string) string { return fmt.Sprintf(` resource "aws_iam_role" "test" { - name = "%s" + name = %[1]q assume_role_policy = <