@@ -133,6 +133,28 @@ resource "tencentcloud_cos_bucket" "with_origin" {
133133}
134134```
135135
136+ Using replication
137+ ```hcl
138+ resource "tencentcloud_cos_bucket" "replica1" {
139+ bucket = "tf-replica-foo-1234567890"
140+ acl = "private"
141+ versioning_enable = true
142+ }
143+
144+ resource "tencentcloud_cos_bucket" "with_replication" {
145+ bucket = "tf-bucket-replica-1234567890"
146+ acl = "private"
147+ versioning_enable = true
148+ replica_role = "qcs::cam::uin/100000000001:uin/100000000001"
149+ replica_rules {
150+ id = "test-rep1"
151+ status = "Enabled"
152+ prefix = "dist"
153+ destination_bucket = "qcs::cos:%s::${tencentcloud_cos_bucket.replica1.bucket}"
154+ }
155+ }
156+ ```
157+
136158Setting log status
137159
138160```hcl
@@ -385,6 +407,47 @@ func resourceTencentCloudCosBucket() *schema.Resource {
385407 Default : false ,
386408 Description : "Enable bucket versioning." ,
387409 },
410+ "replica_role" : {
411+ Type : schema .TypeString ,
412+ Optional : true ,
413+ RequiredWith : []string {"replica_rules" , "versioning_enable" },
414+ Description : "Request initiator identifier, format: `qcs::cam::uin/<owneruin>:uin/<subuin>`. NOTE: only `versioning_enable` is true can configure this argument." ,
415+ },
416+ "replica_rules" : {
417+ Type : schema .TypeList ,
418+ Optional : true ,
419+ Description : "List of replica rule. NOTE: only `versioning_enable` is true and `replica_role` set can configure this argument." ,
420+ RequiredWith : []string {"replica_role" , "versioning_enable" },
421+ Elem : & schema.Resource {
422+ Schema : map [string ]* schema.Schema {
423+ "id" : {
424+ Type : schema .TypeString ,
425+ Optional : true ,
426+ Description : "Name of a specific rule." ,
427+ },
428+ "status" : {
429+ Type : schema .TypeString ,
430+ Required : true ,
431+ Description : "Status identifier, available values: `Enabled`, `Disabled`." ,
432+ },
433+ "prefix" : {
434+ Type : schema .TypeString ,
435+ Optional : true ,
436+ Description : "Prefix matching policy. Policies cannot overlap; otherwise, an error will be returned. To match the root directory, leave this parameter empty." ,
437+ },
438+ "destination_bucket" : {
439+ Type : schema .TypeString ,
440+ Required : true ,
441+ Description : "Destination bucket identifier, format: `qcs::cos:<region>::<bucketname-appid>`. NOTE: destination bucket must enable versioning." ,
442+ },
443+ "destination_storage_class" : {
444+ Type : schema .TypeString ,
445+ Optional : true ,
446+ Description : "Storage class of destination, available values: `STANDARD`, `INTELLIGENT_TIERING`, `STANDARD_IA`. default is following current class of destination." ,
447+ },
448+ },
449+ },
450+ },
388451 "cors_rules" : {
389452 Type : schema .TypeList ,
390453 Optional : true ,
@@ -569,18 +632,18 @@ func resourceTencentCloudCosBucket() *schema.Resource {
569632 Computed : true ,
570633 Description : "The prefix log name which saves the access log of this bucket per 5 minutes. Eg. `MyLogPrefix/`. The log access file format is `log_target_bucket`/`log_prefix`{YYYY}/{MM}/{DD}/{time}_{random}_{index}.gz. Only valid when `log_enable` is `true`." ,
571634 },
572- //computed
573- "cos_bucket_url" : {
574- Type : schema .TypeString ,
575- Computed : true ,
576- Description : "The URL of this cos bucket." ,
577- },
578635 "multi_az" : {
579636 Type : schema .TypeBool ,
580637 Optional : true ,
581638 ForceNew : true ,
582639 Description : "Indicates whether to create a bucket of multi available zone." ,
583640 },
641+ //computed
642+ "cos_bucket_url" : {
643+ Type : schema .TypeString ,
644+ Computed : true ,
645+ Description : "The URL of this cos bucket." ,
646+ },
584647 },
585648 }
586649}
@@ -595,6 +658,17 @@ func resourceTencentCloudCosBucketCreate(d *schema.ResourceData, meta interface{
595658
596659 bucket := d .Get ("bucket" ).(string )
597660 acl := d .Get ("acl" ).(string )
661+ role , roleOk := d .GetOk ("replica_role" )
662+ rule , ruleOk := d .GetOk ("replica_rules" )
663+ versioning , versioningOk := d .GetOk ("versioning_enable" )
664+
665+ if v := versioning .(bool ); ! versioningOk || ! v {
666+ if roleOk || role .(string ) != "" {
667+ return fmt .Errorf ("cannot configure role unless versioning enable" )
668+ } else if ruleOk || len (rule .([]interface {})) > 0 {
669+ return fmt .Errorf ("cannot configure replica rule unless versioning enable" )
670+ }
671+ }
598672
599673 cosService := CosService {client : meta .(* TencentCloudClient ).apiV3Conn }
600674
@@ -713,6 +787,18 @@ func resourceTencentCloudCosBucketRead(d *schema.ResourceData, meta interface{})
713787 return fmt .Errorf ("setting versioning_enable error: %v" , err )
714788 }
715789
790+ replicaResult , err := cosService .GetBucketReplication (ctx , bucket )
791+ if err != nil {
792+ return err
793+ }
794+
795+ if replicaResult != nil {
796+ err := setBucketReplication (d , * replicaResult )
797+ if err != nil {
798+ return err
799+ }
800+ }
801+
716802 //read the log
717803 logEnable , logTargetBucket , logPrefix , err := cosService .GetBucketLogStatus (ctx , bucket )
718804 if err != nil {
@@ -823,6 +909,14 @@ func resourceTencentCloudCosBucketUpdate(d *schema.ResourceData, meta interface{
823909 d .SetPartial ("versioning_enable" )
824910 }
825911
912+ if d .HasChange ("replica_role" ) || d .HasChange ("replica_rules" ) {
913+ err := resourceTencentCloudCosBucketReplicaUpdate (ctx , cosService , d )
914+
915+ if err != nil {
916+ return err
917+ }
918+ }
919+
826920 if d .HasChange ("tags" ) {
827921 bucket := d .Id ()
828922
@@ -949,6 +1043,40 @@ func resourceTencentCloudCosBucketVersioningUpdate(ctx context.Context, client *
9491043 return nil
9501044}
9511045
1046+ func resourceTencentCloudCosBucketReplicaUpdate (ctx context.Context , service CosService , d * schema.ResourceData ) error {
1047+ bucket := d .Get ("bucket" ).(string )
1048+ oldRole , newRole := d .GetChange ("replica_role" )
1049+ oldRules , newRules := d .GetChange ("replica_rules" )
1050+ oldRuleLength := len (oldRules .([]interface {}))
1051+ newRuleLength := len (newRules .([]interface {}))
1052+
1053+ // check if remove
1054+ if oldRole .(string ) != "" && newRole .(string ) == "" || oldRuleLength > 0 && newRuleLength == 0 {
1055+ result , err := service .GetBucketReplication (ctx , bucket )
1056+ if err != nil {
1057+ return err
1058+ }
1059+
1060+ if result != nil {
1061+ err := service .DeleteBucketReplication (ctx , d .Get ("bucket" ).(string ))
1062+ if err != nil {
1063+ return err
1064+ }
1065+ }
1066+ } else if newRole .(string ) != "" || newRuleLength > 0 {
1067+ role , rules , _ := getBucketReplications (d )
1068+ err := service .PutBucketReplication (ctx , d .Get ("bucket" ).(string ), role , rules )
1069+ if err != nil {
1070+ return err
1071+ }
1072+ }
1073+
1074+ d .SetPartial ("replica_role" )
1075+ d .SetPartial ("replica_rules" )
1076+
1077+ return nil
1078+ }
1079+
9521080func resourceTencentCloudCosBucketAclUpdate (ctx context.Context , client * s3.S3 , d * schema.ResourceData ) error {
9531081 logId := getLogId (ctx )
9541082
@@ -1471,3 +1599,54 @@ func transitionHash(v interface{}) int {
14711599 }
14721600 return hashcode .String (buf .String ())
14731601}
1602+
1603+ func getBucketReplications (d * schema.ResourceData ) (role string , rules []cos.BucketReplicationRule , err error ) {
1604+ role = d .Get ("replica_role" ).(string )
1605+ replicaRules := d .Get ("replica_rules" ).([]interface {})
1606+ for i := range replicaRules {
1607+ item := replicaRules [i ].(map [string ]interface {})
1608+ rule := cos.BucketReplicationRule {
1609+ Status : item ["status" ].(string ),
1610+ Destination : & cos.ReplicationDestination {
1611+ Bucket : item ["destination_bucket" ].(string ),
1612+ },
1613+ }
1614+ if v , ok := item ["prefix" ].(string ); ok {
1615+ rule .Prefix = v
1616+ }
1617+ if v , ok := item ["id" ].(string ); ok {
1618+ rule .ID = v
1619+ }
1620+ if v , ok := item ["destination_storage_class" ].(string ); ok {
1621+ rule .Destination .StorageClass = v
1622+ }
1623+ rules = append (rules , rule )
1624+ }
1625+ return
1626+ }
1627+
1628+ func setBucketReplication (d * schema.ResourceData , result cos.GetBucketReplicationResult ) (err error ) {
1629+ if result .Role != "" {
1630+ err = d .Set ("replica_role" , result .Role )
1631+ }
1632+ rules := make ([]map [string ]interface {}, 0 )
1633+ if len (result .Rule ) > 0 {
1634+ for i := range result .Rule {
1635+ item := result .Rule [i ]
1636+ rule := map [string ]interface {}{
1637+ "status" : item .Status ,
1638+ "destination_bucket" : item .Destination .Bucket ,
1639+ "destination_storage_class" : item .Destination .StorageClass ,
1640+ }
1641+ if item .ID != "" {
1642+ rule ["id" ] = item .ID
1643+ }
1644+ if item .Prefix != "" {
1645+ rule ["prefix" ] = item .Prefix
1646+ }
1647+ rules = append (rules , rule )
1648+ }
1649+ }
1650+ err = d .Set ("replica_rules" , rules )
1651+ return
1652+ }
0 commit comments