Skip to content

Commit d56b42b

Browse files
gitmknanonymous
andauthored
feat: support ci_bucket (#1471)
* feat: support ci_bucket * feat: add changelog * fix: modify unit Co-authored-by: anonymous <anonymous@mail.org>
1 parent a2d3b93 commit d56b42b

21 files changed

+1257
-161
lines changed

.changelog/1471.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_ci_bucket_attachment
3+
```

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ require (
8080
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.199
8181
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.515
8282
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/wss v1.0.199
83-
github.com/tencentyun/cos-go-sdk-v5 v0.7.38
83+
github.com/tencentyun/cos-go-sdk-v5 v0.7.40
8484
github.com/yangwenmai/ratelimit v0.0.0-20180104140304-44221c2292e1
8585
github.com/zclconf/go-cty v1.4.2 // indirect
8686
golang.org/x/sys v0.0.0-20200523222454-059865788121 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/wss v1.0.199 h1:hMBLtiJ
632632
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/wss v1.0.199/go.mod h1:nnY91/H3j/Gu7V/oCA6Zeg8T5D3q36EUdBh4EjmHwqY=
633633
github.com/tencentyun/cos-go-sdk-v5 v0.7.38 h1:EsMD39fDk5GRD8ouOcHG5MAb0CIT0ndDm6kZgSAYuBg=
634634
github.com/tencentyun/cos-go-sdk-v5 v0.7.38/go.mod h1:4dCEtLHGh8QPxHEkgq+nFaky7yZxQuYwgSJM87icDaw=
635+
github.com/tencentyun/cos-go-sdk-v5 v0.7.40 h1:W6vDGKCHe4wBACI1d2UgE6+50sJFhRWU4O8IB2ozzxM=
636+
github.com/tencentyun/cos-go-sdk-v5 v0.7.40/go.mod h1:4dCEtLHGh8QPxHEkgq+nFaky7yZxQuYwgSJM87icDaw=
635637
github.com/tetafro/godot v0.3.7 h1:+mecr7RKrUKB5UQ1gwqEMn13sDKTyDR8KNIquB9mm+8=
636638
github.com/tetafro/godot v0.3.7/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0=
637639
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q=

tencentcloud/connectivity/client.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ type TencentCloudClient struct {
151151
tdcpgConn *tdcpg.Client
152152
dbbrainConn *dbbrain.Client
153153
dtsConn *dts.Client
154+
ciConn *cos.Client
154155
}
155156

156157
// NewClientProfile returns a new ClientProfile
@@ -975,6 +976,30 @@ func (me *TencentCloudClient) UseDtsClient() *dts.Client {
975976
return me.dtsConn
976977
}
977978

979+
// UseCiClient returns ci client for service
980+
func (me *TencentCloudClient) UseCiClient(bucket string) *cos.Client {
981+
u, _ := url.Parse(fmt.Sprintf("https://%s.pic.%s.myqcloud.com", bucket, me.Region))
982+
983+
if me.ciConn != nil && me.ciConn.BaseURL.CIURL == u {
984+
return me.ciConn
985+
}
986+
987+
baseUrl := &cos.BaseURL{
988+
CIURL: u,
989+
}
990+
991+
me.ciConn = cos.NewClient(baseUrl, &http.Client{
992+
Timeout: 100 * time.Second,
993+
Transport: &cos.AuthorizationTransport{
994+
SecretID: me.Credential.SecretId,
995+
SecretKey: me.Credential.SecretKey,
996+
SessionToken: me.Credential.Token,
997+
},
998+
})
999+
1000+
return me.ciConn
1001+
}
1002+
9781003
func getEnvDefault(key string, defVal int) int {
9791004
val, ex := os.LookupEnv(key)
9801005
if !ex {

tencentcloud/provider.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,10 @@ TDMQ for RocketMQ(trocket)
860860
tencentcloud_tdmq_rocketmq_topic
861861
tencentcloud_tdmq_rocketmq_group
862862
tencentcloud_tdmq_rocketmq_environment_role
863+
864+
Cloud Infinite(CI)
865+
Resource
866+
tencentcloud_ci_bucket_attachment
863867
*/
864868
package tencentcloud
865869

@@ -1520,6 +1524,7 @@ func Provider() terraform.ResourceProvider {
15201524
"tencentcloud_vpc_end_point_service": resourceTencentCloudVpcEndPointService(),
15211525
"tencentcloud_vpc_end_point": resourceTencentCloudVpcEndPoint(),
15221526
"tencentcloud_vpc_end_point_service_white_list": resourceTencentCloudVpcEndPointServiceWhiteList(),
1527+
"tencentcloud_ci_bucket_attachment": resourceTencentCloudCiBucketAttachment(),
15231528
},
15241529

15251530
ConfigureFunc: providerConfigure,
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
Provides a resource to create a ci bucket
3+
4+
Example Usage
5+
6+
```hcl
7+
resource "tencentcloud_ci_bucket_attachment" "bucket_attachment" {
8+
bucket = "terraform-ci-xxxxxx"
9+
}
10+
```
11+
12+
Import
13+
14+
ci bucket can be imported using the id, e.g.
15+
16+
```
17+
terraform import tencentcloud_ci_bucket_attachment.bucket_attachment terraform-ci-xxxxxx
18+
```
19+
*/
20+
package tencentcloud
21+
22+
import (
23+
"context"
24+
"fmt"
25+
"log"
26+
27+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
28+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
29+
"github.com/pkg/errors"
30+
)
31+
32+
func resourceTencentCloudCiBucketAttachment() *schema.Resource {
33+
return &schema.Resource{
34+
Create: resourceTencentCloudCiBucketAttachmentCreate,
35+
Read: resourceTencentCloudCiBucketAttachmentRead,
36+
Delete: resourceTencentCloudCiBucketAttachmentDelete,
37+
Importer: &schema.ResourceImporter{
38+
State: schema.ImportStatePassthrough,
39+
},
40+
Schema: map[string]*schema.Schema{
41+
"bucket": {
42+
Required: true,
43+
ForceNew: true,
44+
Type: schema.TypeString,
45+
ValidateFunc: validateCosBucketName,
46+
Description: "bucket name.",
47+
},
48+
"ci_status": {
49+
Type: schema.TypeString,
50+
Computed: true,
51+
Description: "Binding object storage state, `on`: bound, `off`: unbound, `unbinding`: unbinding.",
52+
},
53+
},
54+
}
55+
}
56+
57+
func resourceTencentCloudCiBucketAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
58+
defer logElapsed("resource.tencentcloud_ci_bucket_attachment.create")()
59+
defer inconsistentCheck(d, meta)()
60+
61+
logId := getLogId(contextNil)
62+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
63+
64+
var bucket string
65+
if v, ok := d.GetOk("bucket"); ok {
66+
bucket = v.(string)
67+
} else {
68+
return errors.New("get bucket failed!")
69+
}
70+
71+
ciClient := meta.(*TencentCloudClient).apiV3Conn.UseCiClient(bucket)
72+
err := resource.Retry(writeRetryTimeout, func() *resource.RetryError {
73+
result, e := ciClient.CI.OpenCIService(ctx)
74+
if e != nil {
75+
return retryError(e)
76+
} else {
77+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response status [%s]\n", logId, "OpenCIService", bucket, result.Status)
78+
}
79+
return nil
80+
})
81+
if err != nil {
82+
log.Printf("[CRITAL]%s create ci bucket failed, reason:%+v", logId, err)
83+
return err
84+
}
85+
86+
d.SetId(bucket)
87+
88+
return resourceTencentCloudCiBucketAttachmentRead(d, meta)
89+
}
90+
91+
func resourceTencentCloudCiBucketAttachmentRead(d *schema.ResourceData, meta interface{}) error {
92+
defer logElapsed("resource.tencentcloud_ci_bucket_attachment.read")()
93+
defer inconsistentCheck(d, meta)()
94+
95+
logId := getLogId(contextNil)
96+
97+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
98+
99+
service := CiService{client: meta.(*TencentCloudClient).apiV3Conn}
100+
101+
bucket := d.Id()
102+
103+
result, err := service.DescribeCiBucketById(ctx, bucket)
104+
if err != nil {
105+
return err
106+
}
107+
108+
if result == nil {
109+
d.SetId("")
110+
return fmt.Errorf("resource `track` %s does not exist", d.Id())
111+
}
112+
113+
_ = d.Set("bucket", bucket)
114+
_ = d.Set("ci_status", result.CIStatus)
115+
116+
return nil
117+
}
118+
119+
func resourceTencentCloudCiBucketAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
120+
defer logElapsed("resource.tencentcloud_ci_bucket_attachment.delete")()
121+
defer inconsistentCheck(d, meta)()
122+
123+
logId := getLogId(contextNil)
124+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
125+
126+
service := CiService{client: meta.(*TencentCloudClient).apiV3Conn}
127+
bucket := d.Id()
128+
129+
if err := service.DeleteCiBucketById(ctx, bucket); err != nil {
130+
return err
131+
}
132+
133+
retryErr := resource.Retry(writeRetryTimeout, func() *resource.RetryError {
134+
result, e := service.DescribeCiBucketById(ctx, bucket)
135+
if e != nil {
136+
return retryError(e)
137+
}
138+
if result.CIStatus == "unbinding" {
139+
return resource.RetryableError(fmt.Errorf("Binding bucket status is %s , retry...", result.CIStatus))
140+
}
141+
if result.CIStatus == "off" {
142+
return nil
143+
}
144+
return resource.RetryableError(fmt.Errorf("Binding bucket status is %s , retry...", result.CIStatus))
145+
})
146+
if retryErr != nil {
147+
return retryErr
148+
}
149+
150+
return nil
151+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package tencentcloud
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-sdk/terraform"
10+
)
11+
12+
// go test -i; go test -test.run TestAccTencentCloudCiBucketAttachmentResource_basic -v
13+
func TestAccTencentCloudCiBucketAttachmentResource_basic(t *testing.T) {
14+
t.Parallel()
15+
16+
resource.Test(t, resource.TestCase{
17+
PreCheck: func() { testAccPreCheck(t) },
18+
Providers: testAccProviders,
19+
CheckDestroy: testAccCheckCiBucketAttachmentDestroy,
20+
Steps: []resource.TestStep{
21+
{
22+
Config: testAccCiBucketAttachment,
23+
Check: resource.ComposeTestCheckFunc(
24+
testAccCheckCiBucketAttachmentExists("tencentcloud_ci_bucket_attachment.bucket_attachment"),
25+
resource.TestCheckResourceAttrSet("tencentcloud_ci_bucket_attachment.bucket_attachment", "id"),
26+
resource.TestCheckResourceAttr("tencentcloud_ci_bucket_attachment.bucket_attachment", "ci_status", "on"),
27+
),
28+
},
29+
{
30+
ResourceName: "tencentcloud_ci_bucket_attachment.bucket_attachment",
31+
ImportState: true,
32+
ImportStateVerify: true,
33+
},
34+
},
35+
})
36+
}
37+
38+
func testAccCheckCiBucketAttachmentDestroy(s *terraform.State) error {
39+
logId := getLogId(contextNil)
40+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
41+
service := CiService{client: testAccProvider.Meta().(*TencentCloudClient).apiV3Conn}
42+
for _, rs := range s.RootModule().Resources {
43+
if rs.Type != "tencentcloud_ci_bucket_attachment" {
44+
continue
45+
}
46+
47+
res, err := service.DescribeCiBucketById(ctx, rs.Primary.ID)
48+
if err != nil {
49+
return err
50+
}
51+
52+
if res != nil {
53+
status := res.CIStatus
54+
if res.CIStatus == "on" {
55+
return fmt.Errorf("ci bucket still exist, Id: %v, status:%s", rs.Primary.ID, status)
56+
}
57+
}
58+
}
59+
return nil
60+
}
61+
62+
func testAccCheckCiBucketAttachmentExists(re string) resource.TestCheckFunc {
63+
return func(s *terraform.State) error {
64+
logId := getLogId(contextNil)
65+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
66+
service := CiService{client: testAccProvider.Meta().(*TencentCloudClient).apiV3Conn}
67+
68+
rs, ok := s.RootModule().Resources[re]
69+
if !ok {
70+
return fmt.Errorf("ci bucket %s is not found", re)
71+
}
72+
if rs.Primary.ID == "" {
73+
return fmt.Errorf(" id is not set")
74+
}
75+
76+
result, err := service.DescribeCiBucketById(ctx, rs.Primary.ID)
77+
if err != nil {
78+
return err
79+
}
80+
81+
if result == nil {
82+
return fmt.Errorf("ci bucket not found, Id: %v", rs.Primary.ID)
83+
}
84+
85+
if result != nil {
86+
status := result.CIStatus
87+
if result.CIStatus == "off" {
88+
return fmt.Errorf("ci bucket unbound, Id: %v, status:%s", rs.Primary.ID, status)
89+
}
90+
}
91+
return nil
92+
}
93+
}
94+
95+
const testAccCiBucketAttachment = `
96+
97+
resource "tencentcloud_ci_bucket_attachment" "bucket_attachment" {
98+
bucket = "terraform-ci-1308919341"
99+
}
100+
101+
`
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package tencentcloud
2+
3+
import (
4+
"context"
5+
"log"
6+
7+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/connectivity"
8+
ci "github.com/tencentyun/cos-go-sdk-v5"
9+
)
10+
11+
type CiService struct {
12+
client *connectivity.TencentCloudClient
13+
}
14+
15+
func (me *CiService) DescribeCiBucketById(ctx context.Context, bucket string) (serviceResult *ci.CIServiceResult, errRet error) {
16+
logId := getLogId(ctx)
17+
18+
defer func() {
19+
if errRet != nil {
20+
log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, "GetCIService", bucket, errRet.Error())
21+
}
22+
}()
23+
24+
result, response, err := me.client.UseCiClient(bucket).CI.GetCIService(ctx)
25+
if err != nil {
26+
errRet = err
27+
return
28+
}
29+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s], http status [%s]\n", logId, "GetCIService", bucket, result, response.Status)
30+
31+
serviceResult = result
32+
return
33+
}
34+
35+
func (me *CiService) DeleteCiBucketById(ctx context.Context, bucket string) (errRet error) {
36+
logId := getLogId(ctx)
37+
38+
defer func() {
39+
if errRet != nil {
40+
log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, "CloseCIService", bucket, errRet.Error())
41+
}
42+
}()
43+
44+
response, err := me.client.UseCiClient(bucket).CI.CloseCIService(ctx)
45+
if err != nil {
46+
errRet = err
47+
return
48+
}
49+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response status [%s]\n", logId, "CloseCIService", bucket, response.Status)
50+
51+
return
52+
}

vendor/github.com/tencentyun/cos-go-sdk-v5/.gitignore

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)