@@ -14,6 +14,21 @@ resource "tencentcloud_tcr_instance" "foo" {
1414}
1515```
1616
17+ Using public network access whitelist
18+ ```
19+ resource "tencentcloud_tcr_instance" "foo" {
20+ name = "example"
21+ instance_type = "basic"
22+ open_public_operation = true
23+ security_poicy {
24+ cidr_block = "10.0.0.1/24"
25+ }
26+ security_policy {
27+ cidr_block = "192.168.1.1"
28+ }
29+ }
30+ ```
31+
1732Import
1833
1934tcr instance can be imported using the id, e.g.
@@ -27,18 +42,19 @@ package tencentcloud
2742import (
2843 "context"
2944 "fmt"
30-
3145 "github.com/hashicorp/terraform-plugin-sdk/helper/resource"
3246 "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
47+ tcr "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcr/v20190924"
3348 "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper"
49+ "log"
3450)
3551
3652func resourceTencentCloudTcrInstance () * schema.Resource {
3753 return & schema.Resource {
3854 Create : resourceTencentCloudTcrInstanceCreate ,
3955 Read : resourceTencentCloudTcrInstanceRead ,
4056 Update : resourceTencentCloudTcrInstanceUpdate ,
41- Delete : resourceTencentCLoudTcrInstanceDelete ,
57+ Delete : resourceTencentCloudTcrInstanceDelete ,
4258 Importer : & schema.ResourceImporter {
4359 State : schema .ImportStatePassthrough ,
4460 },
@@ -67,6 +83,35 @@ func resourceTencentCloudTcrInstance() *schema.Resource {
6783 Default : false ,
6884 Description : "Control public network access." ,
6985 },
86+ "security_policy" : {
87+ Type : schema .TypeSet ,
88+ Optional : true ,
89+ Description : "Public network access allowlist policies of the TCR instance. Only available when `open_public_operation` is `true`." ,
90+ Elem : & schema.Resource {
91+ Schema : map [string ]* schema.Schema {
92+ "cidr_block" : {
93+ Type : schema .TypeString ,
94+ Optional : true ,
95+ Description : "The public network IP address of the access source." ,
96+ },
97+ "description" : {
98+ Type : schema .TypeString ,
99+ Optional : true ,
100+ Description : "Remarks of policy." ,
101+ },
102+ "index" : {
103+ Type : schema .TypeInt ,
104+ Computed : true ,
105+ Description : "Index of policy." ,
106+ },
107+ "version" : {
108+ Type : schema .TypeString ,
109+ Computed : true ,
110+ Description : "Version of policy." ,
111+ },
112+ },
113+ },
114+ },
70115 //Computed values
71116 "status" : {
72117 Type : schema .TypeString ,
@@ -104,17 +149,23 @@ func resourceTencentCloudTcrInstanceCreate(d *schema.ResourceData, meta interfac
104149 logId := getLogId (contextNil )
105150 ctx := context .WithValue (context .TODO (), logIdKey , logId )
106151
107- tcrService := TCRService {client : meta .(* TencentCloudClient ).apiV3Conn }
152+ client := meta .(* TencentCloudClient ).apiV3Conn
153+ tcrService := TCRService {client : client }
108154
109155 var (
110156 name = d .Get ("name" ).(string )
111157 insType = d .Get ("instance_type" ).(string )
112158 outErr , inErr error
113159 instanceId string
114160 instanceStatus string
115- operation bool
161+ operation = d . Get ( "open_public_operation" ).( bool )
116162 )
117163
164+ // Check if security_policy but open_public_operation is false
165+ if _ , ok := d .GetOk ("security_policy" ); ok && ! operation {
166+ return fmt .Errorf ("`open_public_operation` must be `true` if `security_policy` set" )
167+ }
168+
118169 outErr = resource .Retry (writeRetryTimeout , func () * resource.RetryError {
119170 instanceId , inErr = tcrService .CreateTCRInstance (ctx , name , insType , map [string ]string {})
120171 if inErr != nil {
@@ -147,9 +198,11 @@ func resourceTencentCloudTcrInstanceCreate(d *schema.ResourceData, meta interfac
147198 return err
148199 }
149200 if instanceStatus == "Running" {
201+ openPublicOperation , ok := d .GetOk ("open_public_operation" )
202+ operation = openPublicOperation .(bool )
203+
150204 outErr = resource .Retry (writeRetryTimeout , func () * resource.RetryError {
151- if v , ok := d .GetOk ("open_public_operation" ); ok {
152- operation = v .(bool )
205+ if ok {
153206 if operation {
154207 inErr = tcrService .ManageTCRExternalEndpoint (ctx , instanceId , "Create" )
155208 } else {
@@ -164,6 +217,38 @@ func resourceTencentCloudTcrInstanceCreate(d *schema.ResourceData, meta interfac
164217 if outErr != nil {
165218 return outErr
166219 }
220+
221+ if raw , ok := d .GetOk ("security_policy" ); ok && operation {
222+ // Waiting for External EndPoint opened
223+ err = resource .Retry (5 * readRetryTimeout , func () * resource.RetryError {
224+ var (
225+ status string
226+ )
227+ status , _ , err = tcrService .DescribeExternalEndpointStatus (ctx , instanceId )
228+ if err != nil {
229+ return resource .NonRetryableError (fmt .Errorf ("an error occured during DescribeExternalEndpointStatus: %s" , err .Error ()))
230+ }
231+
232+ if status == "Opened" {
233+ return nil
234+ }
235+
236+ if status == "Opening" {
237+ return resource .RetryableError (fmt .Errorf ("external endpoint status is `%s`, retrying" , status ))
238+ }
239+
240+ return resource .NonRetryableError (fmt .Errorf ("unexpected external endpoint status: `%s`" , status ))
241+ })
242+
243+ if err != nil {
244+ return err
245+ }
246+ if err := resourceTencentCloudTcrSecurityPolicyAdd (d , meta , raw .(* schema.Set ).List ()); err != nil {
247+ return err
248+ }
249+ } else if ! operation {
250+ log .Printf ("[WARN] `open_public_operation` was not opened, skip `security_policy` set." )
251+ }
167252 }
168253
169254 if tags := helper .GetTags (d , "tags" ); len (tags ) > 0 {
@@ -185,7 +270,8 @@ func resourceTencentCloudTcrInstanceRead(d *schema.ResourceData, meta interface{
185270 ctx := context .WithValue (context .TODO (), logIdKey , logId )
186271
187272 var outErr , inErr error
188- tcrService := TCRService {client : meta .(* TencentCloudClient ).apiV3Conn }
273+ client := meta .(* TencentCloudClient ).apiV3Conn
274+ tcrService := TCRService {client : client }
189275 instance , has , outErr := tcrService .DescribeTCRInstanceById (ctx , d .Id ())
190276 if outErr != nil {
191277 outErr = resource .Retry (readRetryTimeout , func () * resource.RetryError {
@@ -234,6 +320,31 @@ func resourceTencentCloudTcrInstanceRead(d *schema.ResourceData, meta interface{
234320 _ = d .Set ("internal_end_point" , instance .InternalEndpoint )
235321 _ = d .Set ("public_status" , publicStatus )
236322
323+ request := tcr .NewDescribeSecurityPoliciesRequest ()
324+ request .RegistryId = helper .String (d .Id ())
325+ response , err := client .UseTCRClient ().DescribeSecurityPolicies (request )
326+ if err == nil {
327+ if response .Response .SecurityPolicySet != nil {
328+ securityPolicySet := response .Response .SecurityPolicySet
329+ policies := make ([]interface {}, 0 , len (securityPolicySet ))
330+ for i := range securityPolicySet {
331+ item := securityPolicySet [i ]
332+ policy := make (map [string ]interface {})
333+ policy ["cidr_block" ] = * item .CidrBlock
334+ policy ["description" ] = * item .Description
335+ policy ["index" ] = * item .PolicyIndex
336+ policy ["version" ] = * item .PolicyVersion
337+ policies = append (policies , policy )
338+ }
339+ if err := d .Set ("security_policy" , policies ); err != nil {
340+ return err
341+ }
342+ }
343+ } else {
344+ _ = d .Set ("security_policy" , make ([]interface {}, 0 ))
345+ log .Printf ("[WARN] %s error: %s" , request .GetAction (), err .Error ())
346+ }
347+
237348 tags := make (map [string ]string , len (instance .TagSpecification .Tags ))
238349 for _ , tag := range instance .TagSpecification .Tags {
239350 tags [* tag .Key ] = * tag .Value
@@ -259,16 +370,13 @@ func resourceTencentCloudTcrInstanceUpdate(d *schema.ResourceData, meta interfac
259370 if d .HasChange ("open_public_operation" ) {
260371 operation = d .Get ("open_public_operation" ).(bool )
261372 outErr = resource .Retry (writeRetryTimeout , func () * resource.RetryError {
262- if v , ok := d .GetOk ("open_public_operation" ); ok {
263- operation = v .(bool )
264- if operation {
265- inErr = tcrService .ManageTCRExternalEndpoint (ctx , instanceId , "Create" )
266- } else {
267- inErr = tcrService .ManageTCRExternalEndpoint (ctx , instanceId , "Delete" )
268- }
269- if inErr != nil {
270- return retryError (inErr )
271- }
373+ if operation {
374+ inErr = tcrService .ManageTCRExternalEndpoint (ctx , instanceId , "Create" )
375+ } else {
376+ inErr = tcrService .ManageTCRExternalEndpoint (ctx , instanceId , "Delete" )
377+ }
378+ if inErr != nil {
379+ return retryError (inErr )
272380 }
273381 return nil
274382 })
@@ -277,6 +385,53 @@ func resourceTencentCloudTcrInstanceUpdate(d *schema.ResourceData, meta interfac
277385 }
278386 }
279387
388+ if d .HasChange ("security_policy" ) {
389+ var err error
390+ // Waiting for External EndPoint opened
391+ err = resource .Retry (5 * readRetryTimeout , func () * resource.RetryError {
392+ var (
393+ status string
394+ )
395+ status , _ , err = tcrService .DescribeExternalEndpointStatus (ctx , instanceId )
396+ if err != nil {
397+ return resource .NonRetryableError (fmt .Errorf ("an error occured during DescribeExternalEndpointStatus: %s" , err .Error ()))
398+ }
399+
400+ if status == "Opened" {
401+ return nil
402+ }
403+
404+ if status == "Opening" {
405+ return resource .RetryableError (fmt .Errorf ("external endpoint status is `%s`, retrying" , status ))
406+ }
407+
408+ return resource .NonRetryableError (fmt .Errorf ("unexpected external endpoint status: `%s`" , status ))
409+ })
410+
411+ if err != nil {
412+ return err
413+ }
414+
415+ o , n := d .GetChange ("security_policy" )
416+ os := o .(* schema.Set )
417+ ns := n .(* schema.Set )
418+ add := ns .Difference (os ).List ()
419+ remove := os .Difference (ns ).List ()
420+ if len (remove ) > 0 {
421+ err := resourceTencentCloudTcrSecurityPolicyRemove (d , meta , remove )
422+ if err != nil {
423+ return err
424+ }
425+ }
426+ if len (add ) > 0 {
427+ err := resourceTencentCloudTcrSecurityPolicyAdd (d , meta , add )
428+ if err != nil {
429+ return err
430+ }
431+ }
432+ d .SetPartial ("security_policy" )
433+ }
434+
280435 if d .HasChange ("tags" ) {
281436 oldTags , newTags := d .GetChange ("tags" )
282437 replaceTags , deleteTags := diffTags (oldTags .(map [string ]interface {}), newTags .(map [string ]interface {}))
@@ -292,7 +447,7 @@ func resourceTencentCloudTcrInstanceUpdate(d *schema.ResourceData, meta interfac
292447 return resourceTencentCloudTcrInstanceRead (d , meta )
293448}
294449
295- func resourceTencentCLoudTcrInstanceDelete (d * schema.ResourceData , meta interface {}) error {
450+ func resourceTencentCloudTcrInstanceDelete (d * schema.ResourceData , meta interface {}) error {
296451 defer logElapsed ("resource.tencentcloud_tcr_instance.delete" )()
297452
298453 logId := getLogId (contextNil )
@@ -338,3 +493,63 @@ func resourceTencentCLoudTcrInstanceDelete(d *schema.ResourceData, meta interfac
338493
339494 return nil
340495}
496+
497+ func resourceTencentCloudTcrSecurityPolicyAdd (d * schema.ResourceData , meta interface {}, add []interface {}) error {
498+ client := meta .(* TencentCloudClient ).apiV3Conn
499+ request := tcr .NewCreateMultipleSecurityPolicyRequest ()
500+ request .RegistryId = helper .String (d .Id ())
501+
502+ for _ , i := range add {
503+ dMap := i .(map [string ]interface {})
504+ policy := & tcr.SecurityPolicy {}
505+ if cidr , ok := dMap ["cidr_block" ]; ok {
506+ policy .CidrBlock = helper .String (cidr .(string ))
507+ }
508+ if desc , ok := dMap ["description" ]; ok {
509+ policy .Description = helper .String (desc .(string ))
510+ }
511+ if index , ok := dMap ["index" ]; ok {
512+ policy .PolicyIndex = helper .IntInt64 (index .(int ))
513+ }
514+ if version , ok := dMap ["version" ]; ok {
515+ policy .PolicyVersion = helper .String (version .(string ))
516+ }
517+ request .SecurityGroupPolicySet = append (request .SecurityGroupPolicySet , policy )
518+ }
519+
520+ _ , err := client .UseTCRClient ().CreateMultipleSecurityPolicy (request )
521+ if err != nil {
522+ return err
523+ }
524+ return nil
525+ }
526+
527+ func resourceTencentCloudTcrSecurityPolicyRemove (d * schema.ResourceData , meta interface {}, remove []interface {}) error {
528+ client := meta .(* TencentCloudClient ).apiV3Conn
529+ request := tcr .NewDeleteMultipleSecurityPolicyRequest ()
530+ request .RegistryId = helper .String (d .Id ())
531+
532+ for _ , i := range remove {
533+ dMap := i .(map [string ]interface {})
534+ policy := & tcr.SecurityPolicy {}
535+ if cidr , ok := dMap ["cidr_block" ]; ok {
536+ policy .CidrBlock = helper .String (cidr .(string ))
537+ }
538+ if desc , ok := dMap ["description" ]; ok {
539+ policy .Description = helper .String (desc .(string ))
540+ }
541+ if index , ok := dMap ["index" ]; ok {
542+ policy .PolicyIndex = helper .IntInt64 (index .(int ))
543+ }
544+ if version , ok := dMap ["version" ]; ok {
545+ policy .PolicyVersion = helper .String (version .(string ))
546+ }
547+ request .SecurityGroupPolicySet = append (request .SecurityGroupPolicySet , policy )
548+ }
549+
550+ _ , err := client .UseTCRClient ().DeleteMultipleSecurityPolicy (request )
551+ if err != nil {
552+ return err
553+ }
554+ return nil
555+ }
0 commit comments