Skip to content

Commit

Permalink
feat(rms): add data source to get the list of RMS resource tags (#5989)
Browse files Browse the repository at this point in the history
  • Loading branch information
profoundwu authored Dec 13, 2024
1 parent 2717bee commit 7bcd69c
Show file tree
Hide file tree
Showing 4 changed files with 316 additions and 0 deletions.
50 changes: 50 additions & 0 deletions docs/data-sources/rms_resource_tags.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
subcategory: "Config"
layout: "huaweicloud"
page_title: "HuaweiCloud: huaweicloud_rms_resource_tags"
description: |-
Use this data source to get the list of RMS resource tags.
---

# huaweicloud_rms_resource_tags

Use this data source to get the list of RMS resource tags.

## Example Usage

```hcl
variable "resource_type" {}
data "huaweicloud_rms_resource_tags" "test" {
resource_type = var.resource_type
}
```

## Argument Reference

The following arguments are supported:

* `region` - (Optional, String) Specifies the region in which to query the resource.
If omitted, the provider-level region will be used.

* `resource_type` - (Required, String) Specifies the resource type.
The valid value can be **config:policyAssignments**.

* `resource_id` - (Optional, String) Specifies the resource ID.

## Attribute Reference

In addition to all arguments above, the following attributes are exported:

* `id` - The data source ID.

* `tags` - The tags.

The [tags](#tags_struct) structure is documented below.

<a name="tags_struct"></a>
The `tags` block supports:

* `key` - The tag key.

* `values` - The tag values.
1 change: 1 addition & 0 deletions huaweicloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,7 @@ func Provider() *schema.Provider {
"huaweicloud_rms_resource_histories": rms.DataSourceRmsHistories(),
"huaweicloud_rms_resource_relations_details": rms.DataSourceRmsRelationsDetails(),
"huaweicloud_rms_remediation_execution_statuses": rms.DataSourceRemediationExecutionStatuses(),
"huaweicloud_rms_resource_tags": rms.DataSourceResourceTags(),

"huaweicloud_sdrs_domain": sdrs.DataSourceSDRSDomain(),

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package rms

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"

"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
)

func TestAccDataSourceResourceTags_basic(t *testing.T) {
dataSource := "data.huaweicloud_rms_resource_tags.test"
dc := acceptance.InitDataSourceCheck(dataSource)
name := acceptance.RandomAccResourceName()
baseConfig := testDataSourceResourceTags_base(name)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acceptance.TestAccPreCheck(t)
},
ProviderFactories: acceptance.TestAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testDataSourceResourceTags_basic(baseConfig),
Check: resource.ComposeTestCheckFunc(
dc.CheckResourceExists(),
resource.TestCheckResourceAttrSet(dataSource, "tags.0.key"),
resource.TestCheckResourceAttrSet(dataSource, "tags.0.values.#"),
),
},
{
Config: testDataSourceResourceTags_specifiedResource(baseConfig),
Check: resource.ComposeTestCheckFunc(
dc.CheckResourceExists(),
resource.TestCheckResourceAttrSet(dataSource, "tags.0.key"),
resource.TestCheckResourceAttrSet(dataSource, "tags.0.values.#"),
),
},
},
})
}

func testDataSourceResourceTags_basic(baseConfig string) string {
return fmt.Sprintf(`
%[1]s
data "huaweicloud_rms_resource_tags" "test" {
resource_type = "config:policyAssignments"
depends_on = [huaweicloud_rms_policy_assignment.test]
}
`, baseConfig)
}

func testDataSourceResourceTags_specifiedResource(baseConfig string) string {
return fmt.Sprintf(`
%[1]s
data "huaweicloud_rms_resource_tags" "test" {
resource_type = "config:policyAssignments"
resource_id = huaweicloud_rms_policy_assignment.test.id
}
`, baseConfig)
}

func testDataSourceResourceTags_base(name string) string {
return fmt.Sprintf(`
data "huaweicloud_rms_policy_definitions" "test" {
name = "regular-matching-of-names"
}
resource "huaweicloud_rms_policy_assignment" "test" {
name = "%[1]s"
description = "A resource name that does not match the regular expression is considered 'non-compliant'."
policy_definition_id = try(data.huaweicloud_rms_policy_definitions.test.definitions[0].id, "")
status = "Disabled"
policy_filter {
region = "%[2]s"
resource_provider = "vpc"
resource_type = "vpcs"
tag_key = "name"
tag_value = "bo"
}
parameters = {
regularExpression = jsonencode("bo-form_")
}
tags = {
foo = "bar"
}
}
`, name, acceptance.HW_REGION_NAME)
}
169 changes: 169 additions & 0 deletions huaweicloud/services/rms/data_source_huaweicloud_rms_resource_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package rms

import (
"context"
"strings"

"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/tidwall/gjson"

"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/helper/httphelper"
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/helper/schemas"
)

func DataSourceResourceTags() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceResourceTagsRead,

Schema: map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: `Specifies the region in which to query the resource. If omitted, the provider-level region will be used.`,
},
"resource_type": {
Type: schema.TypeString,
Required: true,
Description: `Specifies the resource type.`,
},
"resource_id": {
Type: schema.TypeString,
Optional: true,
Description: `Specifies the resource ID.`,
},
"tags": {
Type: schema.TypeList,
Computed: true,
Description: `The tags.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Computed: true,
Description: `The tag key.`,
},
"values": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Description: `The tag values.`,
},
},
},
},
},
}
}

type TagsDSWrapper struct {
*schemas.ResourceDataWrapper
Config *config.Config
}

func newTagsDSWrapper(d *schema.ResourceData, meta interface{}) *TagsDSWrapper {
return &TagsDSWrapper{
ResourceDataWrapper: schemas.NewSchemaWrapper(d),
Config: meta.(*config.Config),
}
}

func dataSourceResourceTagsRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
wrapper := newTagsDSWrapper(d, meta)
if _, ok := d.GetOk("resource_id"); ok {
lisTagForResRst, err := wrapper.ListTagsForResource()
if err != nil {
return diag.FromErr(err)
}

err = wrapper.listTagsToSchema(lisTagForResRst, true)
if err != nil {
return diag.FromErr(err)
}
} else {
lisTagForResTypRst, err := wrapper.ListTagsForResourceType()
if err != nil {
return diag.FromErr(err)
}

err = wrapper.listTagsToSchema(lisTagForResTypRst, false)
if err != nil {
return diag.FromErr(err)
}
}

id, err := uuid.GenerateUUID()
if err != nil {
return diag.FromErr(err)
}
d.SetId(id)

return nil
}

// @API CONFIG GET /v1/resource-manager/{resource_type}/{resource_id}/tags
func (w *TagsDSWrapper) ListTagsForResource() (*gjson.Result, error) {
client, err := w.NewClient(w.Config, "rms")
if err != nil {
return nil, err
}

uri := "/v1/resource-manager/{resource_type}/{resource_id}/tags"
uri = strings.ReplaceAll(uri, "{resource_type}", w.Get("resource_type").(string))
uri = strings.ReplaceAll(uri, "{resource_id}", w.Get("resource_id").(string))
return httphelper.New(client).
Method("GET").
URI(uri).
Request().
Result()
}

// @API CONFIG GET /v1/resource-manager/{resource_type}/tags
func (w *TagsDSWrapper) ListTagsForResourceType() (*gjson.Result, error) {
client, err := w.NewClient(w.Config, "rms")
if err != nil {
return nil, err
}

uri := "/v1/resource-manager/{resource_type}/tags"
uri = strings.ReplaceAll(uri, "{resource_type}", w.Get("resource_type").(string))
return httphelper.New(client).
Method("GET").
URI(uri).
OffsetPager("tags", "offset", "limit", 1000).
Request().
Result()
}

func (w *TagsDSWrapper) listTagsToSchema(body *gjson.Result, specifiedResourceId bool) error {
d := w.ResourceData
parseTagsFunc := parseResourceTypeTags
if specifiedResourceId {
parseTagsFunc = parseResourceTags
}
mErr := multierror.Append(nil,
d.Set("region", w.Config.GetRegion(w.ResourceData)),
d.Set("tags", schemas.SliceToList(body.Get("tags"), parseTagsFunc)),
)

return mErr.ErrorOrNil()
}

func parseResourceTags(tags gjson.Result) any {
rawTag := tags.Get("value").Value().(string)
return map[string]any{
"key": tags.Get("key").Value(),
"values": []string{rawTag},
}
}

func parseResourceTypeTags(tags gjson.Result) any {
return map[string]any{
"key": tags.Get("key").Value(),
"values": schemas.SliceToStrList(tags.Get("values")),
}
}

0 comments on commit 7bcd69c

Please sign in to comment.