Skip to content

Commit e4d1fb4

Browse files
committed
feat: add tke new resource tencentcloud_kubernetes_backup_storage_location
1 parent ea1d19e commit e4d1fb4

File tree

12 files changed

+1048
-45
lines changed

12 files changed

+1048
-45
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ require (
8181
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tdmq v1.0.564
8282
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tem v1.0.578
8383
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.529
84-
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke v1.0.630
84+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke v1.0.644
8585
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tsf v1.0.625
8686
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.199
8787
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.638

go.sum

Lines changed: 2 additions & 32 deletions
Large diffs are not rendered by default.

tencentcloud/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ Tencent Kubernetes Engine(TKE)
420420
tencentcloud_kubernetes_cluster_attachment
421421
tencentcloud_kubernetes_node_pool
422422
tencentcloud_kubernetes_serverless_node_pool
423+
tencentcloud_kubernetes_backup_storage_location
423424
tencentcloud_kubernetes_auth_attachment
424425
tencentcloud_kubernetes_addon_attachment
425426
tencentcloud_kubernetes_cluster_endpoint
@@ -1537,6 +1538,7 @@ func Provider() terraform.ResourceProvider {
15371538
"tencentcloud_kubernetes_cluster_attachment": resourceTencentCloudTkeClusterAttachment(),
15381539
"tencentcloud_kubernetes_node_pool": resourceTencentCloudKubernetesNodePool(),
15391540
"tencentcloud_kubernetes_serverless_node_pool": resourceTkeServerLessNodePool(),
1541+
"tencentcloud_kubernetes_backup_storage_location": resourceTencentCloudTkeBackupStorageLocation(),
15401542
"tencentcloud_mysql_backup_policy": resourceTencentCloudMysqlBackupPolicy(),
15411543
"tencentcloud_mysql_account": resourceTencentCloudMysqlAccount(),
15421544
"tencentcloud_mysql_account_privilege": resourceTencentCloudMysqlAccountPrivilege(),
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
Provide a resource to create tke backup storage location.
3+
4+
~> **NOTE:** To create this resource, you need to create a cos bucket with prefix "tke-backup" in advance.
5+
6+
Example Usage
7+
```
8+
resource "tencentcloud_kubernetes_backup_storage_location" "example_backup" {
9+
name = "example-backup-1"
10+
storage_region = "ap-guangzhou" # region of you pre-created COS bucket
11+
bucket = "tke-backup-example-1" # bucket name of your pre-created COS bucket
12+
}
13+
```
14+
15+
Import
16+
17+
tke backup storage location can be imported, e.g.
18+
19+
```
20+
$ terraform import tencentcloud_kubernetes_backup_storage_location.test xxx
21+
```
22+
*/
23+
package tencentcloud
24+
25+
import (
26+
"context"
27+
"fmt"
28+
29+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
30+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
31+
tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525"
32+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper"
33+
)
34+
35+
const (
36+
backupStorageLocationStateAvailable = "Available"
37+
backupStorageLocationStateUnavailable = "Unavailable"
38+
)
39+
40+
func resourceTencentCloudTkeBackupStorageLocation() *schema.Resource {
41+
return &schema.Resource{
42+
Importer: &schema.ResourceImporter{
43+
State: schema.ImportStatePassthrough,
44+
},
45+
Create: resourceTencentCloudTkeBackupStorageLocationCreate,
46+
Read: resourceTencentCloudTkeBackupStorageLocationRead,
47+
Delete: resourceTencentCloudTkeBackupStorageLocationDelete,
48+
Schema: map[string]*schema.Schema{
49+
"name": {
50+
Type: schema.TypeString,
51+
Required: true,
52+
ForceNew: true,
53+
Description: "Name of the backup storage location.",
54+
},
55+
"storage_region": {
56+
Type: schema.TypeString,
57+
Required: true,
58+
ForceNew: true,
59+
Description: "Region of the storage.",
60+
},
61+
"bucket": {
62+
Type: schema.TypeString,
63+
Required: true,
64+
ForceNew: true,
65+
Description: "Name of the bucket.",
66+
},
67+
"path": {
68+
Type: schema.TypeString,
69+
Optional: true,
70+
ForceNew: true,
71+
Description: "Prefix of the bucket.",
72+
},
73+
"state": {
74+
Type: schema.TypeString,
75+
Computed: true,
76+
Description: "State of the backup storage location.",
77+
},
78+
"message": {
79+
Type: schema.TypeString,
80+
Computed: true,
81+
Description: "Message of the backup storage location.",
82+
},
83+
},
84+
}
85+
}
86+
87+
func resourceTencentCloudTkeBackupStorageLocationCreate(d *schema.ResourceData, meta interface{}) error {
88+
defer logElapsed("resource.tencentcloud_kubernetes_backup_storage_location.create")()
89+
90+
logId := getLogId(contextNil)
91+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
92+
client := meta.(*TencentCloudClient).apiV3Conn
93+
service := TkeService{client: client}
94+
95+
request := genCreateBackupStorageLocationRequest(d)
96+
err := service.createBackupStorageLocation(ctx, request)
97+
if err != nil {
98+
return err
99+
}
100+
101+
// wait for status ok
102+
err = resource.Retry(3*readRetryTimeout, func() *resource.RetryError {
103+
locations, errRet := service.describeBackupStorageLocations(ctx, []string{d.Get("name").(string)})
104+
if errRet != nil {
105+
return retryError(errRet, InternalError)
106+
}
107+
if len(locations) != 1 {
108+
resource.RetryableError(fmt.Errorf("more than 1 location returnen in api response, expected 1 but got %d", len(locations)))
109+
}
110+
if locations[0].State == nil {
111+
return resource.RetryableError(fmt.Errorf("location %s is still in state nil", d.Get("name").(string)))
112+
}
113+
if len(locations) == 1 && *locations[0].State == backupStorageLocationStateAvailable {
114+
return nil
115+
}
116+
return resource.RetryableError(fmt.Errorf("location %s is still in state %s", d.Get("name").(string), *locations[0].State))
117+
})
118+
if err != nil {
119+
return err
120+
}
121+
122+
d.SetId(d.Get("name").(string))
123+
return resourceTencentCloudTkeBackupStorageLocationRead(d, meta)
124+
}
125+
126+
func resourceTencentCloudTkeBackupStorageLocationRead(d *schema.ResourceData, meta interface{}) error {
127+
defer logElapsed("resource.tencentcloud_kubernetes_backup_storage_location.read")()
128+
129+
logId := getLogId(contextNil)
130+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
131+
client := meta.(*TencentCloudClient).apiV3Conn
132+
service := TkeService{client: client}
133+
134+
locations, err := service.describeBackupStorageLocations(ctx, []string{d.Id()})
135+
if err != nil {
136+
return err
137+
}
138+
has := false
139+
for _, location := range locations {
140+
if *location.Name == d.Id() {
141+
has = true
142+
_ = d.Set("name", location.Name)
143+
_ = d.Set("storage_region", location.StorageRegion)
144+
_ = d.Set("bucket", location.Bucket)
145+
_ = d.Set("path", location.Path)
146+
_ = d.Set("state", location.State)
147+
_ = d.Set("message", location.Message)
148+
return nil
149+
}
150+
}
151+
if !has {
152+
d.SetId("")
153+
return nil
154+
}
155+
156+
return nil
157+
}
158+
159+
func resourceTencentCloudTkeBackupStorageLocationDelete(d *schema.ResourceData, meta interface{}) error {
160+
defer logElapsed("resource.tencentcloud_kubernetes_backup_storage_location.delete")()
161+
162+
logId := getLogId(contextNil)
163+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
164+
client := meta.(*TencentCloudClient).apiV3Conn
165+
service := TkeService{client: client}
166+
167+
err := service.deleteBackupStorageLocation(ctx, d.Id())
168+
if err != nil {
169+
return err
170+
}
171+
172+
// wait until location is deleted
173+
err = resource.Retry(3*readRetryTimeout, func() *resource.RetryError {
174+
locations, errRet := service.describeBackupStorageLocations(ctx, []string{d.Id()})
175+
if errRet != nil {
176+
return retryError(errRet, InternalError)
177+
}
178+
if len(locations) == 0 {
179+
return nil
180+
}
181+
return resource.RetryableError(fmt.Errorf("location %s is still not deleted", d.Id()))
182+
})
183+
184+
return nil
185+
}
186+
187+
func genCreateBackupStorageLocationRequest(d *schema.ResourceData) (request *tke.CreateBackupStorageLocationRequest) {
188+
request = tke.NewCreateBackupStorageLocationRequest()
189+
if v, ok := d.GetOk("name"); ok {
190+
request.Name = helper.String(v.(string))
191+
}
192+
if v, ok := d.GetOk("storage_region"); ok {
193+
request.StorageRegion = helper.String(v.(string))
194+
}
195+
if v, ok := d.GetOk("bucket"); ok {
196+
request.Bucket = helper.String(v.(string))
197+
}
198+
if v, ok := d.GetOk("path"); ok {
199+
request.Path = helper.String(v.(string))
200+
}
201+
return request
202+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package tencentcloud
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"math/rand"
8+
"testing"
9+
"time"
10+
11+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
12+
"github.com/hashicorp/terraform-plugin-sdk/terraform"
13+
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
14+
tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525"
15+
)
16+
17+
const (
18+
testTkeBackupStorageLocationResourceKey = "tencentcloud_kubernetes_backup_storage_location.test_case_backup_storage_location"
19+
20+
backupStorageLocationNameTemplate = "tf-test-case-backup-storage-location-%d"
21+
backupLocationBucketTemplate = "tke-backup-tf-test-case-%d"
22+
)
23+
24+
func init() {
25+
// go test -v ./tencentcloud -sweep=ap-guangzhou -sweep-run=tencentcloud_backup_storage_location
26+
resource.AddTestSweepers("testBackupStorageLocationSweep", &resource.Sweeper{
27+
Name: "tencentcloud_backup_storage_location",
28+
F: testBackupStorageLocationSweep,
29+
})
30+
}
31+
32+
func TestAccTencentCloudKubernetesBackupStorageLocationResource_Basic(t *testing.T) {
33+
t.Parallel()
34+
35+
randIns := rand.New(rand.NewSource(time.Now().UnixNano()))
36+
randomNum := randIns.Intn(100)
37+
backupStorageLocationName := fmt.Sprintf(backupStorageLocationNameTemplate, randomNum)
38+
backupLocationBucket := fmt.Sprintf(backupLocationBucketTemplate, randomNum)
39+
40+
resource.Test(t, resource.TestCase{
41+
PreCheck: func() { testAccPreCheck(t) },
42+
Providers: testAccProviders,
43+
CheckDestroy: testAccCheckBackupStorageLocationDestroy,
44+
Steps: []resource.TestStep{
45+
{
46+
Config: getTestAccTkeBackupStorageLocationConfig(backupStorageLocationName, backupLocationBucket),
47+
Check: resource.ComposeTestCheckFunc(
48+
testAccCheckTencentCloudDataSourceID(testTkeBackupStorageLocationResourceKey),
49+
resource.TestCheckResourceAttr(testTkeBackupStorageLocationResourceKey, "name", backupStorageLocationName),
50+
resource.TestCheckResourceAttr(testTkeBackupStorageLocationResourceKey, "storage_region", "ap-guangzhou"),
51+
resource.TestCheckResourceAttrSet(testTkeBackupStorageLocationResourceKey, "bucket"),
52+
),
53+
},
54+
},
55+
})
56+
}
57+
58+
func testBackupStorageLocationSweep(region string) error {
59+
logId := getLogId(contextNil)
60+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
61+
62+
cli, err := sharedClientForRegion(region)
63+
if err != nil {
64+
return fmt.Errorf("error getting client: %s", err)
65+
}
66+
log.Printf("testServerlessNodePoolSweep region %s", region)
67+
68+
client := cli.(*TencentCloudClient).apiV3Conn
69+
service := TkeService{client: client}
70+
71+
randomNum := rand.Intn(100)
72+
backupStorageLocationName := fmt.Sprintf(backupStorageLocationNameTemplate, randomNum)
73+
backupLocationBucket := fmt.Sprintf(backupLocationBucketTemplate, randomNum)
74+
75+
// create backup storage location
76+
request := tke.NewCreateBackupStorageLocationRequest()
77+
request.Name = common.StringPtr(backupStorageLocationName)
78+
request.StorageRegion = common.StringPtr(region)
79+
request.Bucket = common.StringPtr(backupLocationBucket)
80+
if err := service.createBackupStorageLocation(ctx, request); err != nil {
81+
return fmt.Errorf("error creating backup storage location: %s", err)
82+
}
83+
84+
// delete backup storage location
85+
if err := service.deleteBackupStorageLocation(ctx, backupStorageLocationName); err != nil {
86+
return fmt.Errorf("error deleting backup storage location: %s", err)
87+
}
88+
return nil
89+
}
90+
91+
func testAccCheckBackupStorageLocationDestroy(s *terraform.State) error {
92+
logId := getLogId(contextNil)
93+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
94+
95+
client := testAccProvider.Meta().(*TencentCloudClient).apiV3Conn
96+
service := TkeService{client: client}
97+
98+
for _, rs := range s.RootModule().Resources {
99+
if rs.Type != "tencentcloud_kubernetes_backup_storage_location" {
100+
continue
101+
}
102+
103+
locations, err := service.describeBackupStorageLocations(ctx, []string{rs.Primary.ID})
104+
if err != nil {
105+
return err
106+
}
107+
if len(locations) > 0 {
108+
return fmt.Errorf("backup storage location still exists: %s", rs.Primary.ID)
109+
}
110+
}
111+
return nil
112+
}
113+
114+
func getTestAccTkeBackupStorageLocationConfig(name, bucket string) string {
115+
return fmt.Sprintf(testBackupStorageLocationConfigTemplate, bucket, name)
116+
}
117+
118+
const (
119+
testBackupStorageLocationConfigTemplate = `
120+
data "tencentcloud_user_info" "info" {}
121+
locals {
122+
app_id = data.tencentcloud_user_info.info.app_id
123+
uin = data.tencentcloud_user_info.info.uin
124+
owner_uin = data.tencentcloud_user_info.info.owner_uin
125+
}
126+
resource "tencentcloud_cos_bucket" "back_up_bucket" {
127+
bucket = "%s-${local.app_id}"
128+
}
129+
resource "tencentcloud_kubernetes_backup_storage_location" "test_case_backup_storage_location" {
130+
name = "%s"
131+
storage_region = "ap-guangzhou"
132+
bucket = tencentcloud_cos_bucket.back_up_bucket.bucket
133+
}
134+
`
135+
)

0 commit comments

Comments
 (0)