Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added custom_placement_config field in google_storage_bucket resource #12723

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/6619.txt
@@ -0,0 +1,3 @@
```release-note:enhancement
storage: added `custom_placement_config` field to `google_storage_bucket` resource to support custom dual-region GCS buckets
```
64 changes: 64 additions & 0 deletions google/resource_storage_bucket.go
Expand Up @@ -365,6 +365,27 @@ func resourceStorageBucket() *schema.Resource {
Computed: true,
Description: `Enables uniform bucket-level access on a bucket.`,
},
"custom_placement_config": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"data_locations": {
Type: schema.TypeSet,
Required: true,
ForceNew: true,
MaxItems: 2,
MinItems: 2,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: `The list of individual regions that comprise a dual-region bucket. See the docs for a list of acceptable regions. Note: If any of the data_locations changes, it will recreate the bucket.`,
},
},
},
Description: `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.`,
},
},
UseJSONNumber: true,
}
Expand Down Expand Up @@ -482,6 +503,10 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error
}
}

if v, ok := d.GetOk("custom_placement_config"); ok {
sb.CustomPlacementConfig = expandBucketCustomPlacementConfig(v.([]interface{}))
}

var res *storage.Bucket

err = retry(func() error {
Expand Down Expand Up @@ -894,6 +919,42 @@ func flattenBucketEncryption(enc *storage.BucketEncryption) []map[string]interfa
return encryption
}

func expandBucketCustomPlacementConfig(configured interface{}) *storage.BucketCustomPlacementConfig {
cfcs := configured.([]interface{})
if len(cfcs) == 0 || cfcs[0] == nil {
return nil
}
cfc := cfcs[0].(map[string]interface{})
bucketcfc := &storage.BucketCustomPlacementConfig{
DataLocations: expandBucketDataLocations(cfc["data_locations"]),
}
return bucketcfc
}

func flattenBucketCustomPlacementConfig(cfc *storage.BucketCustomPlacementConfig) []map[string]interface{} {
customPlacementConfig := make([]map[string]interface{}, 0, 1)

if cfc == nil {
return customPlacementConfig
}

customPlacementConfig = append(customPlacementConfig, map[string]interface{}{
"data_locations": cfc.DataLocations,
})

return customPlacementConfig
}

func expandBucketDataLocations(configured interface{}) []string {
l := configured.(*schema.Set).List()

req := make([]string, 0, len(l))
for _, raw := range l {
req = append(req, raw.(string))
}
return req
}

func expandBucketLogging(configured interface{}) *storage.BucketLogging {
loggings := configured.([]interface{})
if len(loggings) == 0 {
Expand Down Expand Up @@ -1430,6 +1491,9 @@ func setStorageBucket(d *schema.ResourceData, config *Config, res *storage.Bucke
if err := d.Set("retention_policy", flattenBucketRetentionPolicy(res.RetentionPolicy)); err != nil {
return fmt.Errorf("Error setting retention_policy: %s", err)
}
if err := d.Set("custom_placement_config", flattenBucketCustomPlacementConfig(res.CustomPlacementConfig)); err != nil {
return fmt.Errorf("Error setting custom_placement_config: %s", err)
}

if res.IamConfiguration != nil && res.IamConfiguration.UniformBucketLevelAccess != nil {
if err := d.Set("uniform_bucket_level_access", res.IamConfiguration.UniformBucketLevelAccess.Enabled); err != nil {
Expand Down
36 changes: 36 additions & 0 deletions google/resource_storage_bucket_test.go
Expand Up @@ -103,6 +103,29 @@ func TestAccStorageBucket_lowercaseLocation(t *testing.T) {
})
}

func TestAccStorageBucket_dualLocation(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_dualLocation(bucketName),
},
{
ResourceName: "google_storage_bucket.bucket",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"force_destroy"},
},
},
})
}

func TestAccStorageBucket_customAttributes(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -1287,6 +1310,19 @@ resource "google_storage_bucket" "bucket" {
`, bucketName)
}

func testAccStorageBucket_dualLocation(bucketName string) string {
return fmt.Sprintf(`
resource "google_storage_bucket" "bucket" {
name = "%s"
location = "ASIA"
force_destroy = true
custom_placement_config {
data_locations = ["ASIA-EAST1", "ASIA-SOUTHEAST1"]
}
}
`, bucketName)
}

func testAccStorageBucket_customAttributes(bucketName string) string {
return fmt.Sprintf(`
resource "google_storage_bucket" "bucket" {
Expand Down
6 changes: 6 additions & 0 deletions website/docs/r/storage_bucket.html.markdown
Expand Up @@ -101,6 +101,8 @@ The following arguments are supported:

* `uniform_bucket_level_access` - (Optional, Default: false) Enables [Uniform bucket-level access](https://cloud.google.com/storage/docs/uniform-bucket-level-access) access to a bucket.

* `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).

<a name="nested_lifecycle_rule"></a>The `lifecycle_rule` block supports:

* `action` - (Required) The Lifecycle Rule's action configuration. A single block of this type is supported. Structure is [documented below](#nested_action).
Expand Down Expand Up @@ -189,6 +191,10 @@ The following arguments are supported:
state of the project.
You should take care for race conditions when the same Terraform manages IAM policy on the Cloud KMS crypto key. See the data source page for more details.

<a name="nested_custom_placement_config"></a>The `custom_placement_config` block supports:

* `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).

## Attributes Reference

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