diff --git a/docs/resources/routing_skill_group.md b/docs/resources/routing_skill_group.md index 49fa2701d..a9b8eb6fe 100644 --- a/docs/resources/routing_skill_group.md +++ b/docs/resources/routing_skill_group.md @@ -55,7 +55,7 @@ resource "genesyscloud_routing_skill_group" "skillgroup" { - `description` (String) Description of the skill group - `division_id` (String) The division to which this entity belongs -- `member_divisions` (List of String) Member divisions for this skill group. +- `member_division_ids` (List of String) The IDs of member divisions to add or remove for this skill group. An empty array means all divisions will be removed, '*' means all divisions will be added. - `skill_conditions` (String) JSON encoded array of rules that will be used to determine group membership. ### Read-Only diff --git a/genesyscloud/resource_genesyscloud_user_test.go b/genesyscloud/resource_genesyscloud_user_test.go index c47e3e028..9fefdec8d 100644 --- a/genesyscloud/resource_genesyscloud_user_test.go +++ b/genesyscloud/resource_genesyscloud_user_test.go @@ -3,6 +3,7 @@ package genesyscloud import ( "context" "fmt" + "log" "strconv" "strings" "terraform-provider-genesyscloud/genesyscloud/provider" @@ -1185,7 +1186,11 @@ func testVerifyUsersDestroyed(state *terraform.State) error { diagErr := util.WithRetries(context.Background(), 20*time.Second, func() *retry.RetryError { for _, rs := range state.RootModule().Resources { - if rs.Type != resourceName { + if rs.Type != "genesyscloud_user" { + continue + } + err := checkUserDeleted(rs.Primary.ID)(state) + if err != nil { continue } _, resp, err := usersAPI.GetUser(rs.Primary.ID, nil, "", "") @@ -1194,10 +1199,10 @@ func testVerifyUsersDestroyed(state *terraform.State) error { if util.IsStatus404(resp) { continue } - return retry.NonRetryableError(util.BuildWithRetriesApiDiagnosticError(resourceName, fmt.Sprintf("Unexpected error: %s", err), resp)) + return retry.NonRetryableError(util.BuildWithRetriesApiDiagnosticError("genesyscloud_user", fmt.Sprintf("Unexpected error: %s", err), resp)) } - return retry.RetryableError(util.BuildWithRetriesApiDiagnosticError(resourceName, fmt.Sprintf("User (%s) still exists", rs.Primary.ID), resp)) + return retry.RetryableError(util.BuildWithRetriesApiDiagnosticError("genesyscloud_user", fmt.Sprintf("User (%s) still exists", rs.Primary.ID), resp)) } return nil }) @@ -1210,6 +1215,46 @@ func testVerifyUsersDestroyed(state *terraform.State) error { return nil } +func checkUserDeleted(id string) resource.TestCheckFunc { + log.Printf("Fetching user with ID: %s\n", id) + return func(s *terraform.State) error { + maxAttempts := 30 + for i := 0; i < maxAttempts; i++ { + + deleted, err := isUserDeleted(id) + if err != nil { + return err + } + if deleted { + return nil + } + time.Sleep(10 * time.Second) + } + return fmt.Errorf("user %s was not deleted properly", id) + } +} + +func isUserDeleted(id string) (bool, error) { + sdkConfig, _ := provider.AuthorizeSdk() + usersAPI := platformclientv2.NewUsersApiWithConfig(sdkConfig) + // Attempt to get the user + _, response, err := usersAPI.GetUser(id, nil, "", "") + + // Check if the user is not found (deleted) + if response != nil && response.StatusCode == 404 { + return true, nil // User is deleted + } + + // Handle other errors + if err != nil { + log.Printf("Error fetching user: %v", err) + return false, err + } + + // If user is found, it means the user is not deleted + return false, nil +} + func validateUserSkill(userResourceName string, skillResourceName string, proficiency string) resource.TestCheckFunc { return func(state *terraform.State) error { userResource, ok := state.RootModule().Resources[userResourceName] diff --git a/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group.go b/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group.go index 51b8ee250..72020ec39 100644 --- a/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group.go +++ b/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group.go @@ -104,19 +104,19 @@ func readSkillGroups(ctx context.Context, d *schema.ResourceData, meta interface _ = d.Set("skill_conditions", nil) } - // Set member_divisions avoiding plan not empty error + // Set member_division_ids avoiding plan not empty error memberDivIds, diagErr := readSkillGroupMemberDivisions(ctx, d, meta) if diagErr != nil { return retry.NonRetryableError(fmt.Errorf("%v", diagErr)) } var schemaMemberDivisionIds []string - if divIds, ok := d.Get("member_divisions").([]interface{}); ok { + if divIds, ok := d.Get("member_division_ids").([]interface{}); ok { schemaMemberDivisionIds = lists.InterfaceListToStrings(divIds) } memberDivisionIds := organizeMemberDivisionIdsForRead(schemaMemberDivisionIds, memberDivIds, *skillGroup.Division.Id) - _ = d.Set("member_divisions", memberDivisionIds) + _ = d.Set("member_division_ids", memberDivisionIds) log.Printf("Read skill groups name %s %s", d.Id(), *skillGroup.Name) return cc.CheckState(d) @@ -186,7 +186,7 @@ func deleteSkillGroups(ctx context.Context, d *schema.ResourceData, meta interfa func createRoutingSkillGroupsMemberDivisions(ctx context.Context, d *schema.ResourceData, meta interface{}, skillGroupDivisionIds []string, create bool) diag.Diagnostics { sdkConfig := meta.(*provider.ProviderMeta).ClientConfig proxy := getRoutingSkillGroupsProxy(sdkConfig) - memberDivIds := d.Get("member_divisions").([]interface{}) + memberDivIds := d.Get("member_division_ids").([]interface{}) var reqBody platformclientv2.Skillgroupmemberdivisions if memberDivIds == nil { diff --git a/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_schema.go b/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_schema.go index b139aff79..ab3b7cd0d 100644 --- a/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_schema.go +++ b/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_schema.go @@ -18,7 +18,6 @@ func SetRegistrar(regInstance registrar.Registrar) { regInstance.RegisterExporter(resourceName, ResourceSkillGroupExporter()) } - func ResourceRoutingSkillGroup() *schema.Resource { return &schema.Resource{ Description: `Genesys Cloud Skill Group`, @@ -55,8 +54,8 @@ func ResourceRoutingSkillGroup() *schema.Resource { Computed: true, DiffSuppressFunc: util.SuppressEquivalentJsonDiffs, }, - "member_divisions": { - Description: "Member divisions for this skill group.", + "member_division_ids": { + Description: "The IDs of member divisions to add or remove for this skill group. An empty array means all divisions will be removed, '*' means all divisions will be added.", Type: schema.TypeList, MaxItems: 50, Optional: true, @@ -84,8 +83,8 @@ func ResourceSkillGroupExporter() *resourceExporter.ResourceExporter { return &resourceExporter.ResourceExporter{ GetResourcesFunc: provider.GetAllWithPooledClient(getAllRoutingSkillGroups), RefAttrs: map[string]*resourceExporter.RefAttrSettings{ - "division_id": {RefType: "genesyscloud_auth_division"}, - "member_divisions": {RefType: "genesyscloud_auth_division"}, + "division_id": {RefType: "genesyscloud_auth_division"}, + "member_division_ids": {RefType: "genesyscloud_auth_division"}, }, RemoveIfMissing: map[string][]string{ "division_id": {"division_id"}, diff --git a/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_test.go b/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_test.go index e12cce85d..74f706207 100644 --- a/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_test.go +++ b/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_test.go @@ -311,8 +311,8 @@ data "genesyscloud_auth_division_home" "home" {} testAccCheckSkillConditions("genesyscloud_routing_skill_group."+skillGroupResource, skillCondition1), provider.TestDefaultHomeDivision("genesyscloud_routing_skill_group."+skillGroupResource), - resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions.#", "1"), - util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions", + resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids.#", "1"), + util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids", "data.genesyscloud_auth_division_home.home", "id"), ), }, @@ -324,12 +324,12 @@ data "genesyscloud_auth_division_home" "home" {} testAccCheckSkillConditions("genesyscloud_routing_skill_group."+skillGroupResource, skillCondition2), provider.TestDefaultHomeDivision("genesyscloud_routing_skill_group."+skillGroupResource), - resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions.#", "3"), - util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions", + resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids.#", "3"), + util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids", "data.genesyscloud_auth_division_home.home", "id"), - util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions", + util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids", "genesyscloud_auth_division."+authDivision1Resource, "id"), - util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions", + util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids", "genesyscloud_auth_division."+authDivision2Resource, "id"), ), }, @@ -341,10 +341,10 @@ data "genesyscloud_auth_division_home" "home" {} testAccCheckSkillConditions("genesyscloud_routing_skill_group."+skillGroupResource, skillCondition2), provider.TestDefaultHomeDivision("genesyscloud_routing_skill_group."+skillGroupResource), - resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions.#", "2"), - util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions", + resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids.#", "2"), + util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids", "data.genesyscloud_auth_division_home.home", "id"), - util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions", + util.ValidateResourceAttributeInArray("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids", "genesyscloud_auth_division."+authDivision1Resource, "id"), ), }, @@ -357,7 +357,7 @@ data "genesyscloud_auth_division_home" "home" {} testAccCheckSkillConditions("genesyscloud_routing_skill_group."+skillGroupResource, skillCondition2), provider.TestDefaultHomeDivision("genesyscloud_routing_skill_group."+skillGroupResource), - resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions.#", "0"), + resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids.#", "0"), testVerifyMemberDivisionsCleared("genesyscloud_routing_skill_group."+skillGroupResource), ), }, @@ -370,16 +370,16 @@ data "genesyscloud_auth_division_home" "home" {} testAccCheckSkillConditions("genesyscloud_routing_skill_group."+skillGroupResource, skillCondition2), provider.TestDefaultHomeDivision("genesyscloud_routing_skill_group."+skillGroupResource), - resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions.#", "1"), - resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions.0", "*"), - testVerifyAllDivisionsAssigned("genesyscloud_routing_skill_group."+skillGroupResource, "member_divisions"), + resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids.#", "1"), + resource.TestCheckResourceAttr("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids.0", "*"), + testVerifyAllDivisionsAssigned("genesyscloud_routing_skill_group."+skillGroupResource, "member_division_ids"), ), }, { ResourceName: "genesyscloud_routing_skill_group." + skillGroupResource, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"member_divisions"}, + ImportStateVerifyIgnore: []string{"member_division_ids"}, }, }, CheckDestroy: testVerifySkillGroupDestroyed, @@ -469,7 +469,7 @@ resource "genesyscloud_user" "%s" { skillGroupResource := fmt.Sprintf(` resource "genesyscloud_routing_skill_group" "%s" { name = "%s" - member_divisions = [%s] + member_division_ids = [%s] description = "%s" skill_conditions = jsonencode( [ @@ -520,7 +520,7 @@ resource "genesyscloud_routing_skill_group" "%s" { ResourceName: "genesyscloud_routing_skill_group." + skillGroupResourceId, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"member_divisions"}, + ImportStateVerifyIgnore: []string{"member_division_ids"}, Destroy: true, }, }, @@ -542,7 +542,7 @@ func generateRoutingSkillGroupResource( description="%s" division_id=%s skill_conditions = jsonencode(%s) - member_divisions = %s + member_division_ids = %s } `, resourceID, divisionResourceName, name, description, divisionID, skillCondition, memberDivisionIds) } diff --git a/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_utils.go b/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_utils.go index 396c2b87c..b41412800 100644 --- a/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_utils.go +++ b/genesyscloud/routing_skill_group/resource_genesyscloud_routing_skill_group_utils.go @@ -11,7 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -// Prepare member_divisions list to avoid an unnecessary plan not empty error +// Prepare member_division_ids list to avoid an unnecessary plan not empty error func organizeMemberDivisionIdsForUpdate(schemaIds, apiIds []string) ([]string, []string) { toAdd := make([]string, 0) toRemove := make([]string, 0) @@ -30,7 +30,7 @@ func organizeMemberDivisionIdsForUpdate(schemaIds, apiIds []string) ([]string, [ return toAdd, toRemove } -// Prepare member_divisions list to avoid an unnecessary plan not empty error +// Prepare member_division_ids list to avoid an unnecessary plan not empty error func organizeMemberDivisionIdsForRead(schemaList, apiList []string, divisionId string) []string { if !lists.ItemInSlice(divisionId, schemaList) { apiList = lists.RemoveStringFromSlice(divisionId, apiList) @@ -96,7 +96,7 @@ func createListsForSkillgroupsMembersDivisions(schemaMemberDivisionIds []string, if allMemberDivisionsSpecified(schemaMemberDivisionIds) { if len(schemaMemberDivisionIds) > 1 { - return nil, nil, util.BuildDiagnosticError(resourceName, fmt.Sprintf(`member_divisions should not contain more than one item when the value of an item is "*"`), fmt.Errorf(`member_divisions should not contain more than one item when the value of an item is "*"`)) + return nil, nil, util.BuildDiagnosticError(resourceName, fmt.Sprintf(`member_division_ids should not contain more than one item when the value of an item is "*"`), fmt.Errorf(`member_division_ids should not contain more than one item when the value of an item is "*"`)) } toAdd, err := getAllAuthDivisionIds(meta) return toAdd, nil, err