Skip to content

Commit 2de14a3

Browse files
authored
Merge pull request #1691 from xawei/feat/tke-backup-storage-location
feat: add tke new resource tencentcloud_kubernetes_backup_storage_location
2 parents f63691a + 9e53912 commit 2de14a3

File tree

14 files changed

+1051
-48
lines changed

14 files changed

+1051
-48
lines changed

.changelog/1691.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:new-resource
2+
tencentcloud_kubernetes_backup_storage_location
3+
```

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/extension_tke.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,7 @@ const (
132132
TKE_CLUSTER_OPEN_ACCESS = true
133133
TKE_CLUSTER_CLOSE_ACCESS = false
134134
)
135+
136+
const (
137+
backupStorageLocationStateAvailable = "Available"
138+
)

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
@@ -1544,6 +1545,7 @@ func Provider() terraform.ResourceProvider {
15441545
"tencentcloud_kubernetes_cluster_attachment": resourceTencentCloudTkeClusterAttachment(),
15451546
"tencentcloud_kubernetes_node_pool": resourceTencentCloudKubernetesNodePool(),
15461547
"tencentcloud_kubernetes_serverless_node_pool": resourceTkeServerLessNodePool(),
1548+
"tencentcloud_kubernetes_backup_storage_location": resourceTencentCloudTkeBackupStorageLocation(),
15471549
"tencentcloud_mysql_backup_policy": resourceTencentCloudMysqlBackupPolicy(),
15481550
"tencentcloud_mysql_account": resourceTencentCloudMysqlAccount(),
15491551
"tencentcloud_mysql_account_privilege": resourceTencentCloudMysqlAccountPrivilege(),
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
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+
9+
resource "tencentcloud_kubernetes_backup_storage_location" "example_backup" {
10+
name = "example-backup-1"
11+
storage_region = "ap-guangzhou" # region of you pre-created COS bucket
12+
bucket = "tke-backup-example-1" # bucket name of your pre-created COS bucket
13+
}
14+
15+
```
16+
17+
Import
18+
19+
tke backup storage location can be imported, e.g.
20+
21+
```
22+
$ terraform import tencentcloud_kubernetes_backup_storage_location.test xxx
23+
```
24+
*/
25+
package tencentcloud
26+
27+
import (
28+
"context"
29+
"fmt"
30+
31+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
32+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
33+
tke "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke/v20180525"
34+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper"
35+
)
36+
37+
func resourceTencentCloudTkeBackupStorageLocation() *schema.Resource {
38+
return &schema.Resource{
39+
Importer: &schema.ResourceImporter{
40+
State: schema.ImportStatePassthrough,
41+
},
42+
Create: resourceTencentCloudTkeBackupStorageLocationCreate,
43+
Read: resourceTencentCloudTkeBackupStorageLocationRead,
44+
Delete: resourceTencentCloudTkeBackupStorageLocationDelete,
45+
Schema: map[string]*schema.Schema{
46+
"name": {
47+
Type: schema.TypeString,
48+
Required: true,
49+
ForceNew: true,
50+
Description: "Name of the backup storage location.",
51+
},
52+
"storage_region": {
53+
Type: schema.TypeString,
54+
Required: true,
55+
ForceNew: true,
56+
Description: "Region of the storage.",
57+
},
58+
"bucket": {
59+
Type: schema.TypeString,
60+
Required: true,
61+
ForceNew: true,
62+
Description: "Name of the bucket.",
63+
},
64+
"path": {
65+
Type: schema.TypeString,
66+
Optional: true,
67+
ForceNew: true,
68+
Description: "Prefix of the bucket.",
69+
},
70+
"state": {
71+
Type: schema.TypeString,
72+
Computed: true,
73+
Description: "State of the backup storage location.",
74+
},
75+
"message": {
76+
Type: schema.TypeString,
77+
Computed: true,
78+
Description: "Message of the backup storage location.",
79+
},
80+
},
81+
}
82+
}
83+
84+
func resourceTencentCloudTkeBackupStorageLocationCreate(d *schema.ResourceData, meta interface{}) error {
85+
defer logElapsed("resource.tencentcloud_kubernetes_backup_storage_location.create")()
86+
87+
logId := getLogId(contextNil)
88+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
89+
client := meta.(*TencentCloudClient).apiV3Conn
90+
service := TkeService{client: client}
91+
92+
request := genCreateBackupStorageLocationRequest(d)
93+
err := service.createBackupStorageLocation(ctx, request)
94+
if err != nil {
95+
return err
96+
}
97+
98+
// wait for status ok
99+
err = resource.Retry(3*readRetryTimeout, func() *resource.RetryError {
100+
locations, errRet := service.describeBackupStorageLocations(ctx, []string{d.Get("name").(string)})
101+
if errRet != nil {
102+
return retryError(errRet, InternalError)
103+
}
104+
if len(locations) != 1 {
105+
resource.RetryableError(fmt.Errorf("more than 1 location returnen in api response, expected 1 but got %d", len(locations)))
106+
}
107+
if locations[0].State == nil {
108+
return resource.RetryableError(fmt.Errorf("location %s is still in state nil", d.Get("name").(string)))
109+
}
110+
if len(locations) == 1 && *locations[0].State == backupStorageLocationStateAvailable {
111+
return nil
112+
}
113+
return resource.RetryableError(fmt.Errorf("location %s is still in state %s", d.Get("name").(string), *locations[0].State))
114+
})
115+
if err != nil {
116+
return err
117+
}
118+
119+
d.SetId(d.Get("name").(string))
120+
return resourceTencentCloudTkeBackupStorageLocationRead(d, meta)
121+
}
122+
123+
func resourceTencentCloudTkeBackupStorageLocationRead(d *schema.ResourceData, meta interface{}) error {
124+
defer logElapsed("resource.tencentcloud_kubernetes_backup_storage_location.read")()
125+
126+
logId := getLogId(contextNil)
127+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
128+
client := meta.(*TencentCloudClient).apiV3Conn
129+
service := TkeService{client: client}
130+
131+
locations, err := service.describeBackupStorageLocations(ctx, []string{d.Id()})
132+
if err != nil {
133+
return err
134+
}
135+
for _, location := range locations {
136+
if *location.Name == d.Id() {
137+
_ = d.Set("name", location.Name)
138+
_ = d.Set("storage_region", location.StorageRegion)
139+
_ = d.Set("bucket", location.Bucket)
140+
_ = d.Set("path", location.Path)
141+
_ = d.Set("state", location.State)
142+
_ = d.Set("message", location.Message)
143+
return nil
144+
}
145+
}
146+
147+
d.SetId("")
148+
return nil
149+
}
150+
151+
func resourceTencentCloudTkeBackupStorageLocationDelete(d *schema.ResourceData, meta interface{}) error {
152+
defer logElapsed("resource.tencentcloud_kubernetes_backup_storage_location.delete")()
153+
154+
logId := getLogId(contextNil)
155+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
156+
client := meta.(*TencentCloudClient).apiV3Conn
157+
service := TkeService{client: client}
158+
159+
err := service.deleteBackupStorageLocation(ctx, d.Id())
160+
if err != nil {
161+
return err
162+
}
163+
164+
// wait until location is deleted
165+
err = resource.Retry(3*readRetryTimeout, func() *resource.RetryError {
166+
locations, errRet := service.describeBackupStorageLocations(ctx, []string{d.Id()})
167+
if errRet != nil {
168+
return retryError(errRet, InternalError)
169+
}
170+
if len(locations) == 0 {
171+
return nil
172+
}
173+
return resource.RetryableError(fmt.Errorf("location %s is still not deleted", d.Id()))
174+
})
175+
if err != nil {
176+
return err
177+
}
178+
179+
return nil
180+
}
181+
182+
func genCreateBackupStorageLocationRequest(d *schema.ResourceData) (request *tke.CreateBackupStorageLocationRequest) {
183+
request = tke.NewCreateBackupStorageLocationRequest()
184+
if v, ok := d.GetOk("name"); ok {
185+
request.Name = helper.String(v.(string))
186+
}
187+
if v, ok := d.GetOk("storage_region"); ok {
188+
request.StorageRegion = helper.String(v.(string))
189+
}
190+
if v, ok := d.GetOk("bucket"); ok {
191+
request.Bucket = helper.String(v.(string))
192+
}
193+
if v, ok := d.GetOk("path"); ok {
194+
request.Path = helper.String(v.(string))
195+
}
196+
return request
197+
}
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+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper"
7+
"log"
8+
"math/rand"
9+
"testing"
10+
"time"
11+
12+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
13+
"github.com/hashicorp/terraform-plugin-sdk/terraform"
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 = helper.String(backupStorageLocationName)
78+
request.StorageRegion = helper.String(region)
79+
request.Bucket = helper.String(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)