Skip to content

Commit 41f0247

Browse files
committed
feat(cbh): add postPaid mode to create instance
1 parent 35cb5ae commit 41f0247

File tree

2 files changed

+104
-37
lines changed

2 files changed

+104
-37
lines changed

docs/resources/cbh_instance.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ The following arguments are supported:
7676

7777
Changing this parameter will create a new resource.
7878

79-
* `period_unit` - (Required, String, ForceNew) Specifies the charging period unit of the instance.
79+
* `period_unit` - (Optional, String, ForceNew) Specifies the charging period unit of the instance.
8080
Valid values are *month* and *year*.
8181

8282
Changing this parameter will create a new resource.
8383

84-
* `period` - (Required, Int, ForceNew) Specifies the charging period of the CBH instance.
84+
* `period` - (Optional, Int, ForceNew) Specifies the charging period of the CBH instance.
8585
If `period_unit` is set to **month**, the value ranges from `1` to `9`.
8686
If `period_unit` is set to **year**, the value ranges from `1` to `3`.
8787

huaweicloud/services/cbh/resource_huaweicloud_cbh_instance.go

Lines changed: 102 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cbh
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"log"
78
"strings"
@@ -116,12 +117,13 @@ func ResourceCBHInstance() *schema.Resource {
116117
ForceNew: true,
117118
ValidateFunc: validation.StringInSlice([]string{
118119
"prePaid",
120+
"postPaid",
119121
}, false),
120122
Description: `Specifies the charging mode of the CBH instance.`,
121123
},
122124
"period_unit": {
123125
Type: schema.TypeString,
124-
Required: true,
126+
Optional: true,
125127
ForceNew: true,
126128
ValidateFunc: validation.StringInSlice([]string{
127129
"month", "year",
@@ -130,7 +132,7 @@ func ResourceCBHInstance() *schema.Resource {
130132
},
131133
"period": {
132134
Type: schema.TypeInt,
133-
Required: true,
135+
Optional: true,
134136
ForceNew: true,
135137
Description: `Specifies the charging period of the CBH instance.`,
136138
},
@@ -208,45 +210,57 @@ func resourceCBHInstanceCreate(ctx context.Context, d *schema.ResourceData, meta
208210
cfg = meta.(*config.Config)
209211
region = cfg.GetRegion(d)
210212
createCbhInstanceProduct = "cbh"
213+
serverId string
211214
)
212215

213216
client, err := cfg.NewServiceClient(createCbhInstanceProduct, region)
214217
if err != nil {
215218
return diag.Errorf("error creating CBH client: %s", err)
216219
}
217220

218-
orderId, err := createCBHInstance(client, d, cfg)
219-
if err != nil {
220-
return diag.FromErr(err)
221-
}
222-
223221
bssClient, err := cfg.BssV2Client(cfg.GetRegion(d))
224222
if err != nil {
225223
return diag.Errorf("error creating BSS v2 client: %s", err)
226224
}
227225

228-
if err := common.WaitOrderComplete(ctx, bssClient, orderId, d.Timeout(schema.TimeoutCreate)); err != nil {
229-
return diag.FromErr(err)
230-
}
226+
if d.Get("charging_mode").(string) == "prePaid" {
227+
orderId, err := createCBHInstance(client, d, cfg)
228+
if err != nil {
229+
return diag.FromErr(err)
230+
}
231231

232-
resourceId, err := common.WaitOrderResourceComplete(ctx, bssClient, orderId, d.Timeout(schema.TimeoutCreate))
233-
if err != nil {
234-
return diag.Errorf("error waiting for CBH instance order %s complete: %s", orderId, err)
235-
}
232+
if err := common.WaitOrderComplete(ctx, bssClient, orderId, d.Timeout(schema.TimeoutCreate)); err != nil {
233+
return diag.FromErr(err)
234+
}
236235

237-
instances, err := getCBHInstanceList(client)
238-
if err != nil {
239-
return diag.FromErr(err)
240-
}
241-
expression := fmt.Sprintf("[?resource_info.resource_id == '%s']|[0].server_id", resourceId)
242-
serverId := utils.PathSearch(expression, instances, "").(string)
243-
if serverId == "" {
244-
return diag.Errorf("unable to find the CBH instance ID from the API response")
245-
}
236+
resourceId, err := common.WaitOrderResourceComplete(ctx, bssClient, orderId, d.Timeout(schema.TimeoutCreate))
237+
if err != nil {
238+
return diag.Errorf("error waiting for CBH instance order %s complete: %s", orderId, err)
239+
}
246240

247-
d.SetId(serverId)
248-
if err := waitingForCBHInstanceActive(ctx, client, d, d.Timeout(schema.TimeoutCreate)); err != nil {
249-
return diag.Errorf("error waiting for CBH instance (%s) creation to active: %s", d.Id(), err)
241+
instances, err := getCBHInstanceList(client)
242+
if err != nil {
243+
return diag.FromErr(err)
244+
}
245+
expression := fmt.Sprintf("[?resource_info.resource_id == '%s']|[0].server_id", resourceId)
246+
serverId = utils.PathSearch(expression, instances, "").(string)
247+
if serverId == "" {
248+
return diag.Errorf("unable to find the CBH instance ID from the API response")
249+
}
250+
251+
d.SetId(serverId)
252+
if err := waitingForCBHInstanceActive(ctx, client, d, d.Timeout(schema.TimeoutCreate)); err != nil {
253+
return diag.Errorf("error waiting for CBH instance (%s) creation to active: %s", d.Id(), err)
254+
}
255+
} else {
256+
instanceId, err := createCBHInstance(client, d, cfg)
257+
if err != nil {
258+
return diag.FromErr(err)
259+
}
260+
261+
if err := waitingForCBHInstanceActiveByInstanceID(ctx, client, instanceId, d, d.Timeout(schema.TimeoutCreate)); err != nil {
262+
return diag.Errorf("error waiting for CBH instance (%s) creation to active: %s", d.Id(), err)
263+
}
250264
}
251265

252266
// After successfully creating an instance using the first security group ID, check if it is necessary to update the
@@ -295,11 +309,17 @@ func createCBHInstance(client *golangsdk.ServiceClient, d *schema.ResourceData,
295309
return "", err
296310
}
297311

298-
orderId := utils.PathSearch("order_id", createInstanceRespBody, "").(string)
299-
if orderId == "" {
300-
return "", fmt.Errorf("unable to find the order ID of the CBH instance from the API response")
312+
var targetId string
313+
if d.Get("charging_mode").(string) == "prePaid" {
314+
targetId = utils.PathSearch("order_id", createInstanceRespBody, "").(string)
315+
} else {
316+
targetId = utils.PathSearch("instance_id", createInstanceRespBody, "").(string)
301317
}
302-
return orderId, nil
318+
319+
if targetId == "" {
320+
return "", errors.New("unable to find the order/instance ID of the CBH instance from the API response")
321+
}
322+
return targetId, nil
303323
}
304324

305325
func buildCreateCBHInstanceBodyParam(d *schema.ResourceData, region string, epsId string, publicIp interface{}) map[string]interface{} {
@@ -310,14 +330,16 @@ func buildCreateCBHInstanceBodyParam(d *schema.ResourceData, region string, epsI
310330
"region": region,
311331
"availability_zone": d.Get("availability_zone"),
312332
"charging_mode": buildCreateChargingModeParam(d),
313-
"period_type": buildCreatePeriodTypeParam(d),
314-
"period_num": utils.ValueIgnoreEmpty(d.Get("period")),
315-
"is_auto_renew": buildCreateIsAutoRenewParam(d),
316-
"is_auto_pay": 1,
317333
"network": buildCreateNetworkBodyParam(d, publicIp),
318334
"attach_disk_size": utils.ValueIgnoreEmpty(d.Get("attach_disk_size")),
319335
"enterprise_project_id": utils.ValueIgnoreEmpty(epsId),
320336
}
337+
if d.Get("charging_mode").(string) == "prePaid" {
338+
bodyParam["period_type"] = buildCreatePeriodTypeParam(d)
339+
bodyParam["period_num"] = utils.ValueIgnoreEmpty(d.Get("period"))
340+
bodyParam["is_auto_renew"] = buildCreateIsAutoRenewParam(d)
341+
bodyParam["is_auto_pay"] = 1
342+
}
321343
// The default value of the field `ipv6_enable` is false
322344
if d.Get("ipv6_enable").(bool) {
323345
bodyParam["ipv6_enable"] = true
@@ -335,6 +357,9 @@ func buildCreateChargingModeParam(d *schema.ResourceData) interface{} {
335357
if d.Get("charging_mode").(string) == "prePaid" {
336358
return 0
337359
}
360+
if d.Get("charging_mode").(string) == "postPaid" {
361+
return 1
362+
}
338363
return nil
339364
}
340365

@@ -534,6 +559,48 @@ func waitingForCBHInstanceShutoff(ctx context.Context, client *golangsdk.Service
534559
return err
535560
}
536561

562+
func waitingForCBHInstanceActiveByInstanceID(ctx context.Context, client *golangsdk.ServiceClient, instanceId string, d *schema.ResourceData,
563+
timeout time.Duration) error {
564+
expression := fmt.Sprintf("[?instance_id == '%s']|[0]", instanceId)
565+
unexpectedStatus := []string{"SHUTOFF", "DELETING", "DELETED", "ERROR", "FROZEN"}
566+
stateConf := &resource.StateChangeConf{
567+
Pending: []string{"PENDING"},
568+
Target: []string{"COMPLETED"},
569+
Refresh: func() (interface{}, string, error) {
570+
instances, err := getCBHInstanceList(client)
571+
if err != nil {
572+
return nil, "ERROR", err
573+
}
574+
instance := utils.PathSearch(expression, instances, nil)
575+
if instance == nil {
576+
return nil, "ERROR", golangsdk.ErrDefault404{}
577+
}
578+
579+
status := utils.PathSearch("status_info.status", instance, "").(string)
580+
if status == "ACTIVE" {
581+
serverId := utils.PathSearch("server_id", instance, "").(string)
582+
d.SetId(serverId)
583+
return instance, "COMPLETED", nil
584+
}
585+
586+
if status == "" {
587+
return instance, "ERROR", errors.New("status is not found in list API response")
588+
}
589+
590+
if utils.StrSliceContains(unexpectedStatus, status) {
591+
return instance, status, nil
592+
}
593+
return instance, "PENDING", nil
594+
},
595+
Timeout: timeout,
596+
Delay: 10 * time.Second,
597+
PollInterval: 10 * time.Second,
598+
}
599+
600+
_, err := stateConf.WaitForStateContext(ctx)
601+
return err
602+
}
603+
537604
func waitingForCBHInstanceActive(ctx context.Context, client *golangsdk.ServiceClient, d *schema.ResourceData,
538605
timeout time.Duration) error {
539606
expression := fmt.Sprintf("[?server_id == '%s']|[0]", d.Id())
@@ -557,7 +624,7 @@ func waitingForCBHInstanceActive(ctx context.Context, client *golangsdk.ServiceC
557624
}
558625

559626
if status == "" {
560-
return instance, "ERROR", fmt.Errorf("status is not found in list API response")
627+
return instance, "ERROR", errors.New("status is not found in list API response")
561628
}
562629

563630
if utils.StrSliceContains(unexpectedStatus, status) {

0 commit comments

Comments
 (0)