Skip to content

Commit fa755d4

Browse files
tongyimingmikatong
andauthored
Fix/cvm query (#722)
* [fix] cvm support product params query * [fix] fetch available zones by product * [fix] fetch available zones by product Co-authored-by: mikatong <[email protected]>
1 parent b4125aa commit fa755d4

11 files changed

+328
-0
lines changed

examples/tencentcloud-as/variables.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ variable "max_size" {
1717
variable "desired_capacity" {
1818
default = 0
1919
}
20+
21+
variable "cvm_product" {
22+
default = "cvm"
23+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ require (
1717
github.com/mitchellh/go-homedir v1.1.0
1818
github.com/mozillazg/go-httpheader v0.3.0 // indirect
1919
github.com/pkg/errors v0.9.1
20+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/api v1.0.285
2021
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apigateway v1.0.199
2122
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.199
2223
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.199

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s
446446
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
447447
github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2 h1:Xr9gkxfOP0KQWXKNqmwe8vEeSUiUj4Rlee9CMVX2ZUQ=
448448
github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM=
449+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/api v1.0.285 h1:gFmukRGLtYiXVBVvg/5DP/0fM1+dKpwDjT+khtDVLmc=
450+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/api v1.0.285/go.mod h1:aGlXSWjtSnE6kuqcaRy/NKj1CLiB8NlMSHGsDn+k7Ag=
449451
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apigateway v1.0.199 h1:e9M5HSIq2xw61Oz9whoaq+QT95rZtowkY/2zhdzx9v4=
450452
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apigateway v1.0.199/go.mod h1:ynirFavajqWLAcgEp9ZiMd9xn5JnKTJhQisArjMxNtk=
451453
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as v1.0.199 h1:6g9q97yBhlJcPO03WGdvMYVv+AC027djOAiJPTsBKlY=

tencentcloud/connectivity/client.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/aws/aws-sdk-go/aws/endpoints"
1414
"github.com/aws/aws-sdk-go/aws/session"
1515
"github.com/aws/aws-sdk-go/service/s3"
16+
api "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/api/v20201106"
1617
apigateway "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/apigateway/v20180808"
1718
as "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/as/v20180419"
1819
cam "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam/v20190116"
@@ -94,6 +95,7 @@ type TencentCloudClient struct {
9495
sslCertificateConn *sslCertificate.Client
9596
kmsConn *kms.Client
9697
ssmConn *ssm.Client
98+
apiConn *api.Client
9799
}
98100

99101
// NewClientProfile returns a new ClientProfile
@@ -607,3 +609,15 @@ func (me *TencentCloudClient) UseSsmClient() *ssm.Client {
607609

608610
return me.ssmConn
609611
}
612+
613+
// UseApiClient return API client for service
614+
func (me *TencentCloudClient) UseApiClient() *api.Client {
615+
if me.apiConn != nil {
616+
return me.apiConn
617+
}
618+
cpf := me.NewClientProfile(300)
619+
me.apiConn, _ = api.NewClient(me.Credential, me.Region, cpf)
620+
me.apiConn.WithHttpTransport(&LogRoundTripper{})
621+
622+
return me.apiConn
623+
}

tencentcloud/data_source_tc_availability_zones.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323

2424
func dataSourceTencentCloudAvailabilityZones() *schema.Resource {
2525
return &schema.Resource{
26+
DeprecationMessage: "This data source will been deprecated in Terraform TencentCloud provider later version. Please use `tencentcloud_availability_zones_by_product` instead.",
27+
2628
Read: dataSourceTencentCloudAvailabilityZonesRead,
2729

2830
Schema: map[string]*schema.Schema{
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
Use this data source to get the available zones in current region.
3+
* Must set product param to fetch the product infomations(e.g. => cvm, vpc)
4+
* By default only `AVAILABLE` zones will be returned, but `UNAVAILABLE` zones can also be fetched when `include_unavailable` is specified.
5+
Example Usage
6+
7+
```hcl
8+
data "tencentcloud_availability_zones_by_product" "all" {
9+
product="cvm"
10+
}
11+
```
12+
*/
13+
package tencentcloud
14+
15+
import (
16+
"context"
17+
"log"
18+
19+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
20+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
21+
api "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/api/v20201106"
22+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper"
23+
)
24+
25+
func dataSourceTencentCloudAvailabilityZonesByProduct() *schema.Resource {
26+
return &schema.Resource{
27+
Read: dataSourceTencentCloudAvailabilityZonesByProductRead,
28+
29+
Schema: map[string]*schema.Schema{
30+
"name": {
31+
Type: schema.TypeString,
32+
Optional: true,
33+
Description: "When specified, only the zone with the exactly name match will be returned.",
34+
},
35+
"product": {
36+
Type: schema.TypeString,
37+
Required: true,
38+
Description: "A string variable indicates that the query will use product infomation.",
39+
},
40+
"include_unavailable": {
41+
Type: schema.TypeBool,
42+
Optional: true,
43+
Description: "A bool variable indicates that the query will include `UNAVAILABLE` zones.",
44+
},
45+
"result_output_file": {
46+
Type: schema.TypeString,
47+
Optional: true,
48+
Description: "Used to save results.",
49+
},
50+
51+
// Computed values.
52+
"zones": {
53+
Type: schema.TypeList,
54+
Computed: true,
55+
Description: "A list of zones will be exported and its every element contains the following attributes:",
56+
Elem: &schema.Resource{
57+
Schema: map[string]*schema.Schema{
58+
"id": {
59+
Type: schema.TypeString,
60+
Computed: true,
61+
Description: "An internal id for the zone, like `200003`, usually not so useful.",
62+
},
63+
"name": {
64+
Type: schema.TypeString,
65+
Computed: true,
66+
Description: "The name of the zone, like `ap-guangzhou-3`.",
67+
},
68+
"description": {
69+
Type: schema.TypeString,
70+
Computed: true,
71+
Description: "The description of the zone, like `Guangzhou Zone 3`.",
72+
},
73+
"state": {
74+
Type: schema.TypeString,
75+
Computed: true,
76+
Description: "The state of the zone, indicate availability using `AVAILABLE` and `UNAVAILABLE` values.",
77+
},
78+
},
79+
},
80+
},
81+
},
82+
}
83+
}
84+
85+
func dataSourceTencentCloudAvailabilityZonesByProductRead(d *schema.ResourceData, meta interface{}) error {
86+
defer logElapsed("data_source.tencentcloud_availability_zones.read")()
87+
88+
logId := getLogId(contextNil)
89+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
90+
apiService := APIService{
91+
client: meta.(*TencentCloudClient).apiV3Conn,
92+
}
93+
94+
var name string
95+
var product string
96+
var includeUnavailable = false
97+
if v, ok := d.GetOk("name"); ok {
98+
name = v.(string)
99+
}
100+
if v, ok := d.GetOk("product"); ok {
101+
product = v.(string)
102+
}
103+
if v, ok := d.GetOkExists("include_unavailable"); ok {
104+
includeUnavailable = v.(bool)
105+
}
106+
107+
var zones []*api.ZoneInfo
108+
var errRet error
109+
err := resource.Retry(readRetryTimeout, func() *resource.RetryError {
110+
zones, errRet = apiService.DescribeZonesWithProduct(ctx, product)
111+
if errRet != nil {
112+
return retryError(errRet, InternalError)
113+
}
114+
return nil
115+
})
116+
if err != nil {
117+
return err
118+
}
119+
120+
zoneList := make([]map[string]interface{}, 0, len(zones))
121+
ids := make([]string, 0, len(zones))
122+
for _, zone := range zones {
123+
if name != "" && name != *zone.Zone {
124+
continue
125+
}
126+
if !includeUnavailable && *zone.ZoneState == ZONE_STATE_UNAVAILABLE {
127+
continue
128+
}
129+
mapping := map[string]interface{}{
130+
"id": zone.ZoneId,
131+
"name": zone.Zone,
132+
"description": zone.ZoneName,
133+
"state": zone.ZoneState,
134+
}
135+
zoneList = append(zoneList, mapping)
136+
ids = append(ids, *zone.ZoneId)
137+
}
138+
139+
d.SetId(helper.DataResourceIdsHash(ids))
140+
err = d.Set("zones", zoneList)
141+
if err != nil {
142+
log.Printf("[CRITAL]%s provider set zones list fail, reason:%s\n ", logId, err.Error())
143+
return err
144+
}
145+
146+
output, ok := d.GetOk("result_output_file")
147+
if ok && output.(string) != "" {
148+
if err := writeToFile(output.(string), zoneList); err != nil {
149+
return err
150+
}
151+
}
152+
153+
return nil
154+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package tencentcloud
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
7+
)
8+
9+
func TestAccTencentCloudAvailabilityZonesByProductDataSource_basic(t *testing.T) {
10+
resource.Test(t, resource.TestCase{
11+
PreCheck: func() {
12+
testAccPreCheck(t)
13+
},
14+
Providers: testAccProviders,
15+
Steps: []resource.TestStep{
16+
{
17+
Config: testAccTencentCloudAvailabilityZonesByProductByProductDataSourceConfigBasic,
18+
Check: resource.ComposeTestCheckFunc(
19+
testAccCheckTencentCloudDataSourceID("data.tencentcloud_availability_zones_by_product.all"),
20+
resource.TestCheckResourceAttrSet("data.tencentcloud_availability_zones_by_product.all", "zones.#"),
21+
),
22+
},
23+
{
24+
Config: testAccTencentCloudAvailabilityZonesByProductByProductDataSourceConfigFilterWithName,
25+
Check: resource.ComposeTestCheckFunc(
26+
testAccCheckTencentCloudDataSourceID("data.tencentcloud_availability_zones_by_product.filter"),
27+
resource.TestCheckResourceAttrSet("data.tencentcloud_availability_zones_by_product.filter", "zones.#"),
28+
),
29+
},
30+
{
31+
Config: testAccTencentCloudAvailabilityZonesByProductDataSourceConfigIncludeUnavailable,
32+
Check: resource.ComposeTestCheckFunc(
33+
testAccCheckTencentCloudDataSourceID("data.tencentcloud_availability_zones_by_product.unavailable"),
34+
resource.TestCheckResourceAttrSet("data.tencentcloud_availability_zones_by_product.unavailable", "zones.#"),
35+
),
36+
},
37+
{
38+
Config: testAccTencentCloudAvailabilityZonesByProductDataSourceConfigIncludeUnavailable,
39+
Check: resource.ComposeTestCheckFunc(
40+
testAccCheckTencentCloudDataSourceID("data.tencentcloud_availability_zones_by_product.unavailable"),
41+
resource.TestCheckResourceAttrSet("data.tencentcloud_availability_zones_by_product.unavailable", "zones.#"),
42+
),
43+
},
44+
},
45+
})
46+
}
47+
48+
const testAccTencentCloudAvailabilityZonesByProductByProductDataSourceConfigBasic = `
49+
data "tencentcloud_availability_zones_by_product" "basic" {
50+
product = var.cvm_product
51+
}
52+
`
53+
54+
const testAccTencentCloudAvailabilityZonesByProductByProductDataSourceConfigFilterWithName = defaultVpcVariable + `
55+
data "tencentcloud_availability_zones_by_product" "filter" {
56+
product = var.cvm_product
57+
name = var.availability_zone
58+
}
59+
`
60+
61+
const testAccTencentCloudAvailabilityZonesByProductDataSourceConfigIncludeUnavailable = `
62+
data "tencentcloud_availability_zones_by_product" "unavailable" {
63+
product = var.cvm_product
64+
include_unavailable = true
65+
}
66+
`

tencentcloud/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Resources List
3535
Provider Data Sources
3636
tencentcloud_availability_regions
3737
tencentcloud_availability_zones
38+
tencentcloud_availability_zones_by_product
3839
3940
Anti-DDoS(Dayu)
4041
Data Source
@@ -659,6 +660,7 @@ func Provider() terraform.ResourceProvider {
659660
DataSourcesMap: map[string]*schema.Resource{
660661
"tencentcloud_availability_regions": dataSourceTencentCloudAvailabilityRegions(),
661662
"tencentcloud_availability_zones": dataSourceTencentCloudAvailabilityZones(),
663+
"tencentcloud_availability_zones_by_product": dataSourceTencentCloudAvailabilityZonesByProduct(),
662664
"tencentcloud_instances": dataSourceTencentCloudInstances(),
663665
"tencentcloud_reserved_instances": dataSourceTencentCloudReservedInstances(),
664666
"tencentcloud_placement_groups": dataSourceTencentCloudPlacementGroups(),
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package tencentcloud
2+
3+
import (
4+
"context"
5+
"log"
6+
7+
api "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/api/v20201106"
8+
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
9+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/connectivity"
10+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/ratelimit"
11+
)
12+
13+
type APIService struct {
14+
client *connectivity.TencentCloudClient
15+
}
16+
17+
func (me *APIService) DescribeZonesWithProduct(ctx context.Context, product string) (zones []*api.ZoneInfo, errRet error) {
18+
logId := getLogId(ctx)
19+
request := api.NewDescribeZonesRequest()
20+
request.Product = common.StringPtr(product)
21+
22+
ratelimit.Check(request.GetAction())
23+
// API: https://cloud.tencent.com/document/product/1278/55254
24+
response, err := me.client.UseApiClient().DescribeZones(request)
25+
if err != nil {
26+
log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n",
27+
logId, request.GetAction(), request.ToJsonString(), err.Error())
28+
errRet = err
29+
return
30+
}
31+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n",
32+
logId, request.GetAction(), request.ToJsonString(), response.ToJsonString())
33+
34+
zones = response.Response.ZoneSet
35+
return
36+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
subcategory: "Provider Data Sources"
3+
layout: "tencentcloud"
4+
page_title: "TencentCloud: tencentcloud_availability_zones_by_product"
5+
sidebar_current: "docs-tencentcloud-datasource-availability_zones_by_product"
6+
description: |-
7+
Use this data source to get the available zones in current region.
8+
* Must set product param to fetch the product infomations(e.g. => cvm, vpc)
9+
* By default only `AVAILABLE` zones will be returned, but `UNAVAILABLE` zones can also be fetched when `include_unavailable` is specified.
10+
---
11+
12+
# tencentcloud_availability_zones_by_product
13+
14+
Use this data source to get the available zones in current region.
15+
* Must set product param to fetch the product infomations(e.g. => cvm, vpc)
16+
* By default only `AVAILABLE` zones will be returned, but `UNAVAILABLE` zones can also be fetched when `include_unavailable` is specified.
17+
18+
## Example Usage
19+
20+
```hcl
21+
data "tencentcloud_availability_zones_by_product" "all" {
22+
product = "cvm"
23+
}
24+
```
25+
26+
## Argument Reference
27+
28+
The following arguments are supported:
29+
30+
* `include_unavailable` - (Optional) A bool variable indicates that the query will include `UNAVAILABLE` zones.
31+
* `name` - (Optional) When specified, only the zone with the exactly name match will be returned.
32+
* `result_output_file` - (Optional) Used to save results.
33+
34+
## Attributes Reference
35+
36+
In addition to all arguments above, the following attributes are exported:
37+
38+
* `zones` - A list of zones will be exported and its every element contains the following attributes:
39+
* `description` - The description of the zone, like `Guangzhou Zone 3`.
40+
* `id` - An internal id for the zone, like `200003`, usually not so useful.
41+
* `name` - The name of the zone, like `ap-guangzhou-3`.
42+
* `state` - The state of the zone, indicate availability using `AVAILABLE` and `UNAVAILABLE` values.
43+
44+

0 commit comments

Comments
 (0)