Skip to content

Commit f2fe4b1

Browse files
Adds support for Soft Delete feature, which allows setting soft delete policy on 'google_storage_bucket' resource. (#10171) (#7119)
[upstream:3b9c61bd50c271e769a6cb81dbd28d5ba7512c15] Signed-off-by: Modular Magician <[email protected]>
1 parent 4b10bcf commit f2fe4b1

File tree

4 files changed

+146
-0
lines changed

4 files changed

+146
-0
lines changed

.changelog/10171.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note: enhancement
2+
storage: added 'soft_delete_policy' to 'google_storage_bucket' resource
3+
```

google-beta/services/storage/resource_storage_bucket.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,28 @@ func ResourceStorageBucket() *schema.Resource {
483483
Computed: true,
484484
Description: `Prevents public access to a bucket.`,
485485
},
486+
"soft_delete_policy": {
487+
Type: schema.TypeList,
488+
MaxItems: 1,
489+
Optional: true,
490+
Computed: true,
491+
Description: `The bucket's soft delete policy, which defines the period of time that soft-deleted objects will be retained, and cannot be permanently deleted. If it is not provided, by default Google Cloud Storage sets this to default soft delete policy`,
492+
Elem: &schema.Resource{
493+
Schema: map[string]*schema.Schema{
494+
"retention_duration_seconds": {
495+
Type: schema.TypeInt,
496+
Default: 604800,
497+
Optional: true,
498+
Description: `The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Default value is 604800.`,
499+
},
500+
"effective_time": {
501+
Type: schema.TypeString,
502+
Computed: true,
503+
Description: `Server-determined value that indicates the time from which the policy, or one with a greater retention, was effective. This value is in RFC 3339 format.`,
504+
},
505+
},
506+
},
507+
},
486508
},
487509
UseJSONNumber: true,
488510
}
@@ -613,6 +635,10 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error
613635
sb.Rpo = v.(string)
614636
}
615637

638+
if v, ok := d.GetOk("soft_delete_policy"); ok {
639+
sb.SoftDeletePolicy = expandBucketSoftDeletePolicy(v.([]interface{}))
640+
}
641+
616642
var res *storage.Bucket
617643

618644
err = transport_tpg.Retry(transport_tpg.RetryOptions{
@@ -785,6 +811,12 @@ func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error
785811
}
786812
}
787813

814+
if d.HasChange("soft_delete_policy") {
815+
if v, ok := d.GetOk("soft_delete_policy"); ok {
816+
sb.SoftDeletePolicy = expandBucketSoftDeletePolicy(v.([]interface{}))
817+
}
818+
}
819+
788820
res, err := config.NewStorageClient(userAgent).Buckets.Patch(d.Get("name").(string), sb).Do()
789821
if err != nil {
790822
return err
@@ -1167,6 +1199,32 @@ func flattenBucketObjectRetention(bucketObjectRetention *storage.BucketObjectRet
11671199
return false
11681200
}
11691201

1202+
func expandBucketSoftDeletePolicy(configured interface{}) *storage.BucketSoftDeletePolicy {
1203+
configuredSoftDeletePolicies := configured.([]interface{})
1204+
if len(configuredSoftDeletePolicies) == 0 {
1205+
return nil
1206+
}
1207+
configuredSoftDeletePolicy := configuredSoftDeletePolicies[0].(map[string]interface{})
1208+
softDeletePolicy := &storage.BucketSoftDeletePolicy{
1209+
RetentionDurationSeconds: int64(configuredSoftDeletePolicy["retention_duration_seconds"].(int)),
1210+
}
1211+
softDeletePolicy.ForceSendFields = append(softDeletePolicy.ForceSendFields, "RetentionDurationSeconds")
1212+
return softDeletePolicy
1213+
}
1214+
1215+
func flattenBucketSoftDeletePolicy(softDeletePolicy *storage.BucketSoftDeletePolicy) []map[string]interface{} {
1216+
policies := make([]map[string]interface{}, 0, 1)
1217+
if softDeletePolicy == nil {
1218+
return policies
1219+
}
1220+
policy := map[string]interface{}{
1221+
"retention_duration_seconds": softDeletePolicy.RetentionDurationSeconds,
1222+
"effective_time": softDeletePolicy.EffectiveTime,
1223+
}
1224+
policies = append(policies, policy)
1225+
return policies
1226+
}
1227+
11701228
func expandBucketVersioning(configured interface{}) *storage.BucketVersioning {
11711229
versionings := configured.([]interface{})
11721230
if len(versionings) == 0 {
@@ -1718,6 +1776,9 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res
17181776
return fmt.Errorf("Error setting RPO setting : %s", err)
17191777
}
17201778
}
1779+
if err := d.Set("soft_delete_policy", flattenBucketSoftDeletePolicy(res.SoftDeletePolicy)); err != nil {
1780+
return fmt.Errorf("Error setting soft_delete_policy: %s", err)
1781+
}
17211782
if res.IamConfiguration != nil && res.IamConfiguration.UniformBucketLevelAccess != nil {
17221783
if err := d.Set("uniform_bucket_level_access", res.IamConfiguration.UniformBucketLevelAccess.Enabled); err != nil {
17231784
return fmt.Errorf("Error setting uniform_bucket_level_access: %s", err)

google-beta/services/storage/resource_storage_bucket_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,66 @@ func TestAccStorageBucket_retentionPolicyLocked(t *testing.T) {
13391339
})
13401340
}
13411341

1342+
func TestAccStorageBucket_SoftDeletePolicy(t *testing.T) {
1343+
t.Parallel()
1344+
1345+
var bucket storage.Bucket
1346+
bucketName := fmt.Sprintf("tf-test-acc-bucket-%d", acctest.RandInt(t))
1347+
1348+
acctest.VcrTest(t, resource.TestCase{
1349+
PreCheck: func() { acctest.AccTestPreCheck(t) },
1350+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
1351+
CheckDestroy: testAccStorageBucketDestroyProducer(t),
1352+
Steps: []resource.TestStep{
1353+
{
1354+
Config: testAccStorageBucket_basic(bucketName),
1355+
Check: resource.ComposeTestCheckFunc(
1356+
testAccCheckStorageBucketExists(
1357+
t, "google_storage_bucket.bucket", bucketName, &bucket),
1358+
resource.TestCheckResourceAttr(
1359+
"google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "604800"),
1360+
),
1361+
},
1362+
{
1363+
ResourceName: "google_storage_bucket.bucket",
1364+
ImportState: true,
1365+
ImportStateVerify: true,
1366+
ImportStateVerifyIgnore: []string{"force_destroy"},
1367+
},
1368+
{
1369+
Config: testAccStorageBucket_SoftDeletePolicy(bucketName, 7776000),
1370+
Check: resource.ComposeTestCheckFunc(
1371+
testAccCheckStorageBucketExists(
1372+
t, "google_storage_bucket.bucket", bucketName, &bucket),
1373+
resource.TestCheckResourceAttr(
1374+
"google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "7776000"),
1375+
),
1376+
},
1377+
{
1378+
ResourceName: "google_storage_bucket.bucket",
1379+
ImportState: true,
1380+
ImportStateVerify: true,
1381+
ImportStateVerifyIgnore: []string{"force_destroy"},
1382+
},
1383+
{
1384+
Config: testAccStorageBucket_SoftDeletePolicy(bucketName, 0),
1385+
Check: resource.ComposeTestCheckFunc(
1386+
testAccCheckStorageBucketExists(
1387+
t, "google_storage_bucket.bucket", bucketName, &bucket),
1388+
resource.TestCheckResourceAttr(
1389+
"google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "0"),
1390+
),
1391+
},
1392+
{
1393+
ResourceName: "google_storage_bucket.bucket",
1394+
ImportState: true,
1395+
ImportStateVerify: true,
1396+
ImportStateVerifyIgnore: []string{"force_destroy"},
1397+
},
1398+
},
1399+
})
1400+
}
1401+
13421402
func testAccCheckStorageBucketExists(t *testing.T, n string, bucketName string, bucket *storage.Bucket) resource.TestCheckFunc {
13431403
return func(s *terraform.State) error {
13441404
rs, ok := s.RootModule().Resources[n]
@@ -2265,6 +2325,20 @@ resource "google_storage_bucket" "bucket" {
22652325
`, bucketName)
22662326
}
22672327

2328+
func testAccStorageBucket_SoftDeletePolicy(bucketName string, duration int) string {
2329+
return fmt.Sprintf(`
2330+
resource "google_storage_bucket" "bucket" {
2331+
name = "%s"
2332+
location = "US"
2333+
force_destroy = true
2334+
2335+
soft_delete_policy {
2336+
retention_duration_seconds = %d
2337+
}
2338+
}
2339+
`, bucketName, duration)
2340+
}
2341+
22682342
func testAccStorageBucket_websiteNoAttributes(bucketName string) string {
22692343
return fmt.Sprintf(`
22702344
resource "google_storage_bucket" "website" {

website/docs/r/storage_bucket.html.markdown

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ The following arguments are supported:
133133

134134
* `custom_placement_config` - (Optional) The bucket's custom location configuration, which specifies the individual regions that comprise a dual-region bucket. If the bucket is designated a single or multi-region, the parameters are empty. Structure is [documented below](#nested_custom_placement_config).
135135

136+
* `soft_delete_policy` - (Optional, Computed) The bucket's soft delete policy, which defines the period of time that soft-deleted objects will be retained, and cannot be permanently deleted. If the block is not provided, Server side value will be kept which means removal of block won't generate any terraform change. Structure is [documented below](#nested_soft_delete_policy).
137+
136138
<a name="nested_lifecycle_rule"></a>The `lifecycle_rule` block supports:
137139

138140
* `action` - (Required) The Lifecycle Rule's action configuration. A single block of this type is supported. Structure is [documented below](#nested_action).
@@ -233,6 +235,12 @@ The following arguments are supported:
233235

234236
* `data_locations` - (Required) The list of individual regions that comprise a dual-region bucket. See [Cloud Storage bucket locations](https://cloud.google.com/storage/docs/dual-regions#availability) for a list of acceptable regions. **Note**: If any of the data_locations changes, it will [recreate the bucket](https://cloud.google.com/storage/docs/locations#key-concepts).
235237

238+
<a name="nested_soft_delete_policy"></a>The `soft_delete_policy` block supports:
239+
240+
* `retention_duration_seconds` - (Optional, Default: 604800) The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Default value is 604800. The value must be in between 604800(7 days) and 7776000(90 days). **Note**: To disable the soft delete policy on a bucket, This field must be set to 0.
241+
242+
* `effective_time` - (Computed) Server-determined value that indicates the time from which the policy, or one with a greater retention, was effective. This value is in RFC 3339 format.
243+
236244
## Attributes Reference
237245

238246
In addition to the arguments listed above, the following computed attributes are

0 commit comments

Comments
 (0)