Skip to content

Commit b4a4eb5

Browse files
Bigtable: add data_boost_isolation_read_only support for the Data Boost feature. (#11138) (#7789)
[upstream:cc890e7fedc695ecf781d9b69cb336f44d1b832f] Signed-off-by: Modular Magician <[email protected]>
1 parent e69e7ee commit b4a4eb5

File tree

4 files changed

+237
-0
lines changed

4 files changed

+237
-0
lines changed

.changelog/11138.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
bigtable: added `data_boost_isolation_read_only` and `data_boost_isolation_read_only.compute_billing_owner` fields to `google_bigtable_app_profile` resource
3+
```

google-beta/services/bigtable/resource_bigtable_app_profile.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,23 @@ func ResourceBigtableAppProfile() *schema.Resource {
6262
ForceNew: true,
6363
Description: `The unique name of the app profile in the form '[_a-zA-Z0-9][-_.a-zA-Z0-9]*'.`,
6464
},
65+
"data_boost_isolation_read_only": {
66+
Type: schema.TypeList,
67+
Optional: true,
68+
Description: `Specifies that this app profile is intended for read-only usage via the Data Boost feature.`,
69+
MaxItems: 1,
70+
Elem: &schema.Resource{
71+
Schema: map[string]*schema.Schema{
72+
"compute_billing_owner": {
73+
Type: schema.TypeString,
74+
Required: true,
75+
ValidateFunc: verify.ValidateEnum([]string{"HOST_PAYS"}),
76+
Description: `The Compute Billing Owner for this Data Boost App Profile. Possible values: ["HOST_PAYS"]`,
77+
},
78+
},
79+
},
80+
ConflictsWith: []string{"standard_isolation"},
81+
},
6582
"description": {
6683
Type: schema.TypeString,
6784
Optional: true,
@@ -126,6 +143,7 @@ It is unsafe to send these requests to the same table/row/column in multiple clu
126143
},
127144
},
128145
},
146+
ConflictsWith: []string{"data_boost_isolation_read_only"},
129147
},
130148
"name": {
131149
Type: schema.TypeString,
@@ -184,6 +202,12 @@ func resourceBigtableAppProfileCreate(d *schema.ResourceData, meta interface{})
184202
} else if v, ok := d.GetOkExists("standard_isolation"); !tpgresource.IsEmptyValue(reflect.ValueOf(standardIsolationProp)) && (ok || !reflect.DeepEqual(v, standardIsolationProp)) {
185203
obj["standardIsolation"] = standardIsolationProp
186204
}
205+
dataBoostIsolationReadOnlyProp, err := expandBigtableAppProfileDataBoostIsolationReadOnly(d.Get("data_boost_isolation_read_only"), d, config)
206+
if err != nil {
207+
return err
208+
} else if v, ok := d.GetOkExists("data_boost_isolation_read_only"); !tpgresource.IsEmptyValue(reflect.ValueOf(dataBoostIsolationReadOnlyProp)) && (ok || !reflect.DeepEqual(v, dataBoostIsolationReadOnlyProp)) {
209+
obj["dataBoostIsolationReadOnly"] = dataBoostIsolationReadOnlyProp
210+
}
187211

188212
obj, err = resourceBigtableAppProfileEncoder(d, meta, obj)
189213
if err != nil {
@@ -296,6 +320,9 @@ func resourceBigtableAppProfileRead(d *schema.ResourceData, meta interface{}) er
296320
if err := d.Set("standard_isolation", flattenBigtableAppProfileStandardIsolation(res["standardIsolation"], d, config)); err != nil {
297321
return fmt.Errorf("Error reading AppProfile: %s", err)
298322
}
323+
if err := d.Set("data_boost_isolation_read_only", flattenBigtableAppProfileDataBoostIsolationReadOnly(res["dataBoostIsolationReadOnly"], d, config)); err != nil {
324+
return fmt.Errorf("Error reading AppProfile: %s", err)
325+
}
299326

300327
return nil
301328
}
@@ -340,6 +367,12 @@ func resourceBigtableAppProfileUpdate(d *schema.ResourceData, meta interface{})
340367
} else if v, ok := d.GetOkExists("standard_isolation"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, standardIsolationProp)) {
341368
obj["standardIsolation"] = standardIsolationProp
342369
}
370+
dataBoostIsolationReadOnlyProp, err := expandBigtableAppProfileDataBoostIsolationReadOnly(d.Get("data_boost_isolation_read_only"), d, config)
371+
if err != nil {
372+
return err
373+
} else if v, ok := d.GetOkExists("data_boost_isolation_read_only"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, dataBoostIsolationReadOnlyProp)) {
374+
obj["dataBoostIsolationReadOnly"] = dataBoostIsolationReadOnlyProp
375+
}
343376

344377
obj, err = resourceBigtableAppProfileEncoder(d, meta, obj)
345378
if err != nil {
@@ -370,6 +403,10 @@ func resourceBigtableAppProfileUpdate(d *schema.ResourceData, meta interface{})
370403
if d.HasChange("standard_isolation") {
371404
updateMask = append(updateMask, "standardIsolation")
372405
}
406+
407+
if d.HasChange("data_boost_isolation_read_only") {
408+
updateMask = append(updateMask, "dataBoostIsolationReadOnly")
409+
}
373410
// updateMask is a URL parameter but not present in the schema, so ReplaceVars
374411
// won't set it
375412
url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
@@ -396,6 +433,16 @@ func resourceBigtableAppProfileUpdate(d *schema.ResourceData, meta interface{})
396433
}
397434
}
398435
}
436+
437+
_, hasStandardIsolation := obj["standardIsolation"]
438+
_, hasDataBoostIsolationReadOnly := obj["dataBoostIsolationReadOnly"]
439+
if hasStandardIsolation && hasDataBoostIsolationReadOnly {
440+
// Due to the "conflicts" both fields should be present only if neither was
441+
// previously specified and the user is now manually adding dataBoostIsolationReadOnly.
442+
delete(obj, "standardIsolation")
443+
updateMask = append(updateMask, "dataBoostIsolationReadOnly")
444+
}
445+
399446
// updateMask is a URL parameter but not present in the schema, so ReplaceVars
400447
// won't set it
401448
url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
@@ -566,6 +613,23 @@ func flattenBigtableAppProfileStandardIsolationPriority(v interface{}, d *schema
566613
return v
567614
}
568615

616+
func flattenBigtableAppProfileDataBoostIsolationReadOnly(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
617+
if v == nil {
618+
return nil
619+
}
620+
original := v.(map[string]interface{})
621+
if len(original) == 0 {
622+
return nil
623+
}
624+
transformed := make(map[string]interface{})
625+
transformed["compute_billing_owner"] =
626+
flattenBigtableAppProfileDataBoostIsolationReadOnlyComputeBillingOwner(original["computeBillingOwner"], d, config)
627+
return []interface{}{transformed}
628+
}
629+
func flattenBigtableAppProfileDataBoostIsolationReadOnlyComputeBillingOwner(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
630+
return v
631+
}
632+
569633
func expandBigtableAppProfileDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
570634
return v, nil
571635
}
@@ -643,6 +707,29 @@ func expandBigtableAppProfileStandardIsolationPriority(v interface{}, d tpgresou
643707
return v, nil
644708
}
645709

710+
func expandBigtableAppProfileDataBoostIsolationReadOnly(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
711+
l := v.([]interface{})
712+
if len(l) == 0 || l[0] == nil {
713+
return nil, nil
714+
}
715+
raw := l[0]
716+
original := raw.(map[string]interface{})
717+
transformed := make(map[string]interface{})
718+
719+
transformedComputeBillingOwner, err := expandBigtableAppProfileDataBoostIsolationReadOnlyComputeBillingOwner(original["compute_billing_owner"], d, config)
720+
if err != nil {
721+
return nil, err
722+
} else if val := reflect.ValueOf(transformedComputeBillingOwner); val.IsValid() && !tpgresource.IsEmptyValue(val) {
723+
transformed["computeBillingOwner"] = transformedComputeBillingOwner
724+
}
725+
726+
return transformed, nil
727+
}
728+
729+
func expandBigtableAppProfileDataBoostIsolationReadOnlyComputeBillingOwner(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
730+
return v, nil
731+
}
732+
646733
func resourceBigtableAppProfileEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) {
647734
// Instance is a URL parameter only, so replace self-link/path with resource name only.
648735
if err := d.Set("instance", tpgresource.GetResourceNameFromSelfLink(d.Get("instance").(string))); err != nil {

google-beta/services/bigtable/resource_bigtable_app_profile_test.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,3 +433,138 @@ resource "google_bigtable_app_profile" "ap" {
433433
}
434434
`, instanceName, instanceName, instanceName, instanceName, instanceName, instanceName)
435435
}
436+
437+
func testAccBigtableAppProfile_updateSSDWithPriority(instanceName string) string {
438+
return fmt.Sprintf(`
439+
resource "google_bigtable_instance" "instance" {
440+
name = "%s"
441+
cluster {
442+
cluster_id = "%s"
443+
zone = "us-central1-b"
444+
num_nodes = 1
445+
storage_type = "SSD"
446+
}
447+
448+
cluster {
449+
cluster_id = "%s2"
450+
zone = "us-central1-a"
451+
num_nodes = 1
452+
storage_type = "SSD"
453+
}
454+
455+
cluster {
456+
cluster_id = "%s3"
457+
zone = "us-central1-c"
458+
num_nodes = 1
459+
storage_type = "SSD"
460+
}
461+
462+
deletion_protection = false
463+
}
464+
465+
resource "google_bigtable_app_profile" "ap" {
466+
instance = google_bigtable_instance.instance.id
467+
app_profile_id = "test"
468+
469+
single_cluster_routing {
470+
cluster_id = %q
471+
allow_transactional_writes = false
472+
}
473+
474+
standard_isolation {
475+
priority = "PRIORITY_MEDIUM"
476+
}
477+
478+
ignore_warnings = true
479+
}
480+
`, instanceName, instanceName, instanceName, instanceName, instanceName)
481+
}
482+
483+
func testAccBigtableAppProfile_updateDataBoost(instanceName string) string {
484+
return fmt.Sprintf(`
485+
resource "google_bigtable_instance" "instance" {
486+
name = "%s"
487+
cluster {
488+
cluster_id = "%s"
489+
zone = "us-central1-b"
490+
num_nodes = 1
491+
storage_type = "SSD"
492+
}
493+
494+
cluster {
495+
cluster_id = "%s2"
496+
zone = "us-central1-a"
497+
num_nodes = 1
498+
storage_type = "SSD"
499+
}
500+
501+
cluster {
502+
cluster_id = "%s3"
503+
zone = "us-central1-c"
504+
num_nodes = 1
505+
storage_type = "SSD"
506+
}
507+
508+
deletion_protection = false
509+
}
510+
511+
resource "google_bigtable_app_profile" "ap" {
512+
instance = google_bigtable_instance.instance.id
513+
app_profile_id = "test"
514+
515+
single_cluster_routing {
516+
cluster_id = %q
517+
allow_transactional_writes = false
518+
}
519+
520+
data_boost_isolation_read_only {
521+
compute_billing_owner = "HOST_PAYS"
522+
}
523+
524+
ignore_warnings = true
525+
}
526+
`, instanceName, instanceName, instanceName, instanceName, instanceName)
527+
}
528+
529+
func TestAccBigtableAppProfile_updateStandardIsolationToDataBoost(t *testing.T) {
530+
// bigtable instance does not use the shared HTTP client, this test creates an instance
531+
acctest.SkipIfVcr(t)
532+
t.Parallel()
533+
534+
instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10))
535+
536+
acctest.VcrTest(t, resource.TestCase{
537+
PreCheck: func() { acctest.AccTestPreCheck(t) },
538+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
539+
CheckDestroy: testAccCheckBigtableAppProfileDestroyProducer(t),
540+
Steps: []resource.TestStep{
541+
{
542+
Config: testAccBigtableAppProfile_updateSSDWithPriority(instanceName),
543+
},
544+
{
545+
ResourceName: "google_bigtable_app_profile.ap",
546+
ImportState: true,
547+
ImportStateVerify: true,
548+
ImportStateVerifyIgnore: []string{"ignore_warnings"},
549+
},
550+
{
551+
Config: testAccBigtableAppProfile_updateDataBoost(instanceName),
552+
},
553+
{
554+
ResourceName: "google_bigtable_app_profile.ap",
555+
ImportState: true,
556+
ImportStateVerify: true,
557+
ImportStateVerifyIgnore: []string{"ignore_warnings"},
558+
},
559+
{
560+
Config: testAccBigtableAppProfile_updateSSDWithPriority(instanceName),
561+
},
562+
{
563+
ResourceName: "google_bigtable_app_profile.ap",
564+
ImportState: true,
565+
ImportStateVerify: true,
566+
ImportStateVerifyIgnore: []string{"ignore_warnings"},
567+
},
568+
},
569+
})
570+
}

website/docs/r/bigtable_app_profile.html.markdown

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ The following arguments are supported:
219219
The standard options used for isolating this app profile's traffic from other use cases.
220220
Structure is [documented below](#nested_standard_isolation).
221221

222+
* `data_boost_isolation_read_only` -
223+
(Optional)
224+
Specifies that this app profile is intended for read-only usage via the Data Boost feature.
225+
Structure is [documented below](#nested_data_boost_isolation_read_only).
226+
222227
* `instance` -
223228
(Optional)
224229
The name of the instance to create the app profile within.
@@ -249,6 +254,13 @@ The following arguments are supported:
249254
The priority of requests sent using this app profile.
250255
Possible values are: `PRIORITY_LOW`, `PRIORITY_MEDIUM`, `PRIORITY_HIGH`.
251256

257+
<a name="nested_data_boost_isolation_read_only"></a>The `data_boost_isolation_read_only` block supports:
258+
259+
* `compute_billing_owner` -
260+
(Required)
261+
The Compute Billing Owner for this Data Boost App Profile.
262+
Possible values are: `HOST_PAYS`.
263+
252264
## Attributes Reference
253265

254266
In addition to the arguments listed above, the following computed attributes are exported:

0 commit comments

Comments
 (0)