Skip to content

Commit

Permalink
Add support for processing_units to google_spanner_instance (#4993)…
Browse files Browse the repository at this point in the history
… (#9716)

Co-authored-by: upodroid <cy@borg.dev>
Co-authored-by: Cameron Thornton <camthornton@google.com>
Signed-off-by: Modular Magician <magic-modules@google.com>

Co-authored-by: upodroid <cy@borg.dev>
Co-authored-by: Cameron Thornton <camthornton@google.com>
  • Loading branch information
3 people authored Aug 3, 2021
1 parent e1864af commit 4ac485d
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 5 deletions.
6 changes: 6 additions & 0 deletions .changelog/4993.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```release-note:note
spanner: `num_nodes` will become a required field in the next major release and a value has to be set on `google_spanner_instance`. It will also conflict with the new field `processing_units`.
```
```release-note:enhancement
spanner: added `processing_units` to `google_spanner_instance`.
```
56 changes: 52 additions & 4 deletions google/resource_spanner_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,18 @@ Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"num_nodes": {
Type: schema.TypeInt,
Optional: true,
Description: `The number of nodes allocated to this instance.`,
Default: 1,
Type: schema.TypeInt,
Computed: true,
Optional: true,
Description: `The number of nodes allocated to this instance. At most one of either node_count or processing_units
can be present in terraform.`,
},
"processing_units": {
Type: schema.TypeInt,
Computed: true,
Optional: true,
Description: `The number of processing units allocated to this instance. At most one of processing_units
or node_count can be present in terraform.`,
},
"state": {
Type: schema.TypeString,
Expand Down Expand Up @@ -177,6 +185,12 @@ func resourceSpannerInstanceCreate(d *schema.ResourceData, meta interface{}) err
} else if v, ok := d.GetOkExists("num_nodes"); !isEmptyValue(reflect.ValueOf(nodeCountProp)) && (ok || !reflect.DeepEqual(v, nodeCountProp)) {
obj["nodeCount"] = nodeCountProp
}
processingUnitsProp, err := expandSpannerInstanceProcessingUnits(d.Get("processing_units"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("processing_units"); !isEmptyValue(reflect.ValueOf(processingUnitsProp)) && (ok || !reflect.DeepEqual(v, processingUnitsProp)) {
obj["processingUnits"] = processingUnitsProp
}
labelsProp, err := expandSpannerInstanceLabels(d.Get("labels"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -325,6 +339,9 @@ func resourceSpannerInstanceRead(d *schema.ResourceData, meta interface{}) error
if err := d.Set("num_nodes", flattenSpannerInstanceNumNodes(res["nodeCount"], d, config)); err != nil {
return fmt.Errorf("Error reading Instance: %s", err)
}
if err := d.Set("processing_units", flattenSpannerInstanceProcessingUnits(res["processingUnits"], d, config)); err != nil {
return fmt.Errorf("Error reading Instance: %s", err)
}
if err := d.Set("labels", flattenSpannerInstanceLabels(res["labels"], d, config)); err != nil {
return fmt.Errorf("Error reading Instance: %s", err)
}
Expand Down Expand Up @@ -363,6 +380,12 @@ func resourceSpannerInstanceUpdate(d *schema.ResourceData, meta interface{}) err
} else if v, ok := d.GetOkExists("num_nodes"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nodeCountProp)) {
obj["nodeCount"] = nodeCountProp
}
processingUnitsProp, err := expandSpannerInstanceProcessingUnits(d.Get("processing_units"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("processing_units"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, processingUnitsProp)) {
obj["processingUnits"] = processingUnitsProp
}
labelsProp, err := expandSpannerInstanceLabels(d.Get("labels"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -521,6 +544,23 @@ func flattenSpannerInstanceNumNodes(v interface{}, d *schema.ResourceData, confi
return v // let terraform core handle it otherwise
}

func flattenSpannerInstanceProcessingUnits(v interface{}, d *schema.ResourceData, config *Config) interface{} {
// Handles the string fixed64 format
if strVal, ok := v.(string); ok {
if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil {
return intVal
}
}

// number values are represented as float64
if floatVal, ok := v.(float64); ok {
intVal := int(floatVal)
return intVal
}

return v // let terraform core handle it otherwise
}

func flattenSpannerInstanceLabels(v interface{}, d *schema.ResourceData, config *Config) interface{} {
return v
}
Expand Down Expand Up @@ -555,6 +595,10 @@ func expandSpannerInstanceNumNodes(v interface{}, d TerraformResourceData, confi
return v, nil
}

func expandSpannerInstanceProcessingUnits(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandSpannerInstanceLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
Expand All @@ -567,6 +611,10 @@ func expandSpannerInstanceLabels(v interface{}, d TerraformResourceData, config
}

func resourceSpannerInstanceEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) {
// Temp Logic to accomodate processing_units and num_nodes
if obj["processingUnits"] == nil && obj["nodeCount"] == nil {
obj["nodeCount"] = 1
}
newObj := make(map[string]interface{})
newObj["instance"] = obj
if obj["name"] == nil {
Expand Down
39 changes: 39 additions & 0 deletions google/resource_spanner_instance_generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,45 @@ resource "google_spanner_instance" "example" {
`, context)
}

func TestAccSpannerInstance_spannerInstanceProcessingUnitsExample(t *testing.T) {
skipIfVcr(t)
t.Parallel()

context := map[string]interface{}{
"random_suffix": randString(t, 10),
}

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSpannerInstanceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccSpannerInstance_spannerInstanceProcessingUnitsExample(context),
},
{
ResourceName: "google_spanner_instance.example",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"config"},
},
},
})
}

func testAccSpannerInstance_spannerInstanceProcessingUnitsExample(context map[string]interface{}) string {
return Nprintf(`
resource "google_spanner_instance" "example" {
config = "regional-us-central1"
display_name = "Test Spanner Instance"
processing_units = 200
labels = {
"foo" = "bar"
}
}
`, context)
}

func TestAccSpannerInstance_spannerInstanceMultiRegionalExample(t *testing.T) {
skipIfVcr(t)
t.Parallel()
Expand Down
34 changes: 34 additions & 0 deletions google/resource_spanner_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,30 @@ func TestAccSpannerInstance_basic(t *testing.T) {
})
}

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

idName := fmt.Sprintf("spanner-test-%s", randString(t, 10))
vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSpannerInstanceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccSpannerInstance_noNodeCountSpecified(idName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("google_spanner_instance.basic", "state"),
),
},
{
ResourceName: "google_spanner_instance.basic",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccSpannerInstance_basicWithAutogenName(t *testing.T) {
// Randomness
skipIfVcr(t)
Expand Down Expand Up @@ -140,6 +164,16 @@ resource "google_spanner_instance" "basic" {
`, name, name)
}

func testAccSpannerInstance_noNodeCountSpecified(name string) string {
return fmt.Sprintf(`
resource "google_spanner_instance" "basic" {
name = "%s"
config = "regional-us-central1"
display_name = "%s-dname"
}
`, name, name)
}

func testAccSpannerInstance_basicWithAutogenName(name string) string {
return fmt.Sprintf(`
resource "google_spanner_instance" "basic" {
Expand Down
26 changes: 25 additions & 1 deletion website/docs/r/spanner_instance.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,24 @@ resource "google_spanner_instance" "example" {
}
}
```
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
<a href="https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fdocs-examples.git&cloudshell_working_dir=spanner_instance_processing_units&cloudshell_image=gcr.io%2Fgraphite-cloud-shell-images%2Fterraform%3Alatest&open_in_editor=main.tf&cloudshell_print=.%2Fmotd&cloudshell_tutorial=.%2Ftutorial.md" target="_blank">
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
</a>
</div>
## Example Usage - Spanner Instance Processing Units


```hcl
resource "google_spanner_instance" "example" {
config = "regional-us-central1"
display_name = "Test Spanner Instance"
processing_units = 200
labels = {
"foo" = "bar"
}
}
```
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
<a href="https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fdocs-examples.git&cloudshell_working_dir=spanner_instance_multi_regional&cloudshell_image=gcr.io%2Fgraphite-cloud-shell-images%2Fterraform%3Alatest&open_in_editor=main.tf&cloudshell_print=.%2Fmotd&cloudshell_tutorial=.%2Ftutorial.md" target="_blank">
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
Expand Down Expand Up @@ -103,7 +121,13 @@ The following arguments are supported:

* `num_nodes` -
(Optional)
The number of nodes allocated to this instance.
The number of nodes allocated to this instance. At most one of either node_count or processing_units
can be present in terraform.

* `processing_units` -
(Optional)
The number of processing units allocated to this instance. At most one of processing_units
or node_count can be present in terraform.

* `labels` -
(Optional)
Expand Down

0 comments on commit 4ac485d

Please sign in to comment.