diff --git a/docs/resources/identity_user_v3.md b/docs/resources/identity_user_v3.md index 8ca3da73..9b052e3d 100644 --- a/docs/resources/identity_user_v3.md +++ b/docs/resources/identity_user_v3.md @@ -24,28 +24,41 @@ resource "flexibleengine_identity_user_v3" "user_1" { The following arguments are supported: -* `name` - (Required, String) Specifies the name of the user. The user name consists of - 5 to 32 characters. It can contain only uppercase letters, lowercase letters, - digits, spaces, and special characters (-_) and cannot start with a digit. +* `name` - (Required, String) Specifies the name of the user. The user name consists of 5 to 32 characters. It can + contain only uppercase letters, lowercase letters, digits, spaces, and special characters (-_) and cannot start with a + digit. * `description` - (Optional, String) Specifies the description of the user. * `email` - (Optional, String) Specifies the email address with a maximum of 255 characters. -* `phone` - (Optional, String) Specifies the mobile number with a maximum of 32 digits. - This parameter must be used together with `country_code`. +* `phone` - (Optional, String) Specifies the mobile number with a maximum of 32 digits. This parameter must be used + together with `country_code`. -* `country_code` - (Optional, String) Specifies the country code. The country code of the Chinese mainland is 0086. - This parameter must be used together with `phone`. +* `country_code` - (Optional, String) Specifies the country code. The country code of the Chinese mainland is 0086. This + parameter must be used together with `phone`. -* `password` - (Optional, String) Specifies the password for the user with 6 to 32 characters. - It must contain at least two of the following character types: uppercase letters, lowercase letters, - digits, and special characters. +* `password` - (Optional, String) Specifies the password for the user with 6 to 32 characters. It must contain at least + two of the following character types: uppercase letters, lowercase letters, digits, and special characters. -* `enabled` - (Optional, Bool) Specifies whether the user is enabled or disabled. - Valid values are `true` and `false`. +* `pwd_reset` - (Optional, Bool) Specifies whether or not the password should be reset. By default, the password is asked + to reset at the first login. -## Attributes Reference +* `enabled` - (Optional, Bool) Specifies whether the user is enabled or disabled. Valid values are `true` and `false`. + +* `access_type` - (Optional, String) Specifies the access type of the user. Available values are: + + **default**: support both programmatic and management console access. + + **programmatic**: only support programmatic access. + + **console**: only support management console access. + +* `external_identity_id` - (Optional, String) Specifies the ID of the IAM user in the external system. + This parameter is used for IAM user SSO type, make sure that the **IAM_SAML_Attributes_xUserId** of the federated user + is the same as the `external_identity_id` of the corresponding IAM user. + +* `external_identity_type` - (Optional, String) Specifies the type of the IAM user in the external system. + Only **TenantIdp** is supported now. This parameter must be used together with `external_identity_id`. + +## Attribute Reference In addition to all arguments above, the following attributes are exported: @@ -55,7 +68,7 @@ In addition to all arguments above, the following attributes are exported: * `create_time` - The time when the IAM user was created. -* `last_login` - The tiem when the IAM user last login. +* `last_login` - The time when the IAM user last login. ## Import diff --git a/flexibleengine/acceptance/resource_flexibleengine_identity_user_v3_test.go b/flexibleengine/acceptance/resource_flexibleengine_identity_user_v3_test.go new file mode 100644 index 00000000..b6a314c7 --- /dev/null +++ b/flexibleengine/acceptance/resource_flexibleengine_identity_user_v3_test.go @@ -0,0 +1,188 @@ +package acceptance + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/chnsz/golangsdk/openstack/identity/v3.0/users" + + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance" +) + +func getIdentityUserResourceFunc(c *config.Config, state *terraform.ResourceState) (interface{}, error) { + client, err := c.IAMV3Client(OS_REGION_NAME) + if err != nil { + return nil, fmt.Errorf("error creating IAM client: %s", err) + } + return users.Get(client, state.Primary.ID).Extract() +} + +func TestAccIdentityUser_basic(t *testing.T) { + var user users.User + userName := acceptance.RandomAccResourceName() + initPassword := acceptance.RandomPassword() + newPassword := acceptance.RandomPassword() + resourceName := "flexibleengine_identity_user_v3.user_1" + + rc := acceptance.InitResourceCheck( + resourceName, + &user, + getIdentityUserResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckAdminOnly(t) + }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testAccIdentityUser_basic(userName, initPassword), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(resourceName, "name", userName), + resource.TestCheckResourceAttr(resourceName, "description", "tested by terraform"), + resource.TestCheckResourceAttr(resourceName, "enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "pwd_reset", "true"), + resource.TestCheckResourceAttr(resourceName, "email", "user_1@abc.com"), + resource.TestCheckResourceAttr(resourceName, "password_strength", "Strong"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "password", + }, + }, + { + Config: testAccIdentityUser_update(userName, newPassword), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(resourceName, "name", userName), + resource.TestCheckResourceAttr(resourceName, "description", "updated by terraform"), + resource.TestCheckResourceAttr(resourceName, "enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "pwd_reset", "false"), + resource.TestCheckResourceAttr(resourceName, "email", "user_1@abcd.com"), + ), + }, + { + Config: testAccIdentityUser_no_desc(userName, newPassword), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(resourceName, "name", userName), + resource.TestCheckResourceAttr(resourceName, "description", ""), + ), + }, + }, + }) +} + +func TestAccIdentityUser_external(t *testing.T) { + var user users.User + userName := acceptance.RandomAccResourceName() + password := acceptance.RandomPassword() + initXUserID := "123456789-abcdefg" + newXUserID := "abcdefg-123456789" + resourceName := "flexibleengine_identity_user_v3.user_1" + + rc := acceptance.InitResourceCheck( + resourceName, + &user, + getIdentityUserResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckAdminOnly(t) + }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testAccIdentityUser_external(userName, password, initXUserID), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(resourceName, "name", userName), + resource.TestCheckResourceAttr(resourceName, "description", "IAM user with external identity id"), + resource.TestCheckResourceAttr(resourceName, "enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "pwd_reset", "true"), + resource.TestCheckResourceAttr(resourceName, "password_strength", "Strong"), + resource.TestCheckResourceAttr(resourceName, "external_identity_id", initXUserID), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "password", + }, + }, + { + Config: testAccIdentityUser_external(userName, password, newXUserID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "name", userName), + resource.TestCheckResourceAttr(resourceName, "external_identity_id", newXUserID), + ), + }, + }, + }) +} + +func testAccIdentityUser_basic(name, password string) string { + return fmt.Sprintf(` +resource "flexibleengine_identity_user_v3" "user_1" { + name = "%s" + password = "%s" + enabled = true + email = "user_1@abc.com" + description = "tested by terraform" +} +`, name, password) +} + +func testAccIdentityUser_update(name, password string) string { + return fmt.Sprintf(` +resource "flexibleengine_identity_user_v3" "user_1" { + name = "%s" + password = "%s" + pwd_reset = false + enabled = false + email = "user_1@abcd.com" + description = "updated by terraform" +} +`, name, password) +} + +func testAccIdentityUser_no_desc(name, password string) string { + return fmt.Sprintf(` +resource "flexibleengine_identity_user_v3" "user_1" { + name = "%s" + password = "%s" + pwd_reset = false + enabled = false + email = "user_1@abcd.com" +} +`, name, password) +} + +func testAccIdentityUser_external(name, password, xUserID string) string { + return fmt.Sprintf(` +resource "flexibleengine_identity_user_v3" "user_1" { + name = "%s" + password = "%s" + description = "IAM user with external identity id" + external_identity_id = "%s" +} +`, name, password, xUserID) +} + diff --git a/flexibleengine/provider.go b/flexibleengine/provider.go index 5a861c87..6853d025 100644 --- a/flexibleengine/provider.go +++ b/flexibleengine/provider.go @@ -457,7 +457,6 @@ func Provider() *schema.Provider { "flexibleengine_identity_project_v3": resourceIdentityProjectV3(), "flexibleengine_identity_role_v3": resourceIdentityRoleV3(), "flexibleengine_identity_role_assignment_v3": resourceIdentityRoleAssignmentV3(), - "flexibleengine_identity_user_v3": resourceIdentityUserV3(), "flexibleengine_identity_provider": resourceIdentityProvider(), "flexibleengine_identity_provider_conversion": resourceIAMProviderConversion(), @@ -624,7 +623,8 @@ func Provider() *schema.Provider { "flexibleengine_gaussdb_cassandra_instance": gaussdb.ResourceGeminiDBInstanceV3(), "flexibleengine_gaussdb_influx_instance": gaussdb.ResourceGaussDBInfluxInstanceV3(), - "flexibleengine_identity_acl": iam.ResourceIdentityACL(), + "flexibleengine_identity_acl": iam.ResourceIdentityACL(), + "flexibleengine_identity_user_v3": iam.ResourceIdentityUser(), "flexibleengine_images_image": ims.ResourceImsImage(), "flexibleengine_images_image_copy": ims.ResourceImsImageCopy(),