Skip to content

Commit de8d3fe

Browse files
authored
feat: cdn - support url push and purge (#1105)
1 parent a13254d commit de8d3fe

10 files changed

+1003
-17
lines changed

tencentcloud/provider.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ Content Delivery Network(CDN)
130130
131131
Resource
132132
tencentcloud_cdn_domain
133+
tencentcloud_cdn_url_push
134+
tencentcloud_cdn_url_purge
133135
134136
Ckafka
135137
Data Source
@@ -1039,6 +1041,8 @@ func Provider() terraform.ResourceProvider {
10391041
"tencentcloud_tcaplus_idl": resourceTencentCloudTcaplusIdl(),
10401042
"tencentcloud_tcaplus_table": resourceTencentCloudTcaplusTable(),
10411043
"tencentcloud_cdn_domain": resourceTencentCloudCdnDomain(),
1044+
"tencentcloud_cdn_url_push": resourceTencentCloudUrlPush(),
1045+
"tencentcloud_cdn_url_purge": resourceTencentCloudUrlPurge(),
10421046
"tencentcloud_monitor_policy_group": resourceTencentMonitorPolicyGroup(),
10431047
"tencentcloud_monitor_binding_object": resourceTencentMonitorBindingObject(),
10441048
"tencentcloud_monitor_policy_binding_object": resourceTencentMonitorPolicyBindingObject(),

tencentcloud/resource_tc_cdn_domain_test.go

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package tencentcloud
33
import (
44
"context"
55
"fmt"
6+
"log"
67
"testing"
78

89
sdkErrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
@@ -35,6 +36,11 @@ func init() {
3536
for i := range domains {
3637
item := domains[i]
3738
name := *item.Domain
39+
40+
if isResourcePersist(name, nil) {
41+
continue
42+
}
43+
3844
if *item.Status != "offline" {
3945
_ = service.StopDomain(ctx, name)
4046
}
@@ -61,7 +67,13 @@ func testAccTencentCloudCdnDomainResource(t *testing.T) {
6167
t.Parallel()
6268

6369
resource.Test(t, resource.TestCase{
64-
PreCheck: func() { testAccPreCheckCommon(t, ACCOUNT_TYPE_PREPAY) },
70+
PreCheck: func() {
71+
testAccPreCheckCommon(t, ACCOUNT_TYPE_PREPAY)
72+
if err := testAccCdnDomainVerify("www"); err != nil {
73+
log.Printf("[TestAccTencentCloudCdnDomainResource] Domain Verify failed: %s", err)
74+
t.Fatalf("[TestAccTencentCloudCdnDomainResource] Domain Verify failed: %s", err)
75+
}
76+
},
6577
Providers: testAccProviders,
6678
CheckDestroy: testAccCheckCdnDomainDestroy,
6779
Steps: []resource.TestStep{
@@ -90,7 +102,8 @@ func TestAccTencentCloudCdnDomainWithHTTPs(t *testing.T) {
90102
resource.Test(t, resource.TestCase{
91103
PreCheck: func() {
92104
testAccPreCheckCommon(t, ACCOUNT_TYPE_PREPAY)
93-
if err := testAccCdnDomainVerify(); err != nil {
105+
if err := testAccCdnDomainVerify("c"); err != nil {
106+
log.Printf("[TestAccCentcentCloudCdnDomainWithHTTPs] Domain Verify failed: %s", err)
94107
t.Fatalf("[TestAccCentcentCloudCdnDomainWithHTTPs] Domain Verify failed: %s", err)
95108
}
96109
},
@@ -202,9 +215,12 @@ func testAccGetTestingDomain() (string, error) {
202215
return *domains[0].DomainName, nil
203216
}
204217

205-
func testAccCdnDomainVerify() error {
218+
func testAccCdnDomainVerify(domainPrefix string) error {
219+
logId := getLogId(contextNil)
220+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
206221
cli, _ := sharedClientForRegion("ap-guangzhou")
207222
client := cli.(*TencentCloudClient).apiV3Conn
223+
service := CdnService{client}
208224
continueCode := []string{
209225
// no record
210226
cdn.UNAUTHORIZEDOPERATION_CDNDOMAINRECORDNOTVERIFIED,
@@ -213,16 +229,13 @@ func testAccCdnDomainVerify() error {
213229
}
214230

215231
domainName, err := testAccGetTestingDomain()
216-
l3domain := fmt.Sprintf("c.%s", domainName)
232+
l3domain := fmt.Sprintf("%s.%s", domainPrefix, domainName)
217233

218234
if err != nil {
219235
return err
220236
}
221237

222-
vRequest := cdn.NewVerifyDomainRecordRequest()
223-
vRequest.Domain = &l3domain
224-
225-
vRes, err := client.UseCdnClient().VerifyDomainRecord(vRequest)
238+
result, err := service.VerifyDomainRecord(ctx, l3domain)
226239

227240
if err != nil {
228241

@@ -233,20 +246,18 @@ func testAccCdnDomainVerify() error {
233246
}
234247
}
235248

236-
if vRes.Response != nil && *vRes.Response.Result {
249+
log.Printf("[Precheck] Domain Record Verify: %t", result)
250+
if result {
237251
return nil
238252
}
239253

240-
cRequest := cdn.NewCreateVerifyRecordRequest()
241-
cRequest.Domain = &l3domain
242-
243-
cRes, err := client.UseCdnClient().CreateVerifyRecord(cRequest)
254+
cRes, err := service.CreateVerifyRecord(ctx, l3domain)
244255
if err != nil {
245256
return err
246257
}
247258

248-
recordType := *cRes.Response.RecordType
249-
record := *cRes.Response.Record
259+
recordType := *cRes.RecordType
260+
record := *cRes.Record
250261

251262
err = testAccSetDnsPodRecord(domainName, recordType, record)
252263

@@ -255,11 +266,11 @@ func testAccCdnDomainVerify() error {
255266
}
256267

257268
err = resource.Retry(readRetryTimeout*3, func() *resource.RetryError {
258-
vRes, err = client.UseCdnClient().VerifyDomainRecord(vRequest)
269+
result, err = service.VerifyDomainRecord(ctx, l3domain)
259270
if err != nil {
260271
return retryError(err, continueCode...)
261272
}
262-
if vRes.Response != nil && *vRes.Response.Result {
273+
if result {
263274
return nil
264275
}
265276
return resource.RetryableError(fmt.Errorf("verifying domain, retry"))
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/*
2+
Provide a resource to invoke a Url Purge Request.
3+
4+
Example Usage
5+
6+
```hcl
7+
resource "tencentcloud_cdn_url_purge" "foo" {
8+
urls = [
9+
"https://www.example.com/a"
10+
]
11+
}
12+
```
13+
14+
Change `redo` argument to request new purge task with same urls
15+
16+
```hcl
17+
resource "tencentcloud_cdn_url_purge" "foo" {
18+
urls = [
19+
"https://www.example.com/a"
20+
]
21+
redo = 1
22+
}
23+
```
24+
25+
*/
26+
package tencentcloud
27+
28+
import (
29+
"context"
30+
"fmt"
31+
"log"
32+
33+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
34+
35+
cdn "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn/v20180606"
36+
37+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
38+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper"
39+
)
40+
41+
func resourceTencentCloudUrlPurge() *schema.Resource {
42+
return &schema.Resource{
43+
Read: resourceTencentCloudUrlPurgeRead,
44+
Create: resourceTencentCloudUrlPurgeCreate,
45+
Update: resourceTencentCloudUrlPurgeUpdate,
46+
Delete: resourceTencentCloudUrlPurgeDelete,
47+
Schema: map[string]*schema.Schema{
48+
"urls": {
49+
Type: schema.TypeList,
50+
Required: true,
51+
ForceNew: true,
52+
Elem: &schema.Schema{Type: schema.TypeString},
53+
Description: "List of url to purge. NOTE: urls need include protocol prefix `http://` or `https://`.",
54+
},
55+
"redo": {
56+
Type: schema.TypeInt,
57+
Optional: true,
58+
Description: "Change to purge again. NOTE: this argument only works while resource update, if set to `0` or null will not be triggered.",
59+
},
60+
"area": {
61+
Type: schema.TypeString,
62+
Optional: true,
63+
Description: "Specify purge area. NOTE: only purge same area cache contents.",
64+
},
65+
"url_encode": {
66+
Type: schema.TypeBool,
67+
Optional: true,
68+
Description: "Whether to encode urls, if set to `true` will auto encode instead of manual process.",
69+
},
70+
"task_id": {
71+
Type: schema.TypeString,
72+
Computed: true,
73+
Description: "Task id of last operation.",
74+
},
75+
"purge_history": {
76+
Type: schema.TypeList,
77+
Computed: true,
78+
Description: "logs of latest purge task.",
79+
Elem: &schema.Resource{
80+
Schema: map[string]*schema.Schema{
81+
"task_id": {
82+
Type: schema.TypeString,
83+
Computed: true,
84+
Description: "Purge task id.",
85+
},
86+
"url": {
87+
Type: schema.TypeString,
88+
Computed: true,
89+
Description: "Purge url.",
90+
},
91+
"status": {
92+
Type: schema.TypeString,
93+
Computed: true,
94+
Description: "Purge status of `fail`, `done`, `process`.",
95+
},
96+
"purge_type": {
97+
Type: schema.TypeString,
98+
Computed: true,
99+
Description: "Purge category in of `url` or `path`.",
100+
},
101+
"flush_type": {
102+
Type: schema.TypeString,
103+
Computed: true,
104+
Description: "Purge flush type of `flush` or `delete`.",
105+
},
106+
"create_time": {
107+
Type: schema.TypeString,
108+
Computed: true,
109+
Description: "Purge task create time.",
110+
},
111+
},
112+
},
113+
},
114+
},
115+
}
116+
}
117+
118+
func resourceTencentCloudUrlPurgeRead(d *schema.ResourceData, meta interface{}) error {
119+
defer logElapsed("resource.tencentcloud_cdn_url_purge.read")()
120+
defer inconsistentCheck(d, meta)()
121+
122+
logId := getLogId(contextNil)
123+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
124+
client := meta.(*TencentCloudClient).apiV3Conn
125+
service := CdnService{client}
126+
127+
taskId, ok := d.Get("task_id").(string)
128+
129+
if !ok || taskId == "" {
130+
return fmt.Errorf("no task id provided")
131+
}
132+
133+
request := cdn.NewDescribePurgeTasksRequest()
134+
request.TaskId = &taskId
135+
136+
var (
137+
logs []*cdn.PurgeTask
138+
err error
139+
)
140+
141+
err = resource.Retry(readRetryTimeout*2, func() *resource.RetryError {
142+
logs, err = service.DescribePurgeTasks(ctx, request)
143+
if err != nil {
144+
return retryError(err)
145+
}
146+
if len(logs) == 0 {
147+
return resource.RetryableError(fmt.Errorf("task %s returns nil logs, retrying", taskId))
148+
}
149+
for i := range logs {
150+
item := logs[i]
151+
status := item.Status
152+
if status == nil {
153+
continue
154+
}
155+
switch *status {
156+
case "process":
157+
return resource.RetryableError(fmt.Errorf("processing %s", *item.Url))
158+
case "fail":
159+
return resource.NonRetryableError(fmt.Errorf("purge url %s failed", *item.Url))
160+
default:
161+
continue
162+
}
163+
}
164+
return nil
165+
})
166+
167+
if err != nil {
168+
return err
169+
}
170+
171+
urls := d.Get("urls").([]interface{})
172+
d.SetId("purges-" + GetUrlsHash(helper.InterfacesStrings(urls)))
173+
174+
purgeHistory := make([]interface{}, 0)
175+
176+
if len(logs) > 0 {
177+
for i := range logs {
178+
item := logs[i]
179+
purge := map[string]interface{}{
180+
"task_id": item.TaskId,
181+
"url": item.Url,
182+
"create_time": item.CreateTime,
183+
"status": item.Status,
184+
"purge_type": item.PurgeType,
185+
"flush_type": item.FlushType,
186+
}
187+
purgeHistory = append(purgeHistory, purge)
188+
}
189+
}
190+
191+
_ = d.Set("purge_history", purgeHistory)
192+
193+
return nil
194+
}
195+
196+
func resourceTencentCloudUrlPurgeCreate(d *schema.ResourceData, meta interface{}) error {
197+
defer logElapsed("resource.tencentcloud_cdn_url_purge.create")()
198+
199+
taskId, err := tencentcloudCdnUrlPurge(d, meta)
200+
201+
if err != nil {
202+
return err
203+
}
204+
205+
_ = d.Set("task_id", taskId)
206+
207+
urls := d.Get("urls").([]interface{})
208+
d.SetId("purges-" + GetUrlsHash(helper.InterfacesStrings(urls)))
209+
210+
return resourceTencentCloudUrlPurgeRead(d, meta)
211+
}
212+
213+
func resourceTencentCloudUrlPurgeUpdate(d *schema.ResourceData, meta interface{}) error {
214+
defer logElapsed("resource.tencentcloud_cdn_url_purge.update")()
215+
216+
redo, ok := d.GetOk("redo")
217+
218+
if !d.HasChange("redo") || !ok || redo.(int) == 0 {
219+
return nil
220+
}
221+
222+
taskId, err := tencentcloudCdnUrlPurge(d, meta)
223+
224+
if err != nil {
225+
return err
226+
}
227+
228+
_ = d.Set("task_id", taskId)
229+
230+
return resourceTencentCloudUrlPurgeRead(d, meta)
231+
}
232+
233+
func resourceTencentCloudUrlPurgeDelete(d *schema.ResourceData, meta interface{}) error {
234+
defer logElapsed("resource.tencentcloud_cdn_url_purge.delete")()
235+
log.Printf("noop deleting resoruce %s", "tencentcloud_cdn_url_purge")
236+
return nil
237+
}
238+
239+
func tencentcloudCdnUrlPurge(d *schema.ResourceData, meta interface{}) (string, error) {
240+
logId := getLogId(contextNil)
241+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
242+
243+
client := meta.(*TencentCloudClient).apiV3Conn
244+
service := CdnService{client}
245+
246+
urls := d.Get("urls").([]interface{})
247+
request := cdn.NewPurgeUrlsCacheRequest()
248+
request.Urls = helper.InterfacesStringsPoint(urls)
249+
250+
if v, ok := d.GetOk("area"); ok {
251+
request.Area = helper.String(v.(string))
252+
}
253+
254+
if v, ok := d.GetOk("url_encode"); ok {
255+
request.UrlEncode = helper.Bool(v.(bool))
256+
}
257+
258+
return service.PurgeUrlsCache(ctx, request)
259+
}

0 commit comments

Comments
 (0)