Skip to content

Commit 638cfa8

Browse files
committed
feat(cts): add new data source to query resource tags
1 parent 28636b1 commit 638cfa8

File tree

4 files changed

+270
-0
lines changed

4 files changed

+270
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
subcategory: "Cloud Trace Service (CTS)"
3+
layout: "huaweicloud"
4+
page_title: "HuaweiCloud: huaweicloud_cts_resource_tags"
5+
description: |-
6+
Use this data source to get resource tag list of CTS within HuaweiCloud.
7+
---
8+
9+
# huaweicloud_cts_resource_tags
10+
11+
Use this data source to get resource tag list of CTS within HuaweiCloud.
12+
13+
## Example Usage
14+
15+
```hcl
16+
resource "huaweicloud_obs_bucket" "test" {
17+
bucket = "tf-test-bucket"
18+
acl = "private"
19+
}
20+
21+
resource "huaweicloud_cts_tracker" "test" {
22+
bucket_name = huaweicloud_obs_bucket.test.bucket
23+
file_prefix = "cts"
24+
25+
tags = {
26+
foo1 = "bar1",
27+
foo2 = "bar2"
28+
}
29+
}
30+
31+
data "huaweicloud_cts_resource_tags" "test" {
32+
resource_id = huaweicloud_cts_tracker.test.id
33+
}
34+
```
35+
36+
## Argument Reference
37+
38+
The following arguments are supported:
39+
40+
* `region` - (Optional, String) Specifies the region in which to query the data source.
41+
If omitted, the provider-level region will be used.
42+
43+
* `resource_id` - (Required, String) Specifies the resource ID.
44+
45+
* `resource_type` - (Required, String) Specifies the resource type. The valid value is **cts-tracker**.
46+
47+
## Attribute Reference
48+
49+
In addition to all arguments above, the following attributes are exported:
50+
51+
* `id` - The resource ID.
52+
53+
* `tags` - The list of tags.
54+
The [tags](#cts_resource_tags_attr) structure is documented below.
55+
56+
<a name="cts_resource_tags_attr"></a>
57+
The `tags` block supports:
58+
59+
* `key` - The tag key.
60+
61+
* `value` - The tag value.

huaweicloud/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ func Provider() *schema.Provider {
768768
"huaweicloud_cts_operations": cts.DataSourceCtsOperations(),
769769
"huaweicloud_cts_quotas": cts.DataSourceCtsQuotas(),
770770
"huaweicloud_cts_resources": cts.DataSourceCtsResources(),
771+
"huaweicloud_cts_resource_tags": cts.DataSourceCtsResourcesTags(),
771772
"huaweicloud_cts_tags": cts.DataSourceCtsTags(),
772773
"huaweicloud_cts_users": cts.DataSourceCtsUsers(),
773774

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package cts
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
9+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
10+
)
11+
12+
func TestAccDataSourceResourceTags_basic(t *testing.T) {
13+
dataSourceName := "data.huaweicloud_cts_resource_tags.test"
14+
dc := acceptance.InitDataSourceCheck(dataSourceName)
15+
16+
resource.ParallelTest(t, resource.TestCase{
17+
PreCheck: func() {
18+
acceptance.TestAccPreCheck(t)
19+
},
20+
ProviderFactories: acceptance.TestAccProviderFactories,
21+
Steps: []resource.TestStep{
22+
{
23+
Config: testAccDataSourceResourceTags_basic(),
24+
Check: resource.ComposeTestCheckFunc(
25+
dc.CheckResourceExists(),
26+
resource.TestCheckResourceAttrSet(dataSourceName, "region"),
27+
resource.TestCheckResourceAttrSet(dataSourceName, "tags.#"),
28+
resource.TestCheckOutput("is_tags_exist", "true"),
29+
resource.TestCheckOutput("is_key_set", "true"),
30+
resource.TestCheckOutput("is_values_set", "true"),
31+
),
32+
},
33+
},
34+
})
35+
}
36+
37+
func testAccDataSourceResourceTags_base() string {
38+
return `
39+
resource "huaweicloud_obs_bucket" "test" {
40+
bucket = "tf-test-bucket"
41+
acl = "private"
42+
force_destroy = true
43+
44+
tags = {
45+
foo = "bar"
46+
}
47+
}
48+
49+
resource "huaweicloud_cts_tracker" "test" {
50+
bucket_name = huaweicloud_obs_bucket.test.bucket
51+
file_prefix = "cts"
52+
53+
tags = {
54+
foo1 = "bar1",
55+
foo2 = "bar2"
56+
}
57+
}
58+
`
59+
}
60+
func testAccDataSourceResourceTags_basic() string {
61+
return fmt.Sprintf(`
62+
%s
63+
64+
data "huaweicloud_cts_resource_tags" "test" {
65+
resource_id = huaweicloud_cts_tracker.test.id
66+
resource_type = "cts-tracker"
67+
}
68+
69+
locals {
70+
tags = data.huaweicloud_cts_resource_tags.test.tags
71+
}
72+
73+
output "is_tags_exist" {
74+
value = length(local.tags) > 0
75+
}
76+
77+
output "is_key_set" {
78+
value = alltrue([for v in local.tags[*].key : v != ""])
79+
}
80+
81+
output "is_values_set" {
82+
value = alltrue([for v in local.tags[*].value : v != ""])
83+
}
84+
`, testAccDataSourceResourceTags_base())
85+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package cts
2+
3+
import (
4+
"context"
5+
"strings"
6+
7+
"github.com/hashicorp/go-multierror"
8+
"github.com/hashicorp/go-uuid"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
12+
"github.com/chnsz/golangsdk"
13+
14+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
15+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils"
16+
)
17+
18+
// @API CTS GET /v3/{project_id}/{resource_type}/{resource_id}/tags
19+
func DataSourceCtsResourcesTags() *schema.Resource {
20+
return &schema.Resource{
21+
ReadContext: dataSourceCtsResourcesTagsRead,
22+
23+
Schema: map[string]*schema.Schema{
24+
"region": {
25+
Type: schema.TypeString,
26+
Optional: true,
27+
Computed: true,
28+
Description: `The region in which to query the resource tags.`,
29+
},
30+
"resource_type": {
31+
Type: schema.TypeString,
32+
Required: true,
33+
Description: `The type of resource.`,
34+
},
35+
"resource_id": {
36+
Type: schema.TypeString,
37+
Required: true,
38+
Description: `The ID of resource.`,
39+
},
40+
"tags": {
41+
Type: schema.TypeList,
42+
Computed: true,
43+
Description: `The list of resource tags.`,
44+
Elem: &schema.Resource{
45+
Schema: map[string]*schema.Schema{
46+
"key": {
47+
Type: schema.TypeString,
48+
Computed: true,
49+
Description: `The tag key.`,
50+
},
51+
"value": {
52+
Type: schema.TypeString,
53+
Computed: true,
54+
Description: `The tag value.`,
55+
},
56+
},
57+
},
58+
},
59+
},
60+
}
61+
}
62+
63+
func dataSourceCtsResourcesTagsRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
64+
cfg := meta.(*config.Config)
65+
region := cfg.GetRegion(d)
66+
client, err := cfg.NewServiceClient("cts", region)
67+
if err != nil {
68+
return diag.Errorf("error creating CTS client: %s", err)
69+
}
70+
71+
resourceId := d.Get("resource_id").(string)
72+
httpUrl := "v3/{project_id}/{resource_type}/{resource_id}/tags"
73+
path := client.Endpoint + httpUrl
74+
path = strings.ReplaceAll(path, "{project_id}", client.ProjectID)
75+
path = strings.ReplaceAll(path, "{resource_type}", d.Get("resource_type").(string))
76+
path = strings.ReplaceAll(path, "{resource_id}", resourceId)
77+
78+
requestOpt := golangsdk.RequestOpts{
79+
KeepResponseBody: true,
80+
MoreHeaders: map[string]string{
81+
"Content-Type": "application/json",
82+
},
83+
}
84+
85+
response, err := client.Request("GET", path, &requestOpt)
86+
if err != nil {
87+
return diag.Errorf("error retrieving CTS resource tags: %s", err)
88+
}
89+
90+
respBody, err := utils.FlattenResponse(response)
91+
if err != nil {
92+
return diag.FromErr(err)
93+
}
94+
95+
randUUID, err := uuid.GenerateUUID()
96+
if err != nil {
97+
return diag.Errorf("unable to generate ID: %s", err)
98+
}
99+
d.SetId(randUUID)
100+
101+
mErr := multierror.Append(nil,
102+
d.Set("region", region),
103+
d.Set("tags", flattenResourceTags(utils.PathSearch("tags", respBody, make([]interface{}, 0)).([]interface{}))),
104+
)
105+
106+
return diag.FromErr(mErr.ErrorOrNil())
107+
}
108+
109+
func flattenResourceTags(tags []interface{}) []interface{} {
110+
if len(tags) == 0 {
111+
return nil
112+
}
113+
114+
result := make([]interface{}, 0, len(tags))
115+
for _, tag := range tags {
116+
result = append(result, map[string]interface{}{
117+
"key": utils.PathSearch("key", tag, nil),
118+
"value": utils.PathSearch("value", tag, nil),
119+
})
120+
}
121+
122+
return result
123+
}

0 commit comments

Comments
 (0)