Skip to content

Commit acaa3a9

Browse files
committed
feat(servicestage/config_group): add new resource supports config group
1 parent 4ed097d commit acaa3a9

File tree

4 files changed

+316
-0
lines changed

4 files changed

+316
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
subcategory: "ServiceStage"
3+
layout: "huaweicloud"
4+
page_title: "HuaweiCloud: huaweicloud_servicestagev3_config_group"
5+
description: |-
6+
Manages a configuration group resource within HuaweiCloud.
7+
---
8+
9+
# huaweicloud_servicestagev3_config_group
10+
11+
Manages a configuration group resource within HuaweiCloud.
12+
13+
## Example Usage
14+
15+
```hcl
16+
variables "config_group_name" {}
17+
18+
resource "huaweicloud_servicestagev3_config_group" "test" {
19+
name = var.config_group_name
20+
}
21+
```
22+
23+
## Argument Reference
24+
25+
The following arguments are supported:
26+
27+
* `region` - (Optional, String, ForceNew) Specifies the region in which to create the resource.
28+
If omitted, the provider-level region will be used.
29+
Changing this creates a new resource.
30+
31+
* `name` - (Required, String, NonUpdatable) Specifies the name of the configuration group.
32+
The valid length is limited from `2` to `64`, only letters, digits, hyphens (-) and underscores (_) are allowed.
33+
The name must start with a letter and end with a letter or a digit.
34+
35+
* `description` - (Optional, String, NonUpdatable) Specifies the description of the configuration group.
36+
The maximum length is `256` characters.
37+
38+
## Attribute Reference
39+
40+
In addition to all arguments above, the following attributes are exported:
41+
42+
* `id` - The resource ID. also configuration group ID.
43+
44+
* `creator` - The creator of the configuration group.
45+
46+
* `create_time` - The creation time of the configuration group, in milliseconds.
47+
48+
## Import
49+
50+
The resource can be imported using `id`, e.g.
51+
52+
```bash
53+
$ terraform import huaweicloud_servicestagev3_config_group.test <id>
54+
```

huaweicloud/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -2285,6 +2285,7 @@ func Provider() *schema.Provider {
22852285
// v3 managements
22862286
"huaweicloud_servicestagev3_application": servicestage.ResourceV3Application(),
22872287
"huaweicloud_servicestagev3_component": servicestage.ResourceV3Component(),
2288+
"huaweicloud_servicestagev3_config_group": servicestage.ResourceV3ConfigGroup(),
22882289
"huaweicloud_servicestagev3_environment": servicestage.ResourceV3Environment(),
22892290
"huaweicloud_servicestagev3_environment_associate": servicestage.ResourceV3EnvironmentAssociate(),
22902291

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package servicestage
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
10+
11+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
12+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
13+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/servicestage"
14+
)
15+
16+
func getV3ConfigGroup(conf *config.Config, state *terraform.ResourceState) (interface{}, error) {
17+
client, err := conf.NewServiceClient("servicestage", acceptance.HW_REGION_NAME)
18+
if err != nil {
19+
return nil, fmt.Errorf("error creating ServiceStage client: %s", err)
20+
}
21+
return servicestage.GetV3ConfigGroupById(client, state.Primary.ID)
22+
}
23+
24+
func TestAccV3ConfigGroup_basic(t *testing.T) {
25+
var (
26+
configGroup interface{}
27+
resourceName = "huaweicloud_servicestagev3_config_group.test"
28+
rc = acceptance.InitResourceCheck(resourceName, &configGroup, getV3ConfigGroup)
29+
30+
name = acceptance.RandomAccResourceName()
31+
)
32+
33+
resource.ParallelTest(t, resource.TestCase{
34+
PreCheck: func() { acceptance.TestAccPreCheck(t) },
35+
ProviderFactories: acceptance.TestAccProviderFactories,
36+
CheckDestroy: rc.CheckResourceDestroy(),
37+
Steps: []resource.TestStep{
38+
{
39+
Config: testAccV3ConfigGroup_basic(name),
40+
Check: resource.ComposeTestCheckFunc(
41+
rc.CheckResourceExists(),
42+
resource.TestCheckResourceAttr(resourceName, "name", name),
43+
resource.TestCheckResourceAttr(resourceName, "description", "Created by terraform test"),
44+
resource.TestCheckResourceAttrSet(resourceName, "creator"),
45+
resource.TestMatchResourceAttr(resourceName, "create_time", regexp.MustCompile(`^\d{13}$`)),
46+
),
47+
},
48+
{
49+
ResourceName: resourceName,
50+
ImportState: true,
51+
ImportStateVerify: true,
52+
},
53+
},
54+
})
55+
}
56+
57+
func testAccV3ConfigGroup_basic(name string) string {
58+
return fmt.Sprintf(`
59+
resource "huaweicloud_servicestagev3_config_group" "test" {
60+
name = "%[1]s"
61+
description = "Created by terraform test"
62+
}
63+
`, name)
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
package servicestage
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/hashicorp/go-multierror"
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/common"
15+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
16+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils"
17+
)
18+
19+
var v3ConfigGroupNonUpdatableParams = []string{"name", "description"}
20+
21+
// @API ServiceStage POST /v3/{project_id}/cas/config-groups
22+
// @API ServiceStage GET /v3/{project_id}/cas/config-groups/{config_group_id}
23+
// @API ServiceStage DELETE /v3/{project_id}/cas/config-groups/{config_group_id}
24+
func ResourceV3ConfigGroup() *schema.Resource {
25+
return &schema.Resource{
26+
CreateContext: resourceV3ConfigGroupCreate,
27+
ReadContext: resourceV3ConfigGroupRead,
28+
UpdateContext: resourceV3ConfigGroupUpdate,
29+
DeleteContext: resourceV3ConfigGroupDelete,
30+
31+
CustomizeDiff: config.FlexibleForceNew(v3ConfigGroupNonUpdatableParams),
32+
33+
Importer: &schema.ResourceImporter{
34+
StateContext: schema.ImportStatePassthroughContext,
35+
},
36+
37+
Schema: map[string]*schema.Schema{
38+
"region": {
39+
Type: schema.TypeString,
40+
Optional: true,
41+
Computed: true,
42+
ForceNew: true,
43+
},
44+
"name": {
45+
Type: schema.TypeString,
46+
Required: true,
47+
Description: `The name of the configuration group.`,
48+
},
49+
"description": {
50+
Type: schema.TypeString,
51+
Optional: true,
52+
Description: `The description of the configuration group.`,
53+
},
54+
"creator": {
55+
Type: schema.TypeString,
56+
Computed: true,
57+
Description: `The creator of the configuration group.`,
58+
},
59+
"create_time": {
60+
Type: schema.TypeInt,
61+
Computed: true,
62+
Description: `The creation time of the configuration group, in milliseconds.`,
63+
},
64+
},
65+
}
66+
}
67+
68+
func buildV3ConfigGroupCreateBodyParams(d *schema.ResourceData) map[string]interface{} {
69+
return map[string]interface{}{
70+
"name": d.Get("name"),
71+
"description": utils.ValueIgnoreEmpty(d.Get("description")),
72+
}
73+
}
74+
75+
func resourceV3ConfigGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
76+
var (
77+
cfg = meta.(*config.Config)
78+
httpUrl = "v3/{project_id}/cas/config-groups"
79+
)
80+
client, err := cfg.NewServiceClient("servicestage", cfg.GetRegion(d))
81+
if err != nil {
82+
return diag.Errorf("error creating ServiceStage client: %s", err)
83+
}
84+
85+
createPath := client.Endpoint + httpUrl
86+
createPath = strings.ReplaceAll(createPath, "{project_id}", client.ProjectID)
87+
88+
opt := golangsdk.RequestOpts{
89+
KeepResponseBody: true,
90+
MoreHeaders: map[string]string{
91+
"Content-Type": "application/json;charset=utf8",
92+
},
93+
JSONBody: utils.RemoveNil(buildV3ConfigGroupCreateBodyParams(d)),
94+
}
95+
96+
requestResp, err := client.Request("POST", createPath, &opt)
97+
if err != nil {
98+
return diag.Errorf("error creating configuration group: %s", err)
99+
}
100+
101+
respBody, err := utils.FlattenResponse(requestResp)
102+
if err != nil {
103+
return diag.FromErr(err)
104+
}
105+
106+
configGroupId := utils.PathSearch("id", respBody, "").(string)
107+
if configGroupId == "" {
108+
return diag.Errorf("unable to find the configuration group ID from the API response")
109+
}
110+
d.SetId(configGroupId)
111+
112+
return resourceV3ConfigGroupRead(ctx, d, meta)
113+
}
114+
115+
// GetV3ConfigGroupById is a method used to get configuration group detail bu its ID.
116+
func GetV3ConfigGroupById(client *golangsdk.ServiceClient, configGroupId string) (interface{}, error) {
117+
httpUrl := "v3/{project_id}/cas/config-groups/{config_group_id}"
118+
queryPath := client.Endpoint + httpUrl
119+
queryPath = strings.ReplaceAll(queryPath, "{project_id}", client.ProjectID)
120+
queryPath = strings.ReplaceAll(queryPath, "{config_group_id}", configGroupId)
121+
122+
opt := golangsdk.RequestOpts{
123+
KeepResponseBody: true,
124+
MoreHeaders: map[string]string{
125+
"Content-Type": "application/json;charset=utf8",
126+
},
127+
}
128+
129+
requestResp, err := client.Request("GET", queryPath, &opt)
130+
if err != nil {
131+
return nil, err
132+
}
133+
134+
return utils.FlattenResponse(requestResp)
135+
}
136+
137+
func resourceV3ConfigGroupRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
138+
var (
139+
cfg = meta.(*config.Config)
140+
region = cfg.GetRegion(d)
141+
configGroupId = d.Id()
142+
)
143+
client, err := cfg.NewServiceClient("servicestage", region)
144+
if err != nil {
145+
return diag.Errorf("error creating ServiceStage client: %s", err)
146+
}
147+
148+
respBody, err := GetV3ConfigGroupById(client, configGroupId)
149+
if err != nil {
150+
return common.CheckDeletedDiag(d, err, fmt.Sprintf("error retrieving configuration group (%s)", configGroupId))
151+
}
152+
153+
mErr := multierror.Append(nil,
154+
d.Set("region", region),
155+
d.Set("name", utils.PathSearch("name", respBody, nil)),
156+
d.Set("description", utils.PathSearch("description", respBody, nil)),
157+
d.Set("creator", utils.PathSearch("creator", respBody, nil)),
158+
d.Set("create_time", utils.PathSearch("create_time", respBody, nil)),
159+
)
160+
161+
return diag.FromErr(mErr.ErrorOrNil())
162+
}
163+
164+
func resourceV3ConfigGroupUpdate(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics {
165+
return nil
166+
}
167+
168+
func resourceV3ConfigGroupDelete(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
169+
var (
170+
cfg = meta.(*config.Config)
171+
region = cfg.GetRegion(d)
172+
httpUrl = "v3/{project_id}/cas/config-groups/{config_group_id}"
173+
configGroupId = d.Id()
174+
)
175+
client, err := cfg.NewServiceClient("servicestage", region)
176+
if err != nil {
177+
return diag.Errorf("error creating ServiceStage client: %s", err)
178+
}
179+
180+
deletePath := client.Endpoint + httpUrl
181+
deletePath = strings.ReplaceAll(deletePath, "{project_id}", client.ProjectID)
182+
deletePath = strings.ReplaceAll(deletePath, "{config_group_id}", configGroupId)
183+
184+
opt := golangsdk.RequestOpts{
185+
KeepResponseBody: true,
186+
MoreHeaders: map[string]string{
187+
"Content-Type": "application/json;charset=utf8",
188+
},
189+
}
190+
191+
// The delete API always returns 200 status code whether config group is exist.
192+
_, err = client.Request("DELETE", deletePath, &opt)
193+
if err != nil {
194+
return common.CheckDeletedDiag(d, err, fmt.Sprintf("error deleting configuration group (%s)", configGroupId))
195+
}
196+
return nil
197+
}

0 commit comments

Comments
 (0)