diff --git a/.changelog/3308.txt b/.changelog/3308.txt new file mode 100644 index 0000000000..c8aa22d230 --- /dev/null +++ b/.changelog/3308.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +compute: added ability to resize `google_compute_reservation` +``` diff --git a/google-beta/resource_compute_reservation.go b/google-beta/resource_compute_reservation.go index 04bb98e71e..72c215bde3 100644 --- a/google-beta/resource_compute_reservation.go +++ b/google-beta/resource_compute_reservation.go @@ -29,6 +29,7 @@ func resourceComputeReservation() *schema.Resource { return &schema.Resource{ Create: resourceComputeReservationCreate, Read: resourceComputeReservationRead, + Update: resourceComputeReservationUpdate, Delete: resourceComputeReservationDelete, Importer: &schema.ResourceImporter{ @@ -37,6 +38,7 @@ func resourceComputeReservation() *schema.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(4 * time.Minute), + Update: schema.DefaultTimeout(4 * time.Minute), Delete: schema.DefaultTimeout(4 * time.Minute), }, @@ -56,16 +58,15 @@ character, which cannot be a dash.`, "specific_reservation": { Type: schema.TypeList, Required: true, - ForceNew: true, Description: `Reservation for instances with specific machine shapes.`, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "count": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - Description: `The number of resources that are allocated.`, + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntAtLeast(1), + Description: `The number of resources that are allocated.`, }, "instance_properties": { Type: schema.TypeList, @@ -331,6 +332,55 @@ func resourceComputeReservationRead(d *schema.ResourceData, meta interface{}) er return nil } +func resourceComputeReservationUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + d.Partial(true) + + if d.HasChange("specific_reservation") { + obj := make(map[string]interface{}) + + specificReservationProp, err := expandComputeReservationSpecificReservation(d.Get("specific_reservation"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("specific_reservation"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, specificReservationProp)) { + obj["specificReservation"] = specificReservationProp + } + + obj, err = resourceComputeReservationUpdateEncoder(d, meta, obj) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/reservations/{{name}}/resize") + if err != nil { + return err + } + res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return fmt.Errorf("Error updating Reservation %q: %s", d.Id(), err) + } + + err = computeOperationWaitTime( + config, res, project, "Updating Reservation", + int(d.Timeout(schema.TimeoutUpdate).Minutes())) + if err != nil { + return err + } + + d.SetPartial("specific_reservation") + } + + d.Partial(false) + + return resourceComputeReservationRead(d, meta) +} + func resourceComputeReservationDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -756,3 +806,10 @@ func expandComputeReservationZone(v interface{}, d TerraformResourceData, config } return f.RelativeLink(), nil } + +func resourceComputeReservationUpdateEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + newObj := make(map[string]interface{}) + newObj["specificSkuCount"] = obj["specificReservation"].(map[string]interface{})["count"] + + return newObj, nil +} diff --git a/google-beta/resource_compute_reservation_test.go b/google-beta/resource_compute_reservation_test.go new file mode 100644 index 0000000000..bc6b0de1e4 --- /dev/null +++ b/google-beta/resource_compute_reservation_test.go @@ -0,0 +1,56 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccComputeReservation_update(t *testing.T) { + t.Parallel() + + reservationName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeReservationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeReservation_basic(reservationName, "2"), + }, + { + ResourceName: "google_compute_reservation.reservation", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeReservation_basic(reservationName, "1"), + }, + { + ResourceName: "google_compute_reservation.reservation", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeReservation_basic(reservationName, count string) string { + return fmt.Sprintf(` +resource "google_compute_reservation" "reservation" { + name = "%s" + zone = "us-central1-a" + + specific_reservation { + count = %s + instance_properties { + min_cpu_platform = "Intel Cascade Lake" + machine_type = "n2-standard-2" + } + } +} +`, reservationName, count) +} diff --git a/website/docs/r/compute_reservation.html.markdown b/website/docs/r/compute_reservation.html.markdown index 0aac6c40fc..019b7841b7 100644 --- a/website/docs/r/compute_reservation.html.markdown +++ b/website/docs/r/compute_reservation.html.markdown @@ -188,6 +188,7 @@ This resource provides the following [Timeouts](/docs/configuration/resources.html#timeouts) configuration options: - `create` - Default is 4 minutes. +- `update` - Default is 4 minutes. - `delete` - Default is 4 minutes. ## Import