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

Add support for processing_units to google_spanner_instance #9716

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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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