Skip to content

Commit 18c538d

Browse files
feat(evs/evs_snapshot_metadata): support evs_snapshot_metadata resource (#6895)
1 parent b90ed2c commit 18c538d

File tree

4 files changed

+476
-0
lines changed

4 files changed

+476
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
subcategory: "Elastic Volume Service (EVS)"
3+
layout: "huaweicloud"
4+
page_title: "HuaweiCloud: huaweicloud_evs_snapshot_metadata"
5+
description: |-
6+
Manages an EVS snapshot metadata resource within HuaweiCloud.
7+
---
8+
9+
# huaweicloud_evs_snapshot_metadata
10+
11+
Manages an EVS snapshot metadata resource within HuaweiCloud.
12+
13+
## Example Usage
14+
15+
```hcl
16+
variable "snapshot_id" {}
17+
18+
resource "huaweicloud_evs_snapshot_metadata" "test" {
19+
snapshot_id = var.snapshot_id
20+
21+
metadata = {
22+
foo = "bar"
23+
key = "value"
24+
}
25+
}
26+
```
27+
28+
## Argument Reference
29+
30+
The following arguments are supported:
31+
32+
* `region` - (Optional, String, ForceNew) Specifies the region in which to create the resource.
33+
If omitted, the provider-level region will be used. Changing this parameter will create a new resource.
34+
35+
* `snapshot_id` - (Required, String, NonUpdatable) Specifies the ID of the snapshot.
36+
37+
* `metadata` - (Required, Map) Specifies the user-defined metadata key-value pair.
38+
39+
-> When updating the `metadata` parameter, all existing key-value pairs will be overwritten.
40+
41+
## Attribute Reference
42+
43+
In addition to all arguments above, the following attributes are exported:
44+
45+
* `id` - The resource ID, same as `snapshot_id`.

huaweicloud/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,6 +2009,7 @@ func Provider() *schema.Provider {
20092009

20102010
"huaweicloud_evs_snapshot": evs.ResourceEvsSnapshot(),
20112011
"huaweicloud_evsv3_snapshot": evs.ResourceV3Snapshot(),
2012+
"huaweicloud_evs_snapshot_metadata": evs.ResourceSnapshotMetadata(),
20122013
"huaweicloud_evs_volume": evs.ResourceEvsVolume(),
20132014
"huaweicloud_evs_snapshot_rollback": evs.ResourceSnapshotRollBack(),
20142015
"huaweicloud_evs_volume_transfer": evs.ResourceVolumeTransfer(),
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
package evs
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"strings"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
11+
12+
"github.com/chnsz/golangsdk"
13+
14+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
15+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
16+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils"
17+
)
18+
19+
func getSnapshotMetadataResourceFunc(conf *config.Config, state *terraform.ResourceState) (interface{}, error) {
20+
var (
21+
region = acceptance.HW_REGION_NAME
22+
product = "evs"
23+
metadataResult = make(map[string]interface{})
24+
)
25+
26+
client, err := conf.NewServiceClient(product, region)
27+
if err != nil {
28+
return nil, fmt.Errorf("error creating EVS client: %s", err)
29+
}
30+
31+
requestPath := client.Endpoint + "v3/{project_id}/snapshots/{snapshot_id}/metadata"
32+
requestPath = strings.ReplaceAll(requestPath, "{project_id}", client.ProjectID)
33+
requestPath = strings.ReplaceAll(requestPath, "{snapshot_id}", state.Primary.ID)
34+
requestOpt := golangsdk.RequestOpts{
35+
KeepResponseBody: true,
36+
}
37+
38+
metadataMap := make(map[string]string)
39+
for k, v := range state.Primary.Attributes {
40+
if strings.HasPrefix(k, "metadata.") && k != "metadata.%" {
41+
key := strings.TrimPrefix(k, "metadata.")
42+
metadataMap[key] = v
43+
}
44+
}
45+
46+
for key := range metadataMap {
47+
getPath := fmt.Sprintf("%s/%s", requestPath, key)
48+
getResp, err := client.Request("GET", getPath, &requestOpt)
49+
if err != nil {
50+
var errDefault404 golangsdk.ErrDefault404
51+
if errors.As(err, &errDefault404) {
52+
continue
53+
}
54+
55+
return nil, fmt.Errorf("error retrieving EVS snapshot metadata: %s", err)
56+
}
57+
58+
respBody, err := utils.FlattenResponse(getResp)
59+
if err != nil {
60+
return nil, err
61+
}
62+
63+
metaResp := utils.PathSearch("meta", respBody, make(map[string]interface{})).(map[string]interface{})
64+
for k, v := range metaResp {
65+
metadataResult[k] = v
66+
}
67+
}
68+
69+
// Only when all key queries in `metadata` return `404`, it is considered that the resource does not exist.
70+
if len(metadataMap) > 0 && len(metadataResult) == 0 {
71+
return nil, golangsdk.ErrDefault404{}
72+
}
73+
74+
return metadataResult, nil
75+
}
76+
77+
func TestAccSnapshotMetadata_basic(t *testing.T) {
78+
var (
79+
snapshotMetadata interface{}
80+
rName = acceptance.RandomAccResourceName()
81+
resourceName = "huaweicloud_evs_snapshot_metadata.test"
82+
)
83+
84+
rc := acceptance.InitResourceCheck(
85+
resourceName,
86+
&snapshotMetadata,
87+
getSnapshotMetadataResourceFunc,
88+
)
89+
90+
resource.ParallelTest(t, resource.TestCase{
91+
PreCheck: func() {
92+
acceptance.TestAccPreCheck(t)
93+
},
94+
ProviderFactories: acceptance.TestAccProviderFactories,
95+
CheckDestroy: rc.CheckResourceDestroy(),
96+
Steps: []resource.TestStep{
97+
{
98+
Config: testAccSnapshotMetadata_basic(rName),
99+
Check: resource.ComposeTestCheckFunc(
100+
rc.CheckResourceExists(),
101+
resource.TestCheckResourceAttr(resourceName, "metadata.foo", "bar"),
102+
resource.TestCheckResourceAttr(resourceName, "metadata.key", "value"),
103+
resource.TestCheckResourceAttrPair(resourceName, "snapshot_id", "huaweicloud_evsv3_snapshot.test", "id"),
104+
),
105+
},
106+
{
107+
Config: testAccSnapshotMetadata_update1(rName),
108+
Check: resource.ComposeTestCheckFunc(
109+
rc.CheckResourceExists(),
110+
resource.TestCheckResourceAttr(resourceName, "metadata.foo", "bar_update"),
111+
resource.TestCheckResourceAttr(resourceName, "metadata.key", "value_update"),
112+
resource.TestCheckResourceAttr(resourceName, "metadata.test_key", "test_value"),
113+
),
114+
},
115+
{
116+
Config: testAccSnapshotMetadata_update2(rName),
117+
Check: resource.ComposeTestCheckFunc(
118+
rc.CheckResourceExists(),
119+
resource.TestCheckResourceAttr(resourceName, "metadata.#", "0"),
120+
),
121+
},
122+
{
123+
Config: testAccSnapshotMetadata_update3(rName),
124+
Check: resource.ComposeTestCheckFunc(
125+
rc.CheckResourceExists(),
126+
resource.TestCheckResourceAttr(resourceName, "metadata.foo", "bar"),
127+
),
128+
},
129+
},
130+
})
131+
}
132+
133+
func testAccSnapshotMetadata_base(rName string) string {
134+
return fmt.Sprintf(`
135+
data "huaweicloud_availability_zones" "test" {}
136+
137+
resource "huaweicloud_evs_volume" "test" {
138+
name = "%[1]s"
139+
availability_zone = data.huaweicloud_availability_zones.test.names[0]
140+
volume_type = "SAS"
141+
size = 12
142+
}
143+
144+
resource "huaweicloud_evsv3_snapshot" "test" {
145+
volume_id = huaweicloud_evs_volume.test.id
146+
name = "%[1]s"
147+
}
148+
`, rName)
149+
}
150+
151+
func testAccSnapshotMetadata_basic(rName string) string {
152+
return fmt.Sprintf(`
153+
%[1]s
154+
155+
resource "huaweicloud_evs_snapshot_metadata" "test" {
156+
snapshot_id = huaweicloud_evsv3_snapshot.test.id
157+
158+
metadata = {
159+
foo = "bar"
160+
key = "value"
161+
}
162+
}
163+
`, testAccSnapshotMetadata_base(rName))
164+
}
165+
166+
func testAccSnapshotMetadata_update1(rName string) string {
167+
return fmt.Sprintf(`
168+
%[1]s
169+
170+
resource "huaweicloud_evs_snapshot_metadata" "test" {
171+
snapshot_id = huaweicloud_evsv3_snapshot.test.id
172+
173+
metadata = {
174+
foo = "bar_update"
175+
test_key = "test_value"
176+
key = "value_update"
177+
}
178+
}
179+
`, testAccSnapshotMetadata_base(rName))
180+
}
181+
182+
func testAccSnapshotMetadata_update2(rName string) string {
183+
return fmt.Sprintf(`
184+
%[1]s
185+
186+
resource "huaweicloud_evs_snapshot_metadata" "test" {
187+
snapshot_id = huaweicloud_evsv3_snapshot.test.id
188+
189+
metadata = {}
190+
}
191+
`, testAccSnapshotMetadata_base(rName))
192+
}
193+
194+
func testAccSnapshotMetadata_update3(rName string) string {
195+
return fmt.Sprintf(`
196+
%[1]s
197+
198+
resource "huaweicloud_evs_snapshot_metadata" "test" {
199+
snapshot_id = huaweicloud_evsv3_snapshot.test.id
200+
201+
metadata = {
202+
foo = "bar"
203+
}
204+
}
205+
`, testAccSnapshotMetadata_base(rName))
206+
}

0 commit comments

Comments
 (0)