From 7fdea1d8cadecc0a2835afe8ffac5c90626629d8 Mon Sep 17 00:00:00 2001 From: The Magician Date: Tue, 6 Dec 2022 10:29:28 -0800 Subject: [PATCH] Add Support for Storage Autoclass (#6870) (#13185) Fixes https://github.com/hashicorp/terraform-provider-google/issues/13044 Signed-off-by: Modular Magician Signed-off-by: Modular Magician --- .changelog/6870.txt | 3 + google/resource_storage_bucket.go | 61 +++++++++++++++++++++ google/resource_storage_bucket_test.go | 39 +++++++++++++ website/docs/r/storage_bucket.html.markdown | 6 ++ 4 files changed, 109 insertions(+) create mode 100644 .changelog/6870.txt diff --git a/.changelog/6870.txt b/.changelog/6870.txt new file mode 100644 index 0000000000..e57f635c4b --- /dev/null +++ b/.changelog/6870.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +storage: added support for `autoclass` in `google_storage_bucket` resource +``` diff --git a/google/resource_storage_bucket.go b/google/resource_storage_bucket.go index 1f8940ac7e..91911ebb88 100644 --- a/google/resource_storage_bucket.go +++ b/google/resource_storage_bucket.go @@ -247,6 +247,24 @@ func resourceStorageBucket() *schema.Resource { Description: `The bucket's Versioning configuration.`, }, + "autoclass": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `While set to true, autoclass automatically transitions objects in your bucket to appropriate storage classes based on each object's access pattern.`, + }, + }, + }, + Description: `The bucket's autoclass configuration.`, + }, + "website": { Type: schema.TypeList, Optional: true, @@ -475,6 +493,10 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error sb.Versioning = expandBucketVersioning(v) } + if v, ok := d.GetOk("autoclass"); ok { + sb.Autoclass = expandBucketAutoclass(v) + } + if v, ok := d.GetOk("website"); ok { sb.Website = expandBucketWebsite(v.([]interface{})) } @@ -599,6 +621,12 @@ func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error } } + if d.HasChange("autoclass") { + if v, ok := d.GetOk("autoclass"); ok { + sb.Autoclass = expandBucketAutoclass(v) + } + } + if d.HasChange("website") { sb.Website = expandBucketWebsite(d.Get("website")) } @@ -1047,6 +1075,22 @@ func expandBucketVersioning(configured interface{}) *storage.BucketVersioning { return bucketVersioning } +func expandBucketAutoclass(configured interface{}) *storage.BucketAutoclass { + autoclassList := configured.([]interface{}) + if len(autoclassList) == 0 { + return nil + } + + autoclass := autoclassList[0].(map[string]interface{}) + + bucketAutoclass := &storage.BucketAutoclass{} + + bucketAutoclass.Enabled = autoclass["enabled"].(bool) + bucketAutoclass.ForceSendFields = append(bucketAutoclass.ForceSendFields, "Enabled") + + return bucketAutoclass +} + func flattenBucketVersioning(bucketVersioning *storage.BucketVersioning) []map[string]interface{} { versionings := make([]map[string]interface{}, 0, 1) @@ -1061,6 +1105,20 @@ func flattenBucketVersioning(bucketVersioning *storage.BucketVersioning) []map[s return versionings } +func flattenBucketAutoclass(bucketAutoclass *storage.BucketAutoclass) []map[string]interface{} { + autoclassList := make([]map[string]interface{}, 0, 1) + + if bucketAutoclass == nil { + return autoclassList + } + + autoclass := map[string]interface{}{ + "enabled": bucketAutoclass.Enabled, + } + autoclassList = append(autoclassList, autoclass) + return autoclassList +} + func flattenBucketLifecycle(lifecycle *storage.BucketLifecycle) []map[string]interface{} { if lifecycle == nil || lifecycle.Rule == nil { return []map[string]interface{}{} @@ -1499,6 +1557,9 @@ func setStorageBucket(d *schema.ResourceData, config *Config, res *storage.Bucke if err := d.Set("versioning", flattenBucketVersioning(res.Versioning)); err != nil { return fmt.Errorf("Error setting versioning: %s", err) } + if err := d.Set("autoclass", flattenBucketAutoclass(res.Autoclass)); err != nil { + return fmt.Errorf("Error setting autoclass: %s", err) + } if err := d.Set("lifecycle_rule", flattenBucketLifecycle(res.Lifecycle)); err != nil { return fmt.Errorf("Error setting lifecycle_rule: %s", err) } diff --git a/google/resource_storage_bucket_test.go b/google/resource_storage_bucket_test.go index 0d0a665f3f..8888c4fab4 100644 --- a/google/resource_storage_bucket_test.go +++ b/google/resource_storage_bucket_test.go @@ -53,6 +53,33 @@ func TestAccStorageBucket_basic(t *testing.T) { }) } +func TestAccStorageBucket_basicWithAutoclass(t *testing.T) { + t.Parallel() + + bucketName := testBucketName(t) + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccStorageBucketDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccStorageBucket_basicWithAutoclass(bucketName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "force_destroy", "false"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + }, + }) +} + func TestAccStorageBucket_requesterPays(t *testing.T) { t.Parallel() @@ -1329,6 +1356,18 @@ resource "google_storage_bucket" "bucket" { `, bucketName) } +func testAccStorageBucket_basicWithAutoclass(bucketName string) string { + return fmt.Sprintf(` +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "US" + autoclass { + enabled = true + } +} +`, bucketName) +} + func testAccStorageBucket_requesterPays(bucketName string, pays bool) string { return fmt.Sprintf(` resource "google_storage_bucket" "bucket" { diff --git a/website/docs/r/storage_bucket.html.markdown b/website/docs/r/storage_bucket.html.markdown index 15cc75e6a3..5de9bcab92 100644 --- a/website/docs/r/storage_bucket.html.markdown +++ b/website/docs/r/storage_bucket.html.markdown @@ -101,6 +101,8 @@ The following arguments are supported: * `storage_class` - (Optional, Default: 'STANDARD') The [Storage Class](https://cloud.google.com/storage/docs/storage-classes) of the new bucket. Supported values include: `STANDARD`, `MULTI_REGIONAL`, `REGIONAL`, `NEARLINE`, `COLDLINE`, `ARCHIVE`. +* `autoclass` - (Optional) The bucket's [Autoclass](https://cloud.google.com/storage/docs/autoclass) configuration. Structure is [documented below](#nested_autoclass). + * `lifecycle_rule` - (Optional) The bucket's [Lifecycle Rules](https://cloud.google.com/storage/docs/lifecycle#configuration) configuration. Multiple blocks of this type are permitted. Structure is [documented below](#nested_lifecycle_rule). * `versioning` - (Optional) The bucket's [Versioning](https://cloud.google.com/storage/docs/object-versioning) configuration. Structure is [documented below](#nested_versioning). @@ -163,6 +165,10 @@ The following arguments are supported: * `noncurrent_time_before` - (Optional) Relevant only for versioned objects. The date in RFC 3339 (e.g. `2017-06-13`) when the object became nonconcurrent. +The `autoclass` block supports: + +* `enabled` - (Required) While set to `true`, autoclass automatically transitions objects in your bucket to appropriate storage classes based on each object's access pattern. + The `versioning` block supports: * `enabled` - (Required) While set to `true`, versioning is fully enabled for this bucket.