From 1ee94718e3e0883f30263b388fc7a39663aa97da Mon Sep 17 00:00:00 2001 From: luoping-12345 Date: Thu, 26 Dec 2024 14:56:01 +0800 Subject: [PATCH] feat(identitycenter): support permission set tags --- .../identitycenter_permission_set.md | 2 + ...loud_identitycenter_permission_set_test.go | 13 +- ...aweicloud_identitycenter_permission_set.go | 124 ++++++++++++++++-- 3 files changed, 127 insertions(+), 12 deletions(-) diff --git a/docs/resources/identitycenter_permission_set.md b/docs/resources/identitycenter_permission_set.md index 2b0b50761f..468af86682 100644 --- a/docs/resources/identitycenter_permission_set.md +++ b/docs/resources/identitycenter_permission_set.md @@ -51,6 +51,8 @@ In addition to all arguments above, the following attributes are exported: * `account_ids` - The array of one or more account IDs bound to the permission set. +* `tags` - (Optional, Map) Specifies the key/value pairs to associate with the permission set. + ## Import The Identity Center permission set can be imported using the `instance_id` and `id` separated by a slash, e.g. diff --git a/huaweicloud/services/acceptance/identitycenter/resource_huaweicloud_identitycenter_permission_set_test.go b/huaweicloud/services/acceptance/identitycenter/resource_huaweicloud_identitycenter_permission_set_test.go index d944a67d86..dd086e3e23 100644 --- a/huaweicloud/services/acceptance/identitycenter/resource_huaweicloud_identitycenter_permission_set_test.go +++ b/huaweicloud/services/acceptance/identitycenter/resource_huaweicloud_identitycenter_permission_set_test.go @@ -68,8 +68,8 @@ func TestAccPermissionSet_basic(t *testing.T) { resource.TestCheckResourceAttr(rName, "description", "created by terraform"), resource.TestCheckResourceAttrSet(rName, "urn"), resource.TestCheckResourceAttrSet(rName, "created_at"), - resource.TestCheckResourceAttrPair(rName, "instance_id", - "data.huaweicloud_identitycenter_instance.system", "id"), + resource.TestCheckResourceAttrPair(rName, "instance_id", "data.huaweicloud_identitycenter_instance.system", "id"), + resource.TestCheckResourceAttr(rName, "tags.foo", "bar"), ), }, { @@ -78,6 +78,7 @@ func TestAccPermissionSet_basic(t *testing.T) { resource.TestCheckResourceAttr(rName, "name", name), resource.TestCheckResourceAttr(rName, "session_duration", "PT4H"), resource.TestCheckResourceAttr(rName, "description", "updated by terraform"), + resource.TestCheckResourceAttr(rName, "tags.foo", "bar_update"), ), }, { @@ -123,6 +124,10 @@ resource "huaweicloud_identitycenter_permission_set" "test" { name = "%s" session_duration = "PT8H" description = "created by terraform" + + tags = { + foo = "bar" + } } `, name) } @@ -148,6 +153,10 @@ resource "huaweicloud_identitycenter_permission_set" "test" { instance_id = data.huaweicloud_identitycenter_instance.system.id name = "%s" session_duration = "PT4H" + + tags = { + foo = "bar_update" + } } `, name) } diff --git a/huaweicloud/services/identitycenter/resource_huaweicloud_identitycenter_permission_set.go b/huaweicloud/services/identitycenter/resource_huaweicloud_identitycenter_permission_set.go index f255318ca6..2588966299 100644 --- a/huaweicloud/services/identitycenter/resource_huaweicloud_identitycenter_permission_set.go +++ b/huaweicloud/services/identitycenter/resource_huaweicloud_identitycenter_permission_set.go @@ -26,6 +26,9 @@ import ( // @API IdentityCenter DELETE /v1/instances/{instance_id}/permission-sets/{id} // @API IdentityCenter GET /v1/instances/{instance_id}/permission-sets/{id} // @API IdentityCenter PUT /v1/instances/{instance_id}/permission-sets/{id} +// @API IdentityCenter POST /v1/instances/{resource_type}/{resource_id}/tags/create +// @API IdentityCenter POST /v1/instances/{resource_type}/{resource_id}/tags/delete +// @API IdentityCenter GET /v1/instances/{resource_type}/{resource_id}/tags func ResourcePermissionSet() *schema.Resource { return &schema.Resource{ CreateContext: resourcePermissionSetCreate, @@ -62,6 +65,7 @@ func ResourcePermissionSet() *schema.Resource { Optional: true, Computed: true, }, + "tags": common.TagsSchema(), "urn": { Type: schema.TypeString, Computed: true, @@ -115,6 +119,13 @@ func resourcePermissionSetCreate(ctx context.Context, d *schema.ResourceData, me } d.SetId(permissionSetId) + + if _, ok := d.GetOk("tags"); ok { + if err := updateTags(createPermissionSetClient, d, "identitycenter:permissionset", d.Id()); err != nil { + return diag.Errorf("error creating tags of Identity Center permission set %s: %s", d.Id(), err) + } + } + return resourcePermissionSetRead(ctx, d, meta) } @@ -176,6 +187,16 @@ func resourcePermissionSetRead(_ context.Context, d *schema.ResourceData, meta i d.Set("account_ids", accountIDs), ) + tags, err := getPermissionSetTags(getPermissionSetClient, d.Id()) + if err != nil { + log.Printf("[WARN] error fetching tags of permission set: %s", err) + } + + mErr = multierror.Append( + mErr, + d.Set("tags", tags), + ) + return diag.FromErr(mErr.ErrorOrNil()) } @@ -205,6 +226,10 @@ func getAssignededAccounts(client *golangsdk.ServiceClient, instanceID, psID str func resourcePermissionSetUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { cfg := meta.(*config.Config) region := cfg.GetRegion(d) + client, err := cfg.NewServiceClient("identitycenter", region) + if err != nil { + return diag.Errorf("error creating Identity Center client: %s", err) + } updatePermissionSetChanges := []string{ "session_duration", @@ -213,16 +238,9 @@ func resourcePermissionSetUpdate(ctx context.Context, d *schema.ResourceData, me } if d.HasChanges(updatePermissionSetChanges...) { - var ( - updatePermissionSetHttpUrl = "v1/instances/{instance_id}/permission-sets/{id}" - updatePermissionSetProduct = "identitycenter" - ) - updatePermissionSetClient, err := cfg.NewServiceClient(updatePermissionSetProduct, region) - if err != nil { - return diag.Errorf("error creating Identity Center client: %s", err) - } + updatePermissionSetHttpUrl := "v1/instances/{instance_id}/permission-sets/{id}" - updatePermissionSetPath := updatePermissionSetClient.Endpoint + updatePermissionSetHttpUrl + updatePermissionSetPath := client.Endpoint + updatePermissionSetHttpUrl updatePermissionSetPath = strings.ReplaceAll(updatePermissionSetPath, "{instance_id}", d.Get("instance_id").(string)) updatePermissionSetPath = strings.ReplaceAll(updatePermissionSetPath, "{id}", d.Id()) @@ -230,12 +248,18 @@ func resourcePermissionSetUpdate(ctx context.Context, d *schema.ResourceData, me KeepResponseBody: true, } updatePermissionSetOpt.JSONBody = utils.RemoveNil(buildUpdatePermissionSetBodyParams(d)) - _, err = updatePermissionSetClient.Request("PUT", updatePermissionSetPath, &updatePermissionSetOpt) + _, err = client.Request("PUT", updatePermissionSetPath, &updatePermissionSetOpt) if err != nil { return diag.Errorf("error updating permission set: %s", err) } } + if d.HasChange("tags") { + if err := updateTags(client, d, "identitycenter:permissionset", d.Id()); err != nil { + return diag.Errorf("error updating tags of Identitycenter permission set %s: %s", d.Id(), err) + } + } + return resourcePermissionSetRead(ctx, d, meta) } @@ -295,3 +319,83 @@ func resourcePermissionSetImport(_ context.Context, d *schema.ResourceData, _ in return []*schema.ResourceData{d}, nil } + +func updateTags(client *golangsdk.ServiceClient, d *schema.ResourceData, tagsType string, id string) error { + oRaw, nRaw := d.GetChange("tags") + oMap := oRaw.(map[string]interface{}) + nMap := nRaw.(map[string]interface{}) + + manageTagsHttpUrl := "v1/instances/{resource_type}/{resource_id}/tags/{action}" + manageTagsPath := client.Endpoint + manageTagsHttpUrl + manageTagsPath = strings.ReplaceAll(manageTagsPath, "{resource_type}", tagsType) + manageTagsPath = strings.ReplaceAll(manageTagsPath, "{resource_id}", id) + manageTagsOpt := golangsdk.RequestOpts{ + KeepResponseBody: true, + } + + // remove old tags + if len(oMap) > 0 { + manageDeleteTagsPath := strings.ReplaceAll(manageTagsPath, "{action}", "delete") + manageTagsOpt.JSONBody = map[string]interface{}{ + "tags": utils.ExpandResourceTags(oMap), + } + _, err := client.Request("POST", manageDeleteTagsPath, &manageTagsOpt) + if err != nil { + return err + } + } + + // set new tags + if len(nMap) > 0 { + manageCreateTagsPath := strings.ReplaceAll(manageTagsPath, "{action}", "create") + manageTagsOpt.JSONBody = map[string]interface{}{ + "tags": utils.ExpandResourceTags(nMap), + } + _, err := client.Request("POST", manageCreateTagsPath, &manageTagsOpt) + if err != nil { + return err + } + } + + return nil +} + +func getPermissionSetTags(client *golangsdk.ServiceClient, id string) (interface{}, error) { + getPermissionSetTagsHttpUrl := "v1/instances/{resource_type}/{resource_id}/tags?limit=10" + getPermissionSetTagsPath := client.Endpoint + getPermissionSetTagsHttpUrl + getPermissionSetTagsPath = strings.ReplaceAll(getPermissionSetTagsPath, "{resource_type}", "identitycenter:permissionset") + getPermissionSetTagsPath = strings.ReplaceAll(getPermissionSetTagsPath, "{resource_id}", id) + + getPermissionSetTagsOpt := golangsdk.RequestOpts{ + KeepResponseBody: true, + } + + path := getPermissionSetTagsPath + var permissionSetTags []interface{} + for { + getPermissionSetTagsResp, err := client.Request("GET", path, &getPermissionSetTagsOpt) + if err != nil { + return nil, err + } + getPermissionSetTagsRespBody, err := utils.FlattenResponse(getPermissionSetTagsResp) + if err != nil { + return nil, err + } + tags := utils.PathSearch("tags", getPermissionSetTagsRespBody, make([]interface{}, 0)).([]interface{}) + permissionSetTags = append(permissionSetTags, tags...) + + marker := utils.PathSearch("page_info.next_marker", getPermissionSetTagsRespBody, nil) + if marker == nil { + break + } + path = fmt.Sprintf("%s&marker=%s", getPermissionSetTagsPath, marker) + } + + result := make(map[string]interface{}) + for _, val := range permissionSetTags { + valMap := val.(map[string]interface{}) + result[valMap["key"].(string)] = valMap["value"] + } + + return result, nil +}