Skip to content

Commit db772a0

Browse files
authored
Merge pull request #169 from oliverpei/master
support reserved instance
2 parents 4282d86 + 5ff921e commit db772a0

30 files changed

+1704
-49
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
## 1.20.2 (Unreleased)
1+
## 1.21.0 (Unreleased)
2+
3+
FEATURES:
4+
5+
* **New Data Source**: `tencentcloud_reserved_instance_configs`
6+
* **New Data Source**: `tencentcloud_reserved_instances`
7+
* **New Resource**: `tencentcloud_reserved_instance`
28

39
ENHANCEMENTS:
410

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/hashicorp/terraform v0.12.3
1313
github.com/likexian/gokit v0.0.0-20190604165112-68b8a4ba758c
1414
github.com/mitchellh/go-homedir v1.1.0
15-
github.com/tencentcloud/tencentcloud-sdk-go v3.0.87-0.20190912121957-c0615982c83b+incompatible
15+
github.com/tencentcloud/tencentcloud-sdk-go v3.0.89-0.20191011161912-cf7a17a053dc+incompatible
1616
github.com/terraform-providers/terraform-provider-template v1.0.0
1717
github.com/yangwenmai/ratelimit v0.0.0-20180104140304-44221c2292e1
1818
github.com/zqfan/tencentcloud-sdk-go v0.0.0-0.20181105105106-4c76f78ff2e6

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,8 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
444444
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
445445
github.com/svanharmelen/jsonapi v0.0.0-20180618144545-0c0828c3f16d/go.mod h1:BSTlc8jOjh0niykqEGVXOLXdi9o0r0kR8tCYiMvjFgw=
446446
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
447-
github.com/tencentcloud/tencentcloud-sdk-go v3.0.87-0.20190912121957-c0615982c83b+incompatible h1:sDNLz6GOccksu6f0BQGCvIrgVNVEsEMPWlavN/OOwRc=
448-
github.com/tencentcloud/tencentcloud-sdk-go v3.0.87-0.20190912121957-c0615982c83b+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
447+
github.com/tencentcloud/tencentcloud-sdk-go v3.0.89-0.20191011161912-cf7a17a053dc+incompatible h1:h17QeWh1jk/uNz+ITJYiIzoSnOsMBH8Y81a+u28xwRc=
448+
github.com/tencentcloud/tencentcloud-sdk-go v3.0.89-0.20191011161912-cf7a17a053dc+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
449449
github.com/terraform-providers/terraform-provider-openstack v1.15.0/go.mod h1:2aQ6n/BtChAl1y2S60vebhyJyZXBsuAI5G4+lHrT1Ew=
450450
github.com/terraform-providers/terraform-provider-template v1.0.0 h1:g2pyFaAJu369iAb7qGWmVwtQ15/35lRAfW91Je8wLjE=
451451
github.com/terraform-providers/terraform-provider-template v1.0.0/go.mod h1:/J+B8me5DCMa0rEBH5ic2aKPjhtpWNeScmxFJWxB1EU=
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
Use this data source to query reserved instances configuration.
3+
4+
Example Usage
5+
6+
```hcl
7+
data "tencentcloud_reserved_instance_configs" "config" {
8+
availability_zone = "na-siliconvalley-1"
9+
}
10+
```
11+
*/
12+
package tencentcloud
13+
14+
import (
15+
"context"
16+
"log"
17+
"strconv"
18+
19+
"github.com/hashicorp/terraform/helper/resource"
20+
"github.com/hashicorp/terraform/helper/schema"
21+
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
22+
)
23+
24+
func dataSourceTencentCloudReservedInstanceConfigs() *schema.Resource {
25+
return &schema.Resource{
26+
Read: dataSourceTencentCloudReservedInstanceConfigsRead,
27+
28+
Schema: map[string]*schema.Schema{
29+
"availability_zone": {
30+
Type: schema.TypeString,
31+
Optional: true,
32+
Description: "The available zone that the reserved instance locates at.",
33+
},
34+
"duration": {
35+
Type: schema.TypeInt,
36+
Optional: true,
37+
ValidateFunc: validateAllowedIntValue([]int{31536000, 94608000}),
38+
Description: "Validity period of the reserved instance. Valid values are 31536000(1 year) and 94608000(3 years).",
39+
},
40+
"instance_type": {
41+
Type: schema.TypeString,
42+
Optional: true,
43+
Description: "The type of reserved instance.",
44+
},
45+
"result_output_file": {
46+
Type: schema.TypeString,
47+
Optional: true,
48+
Description: "Used to save results.",
49+
},
50+
51+
// computed
52+
"config_list": {
53+
Type: schema.TypeList,
54+
Computed: true,
55+
Description: "An information list of reserved instance configuration. Each element contains the following attributes:",
56+
Elem: &schema.Resource{
57+
Schema: map[string]*schema.Schema{
58+
"config_id": {
59+
Type: schema.TypeString,
60+
Computed: true,
61+
Description: "Configuration ID of the purchasable reserved instance.",
62+
},
63+
"availability_zone": {
64+
Type: schema.TypeString,
65+
Computed: true,
66+
Description: "Availability zone of the purchasable reserved instance.",
67+
},
68+
"instance_type": {
69+
Type: schema.TypeString,
70+
Computed: true,
71+
Description: "Instance type of the reserved instance.",
72+
},
73+
"duration": {
74+
Type: schema.TypeInt,
75+
Computed: true,
76+
Description: "Validity period of the reserved instance.",
77+
},
78+
"price": {
79+
Type: schema.TypeInt,
80+
Computed: true,
81+
Description: "Purchase price of the reserved instance.",
82+
},
83+
"currency_code": {
84+
Type: schema.TypeString,
85+
Computed: true,
86+
Description: "Settlement currency of the reserved instance, which is a standard currency code as listed in ISO 4217.",
87+
},
88+
"platform": {
89+
Type: schema.TypeString,
90+
Computed: true,
91+
Description: "Platform of the reserved instance.",
92+
},
93+
},
94+
},
95+
},
96+
},
97+
}
98+
}
99+
100+
func dataSourceTencentCloudReservedInstanceConfigsRead(d *schema.ResourceData, meta interface{}) error {
101+
defer logElapsed("data_source.tencentcloud_reserved_instance_configs.read")()
102+
logId := getLogId(contextNil)
103+
ctx := context.WithValue(context.TODO(), "logId", logId)
104+
cvmService := CvmService{
105+
client: meta.(*TencentCloudClient).apiV3Conn,
106+
}
107+
108+
filter := make(map[string]string)
109+
if v, ok := d.GetOk("availability_zone"); ok {
110+
filter["zone"] = v.(string)
111+
}
112+
if v, ok := d.GetOk("duration"); ok {
113+
filter["duration"] = strconv.Itoa(v.(int))
114+
}
115+
if v, ok := d.GetOk("instance_type"); ok {
116+
filter["instance-type"] = v.(string)
117+
}
118+
119+
var configs []*cvm.ReservedInstancesOffering
120+
var errRet error
121+
err := resource.Retry(readRetryTimeout, func() *resource.RetryError {
122+
configs, errRet = cvmService.DescribeReservedInstanceConfigs(ctx, filter)
123+
if errRet != nil {
124+
return retryError(errRet, "InternalError")
125+
}
126+
return nil
127+
})
128+
if err != nil {
129+
return err
130+
}
131+
132+
configList := make([]map[string]interface{}, 0, len(configs))
133+
ids := make([]string, 0, len(configs))
134+
for _, config := range configs {
135+
mapping := map[string]interface{}{
136+
"config_id": config.ReservedInstancesOfferingId,
137+
"availability_zone": config.Zone,
138+
"instance_type": config.InstanceType,
139+
"duration": config.Duration,
140+
"price": config.FixedPrice,
141+
"currency_code": config.CurrencyCode,
142+
"platform": config.ProductDescription,
143+
}
144+
configList = append(configList, mapping)
145+
ids = append(ids, *config.ReservedInstancesOfferingId)
146+
}
147+
148+
d.SetId(dataResourceIdsHash(ids))
149+
err = d.Set("config_list", configList)
150+
if err != nil {
151+
log.Printf("[CRITAL]%s provider set config list fail, reason:%s\n ", logId, err.Error())
152+
return err
153+
}
154+
155+
output, ok := d.GetOk("result_output_file")
156+
if ok && output.(string) != "" {
157+
if err := writeToFile(output.(string), configList); err != nil {
158+
return err
159+
}
160+
}
161+
return nil
162+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package tencentcloud
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform/helper/resource"
7+
)
8+
9+
func TestAccTencentCloudReservedInstanceConfigsDataSource(t *testing.T) {
10+
resource.Test(t, resource.TestCase{
11+
PreCheck: func() { testAccPreCheck(t) },
12+
Providers: testAccProviders,
13+
Steps: []resource.TestStep{
14+
{
15+
Config: testAccReservedInstanceConfigsDataSource,
16+
Check: resource.ComposeTestCheckFunc(
17+
resource.TestCheckResourceAttrSet("data.tencentcloud_reserved_instance_configs.configs", "config_list.#"),
18+
),
19+
},
20+
},
21+
})
22+
}
23+
24+
const testAccReservedInstanceConfigsDataSource = `
25+
data "tencentcloud_reserved_instance_configs" "configs" {
26+
availability_zone = "ap-guangzhou-2"
27+
}
28+
`
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
Use this data source to query reserved instances.
3+
4+
Example Usage
5+
6+
```hcl
7+
data "tencentcloud_reserved_instances" "instances" {
8+
availability_zone = "na-siliconvalley-1"
9+
instance_type = "S2.MEDIUM8"
10+
}
11+
```
12+
*/
13+
package tencentcloud
14+
15+
import (
16+
"context"
17+
"log"
18+
19+
"github.com/hashicorp/terraform/helper/resource"
20+
21+
"github.com/hashicorp/terraform/helper/schema"
22+
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
23+
)
24+
25+
func dataSourceTencentCloudReservedInstances() *schema.Resource {
26+
return &schema.Resource{
27+
Read: dataSourceTencentCloudReservedInstancesRead,
28+
29+
Schema: map[string]*schema.Schema{
30+
"reserved_instance_id": {
31+
Type: schema.TypeString,
32+
Optional: true,
33+
Description: "ID of the reserved instance to be query.",
34+
},
35+
"availability_zone": {
36+
Type: schema.TypeString,
37+
Optional: true,
38+
Description: "The available zone that the reserved instance locates at.",
39+
},
40+
"instance_type": {
41+
Type: schema.TypeString,
42+
Optional: true,
43+
Description: "The type of reserved instance.",
44+
},
45+
"result_output_file": {
46+
Type: schema.TypeString,
47+
Optional: true,
48+
Description: "Used to save results.",
49+
},
50+
51+
// computed
52+
"reserved_instance_list": {
53+
Type: schema.TypeList,
54+
Computed: true,
55+
Description: "An information list of reserved instance. Each element contains the following attributes:",
56+
Elem: &schema.Resource{
57+
Schema: map[string]*schema.Schema{
58+
"reserved_instance_id": {
59+
Type: schema.TypeString,
60+
Computed: true,
61+
Description: "ID of the reserved instance.",
62+
},
63+
"instance_type": {
64+
Type: schema.TypeString,
65+
Computed: true,
66+
Description: "The type of reserved instance.",
67+
},
68+
"instance_count": {
69+
Type: schema.TypeInt,
70+
Computed: true,
71+
Description: "Number of reserved instance.",
72+
},
73+
"availability_zone": {
74+
Type: schema.TypeString,
75+
Computed: true,
76+
Description: "Availability zone of the reserved instance.",
77+
},
78+
"start_time": {
79+
Type: schema.TypeString,
80+
Computed: true,
81+
Description: "Start time of the reserved instance.",
82+
},
83+
"end_time": {
84+
Type: schema.TypeString,
85+
Computed: true,
86+
Description: "Expiry time of the reserved instance.",
87+
},
88+
"status": {
89+
Type: schema.TypeString,
90+
Computed: true,
91+
Description: "Status of the reserved instance.",
92+
},
93+
},
94+
},
95+
},
96+
},
97+
}
98+
}
99+
100+
func dataSourceTencentCloudReservedInstancesRead(d *schema.ResourceData, meta interface{}) error {
101+
defer logElapsed("data_source.tencentcloud_reserved_instances.read")
102+
logId := getLogId(contextNil)
103+
ctx := context.WithValue(context.TODO(), "logId", logId)
104+
cvmService := CvmService{
105+
client: meta.(*TencentCloudClient).apiV3Conn,
106+
}
107+
108+
filter := make(map[string]string)
109+
if v, ok := d.GetOk("reserved_instance_id"); ok {
110+
filter["reserved-instances-id"] = v.(string)
111+
}
112+
if v, ok := d.GetOk("availability_zone"); ok {
113+
filter["zone"] = v.(string)
114+
}
115+
if v, ok := d.GetOk("instance_type"); ok {
116+
filter["instance-type"] = v.(string)
117+
}
118+
119+
var instances []*cvm.ReservedInstances
120+
var errRet error
121+
err := resource.Retry(readRetryTimeout, func() *resource.RetryError {
122+
instances, errRet = cvmService.DescribeReservedInstanceByFilter(ctx, filter)
123+
if errRet != nil {
124+
return retryError(errRet, "InternalError")
125+
}
126+
return nil
127+
})
128+
if err != nil {
129+
return err
130+
}
131+
132+
instanceList := make([]map[string]interface{}, 0, len(instances))
133+
ids := make([]string, 0, len(instances))
134+
for _, instance := range instances {
135+
mapping := map[string]interface{}{
136+
"reserved_instance_id": instance.ReservedInstancesId,
137+
"instance_type": instance.InstanceType,
138+
"instance_count": instance.InstanceCount,
139+
"availability_zone": instance.Zone,
140+
"start_time": instance.StartTime,
141+
"end_time": instance.EndTime,
142+
"status": instance.State,
143+
}
144+
instanceList = append(instanceList, mapping)
145+
ids = append(ids, *instance.ReservedInstancesId)
146+
}
147+
d.SetId(dataResourceIdsHash(ids))
148+
err = d.Set("reserved_instance_list", instanceList)
149+
if err != nil {
150+
log.Printf("[CRITAL]%s provider set reserved instance list fail, reason:%s\n ", logId, err.Error())
151+
return err
152+
}
153+
154+
output, ok := d.GetOk("result_output_file")
155+
if ok && output.(string) != "" {
156+
if err := writeToFile(output.(string), instanceList); err != nil {
157+
return err
158+
}
159+
}
160+
return nil
161+
}

0 commit comments

Comments
 (0)