diff --git a/mmv1/products/workbench/Instance.yaml b/mmv1/products/workbench/Instance.yaml index b0b2b08e8d43..8575e8be652f 100644 --- a/mmv1/products/workbench/Instance.yaml +++ b/mmv1/products/workbench/Instance.yaml @@ -55,7 +55,7 @@ examples: ignore_read_extra: - 'gce_setup.0.vm_image' - !ruby/object:Provider::Terraform::Examples - name: 'workbench_instance_labels' + name: 'workbench_instance_labels_stopped' primary_resource_id: 'instance' primary_resource_name: "fmt.Sprintf(\"tf-test-workbench-instance%s\", context[\"\ @@ -66,6 +66,8 @@ examples: network_name: 'wbi-test-default' test_env_vars: service_account: :SERVICE_ACCT + ignore_read_extra: + - 'desired_state' - !ruby/object:Provider::Terraform::Examples name: 'workbench_instance_full' primary_resource_id: 'instance' @@ -83,15 +85,20 @@ examples: service_account: :SERVICE_ACCT ignore_read_extra: - 'gce_setup.0.vm_image' - - 'gce_setup.0.boot_disk.0.disk_encryption' - 'gce_setup.0.boot_disk.0.disk_type' - - 'gce_setup.0.boot_disk.0.kms_key' - - 'gce_setup.0.data_disks.0.disk_encryption' - 'gce_setup.0.data_disks.0.disk_type' - - 'gce_setup.0.data_disks.0.kms_key' timeouts: !ruby/object:Api::Timeouts insert_minutes: 10 update_minutes: 20 +virtual_fields: + - !ruby/object:Api::Type::Enum + name: desired_state + description: | + Desired state of the Workbench Instance. Set this field to `ACTIVE` to start the Instance, and `STOPPED` to stop the Instance. + values: + - :ACTIVE + - :STOPPED + default_value: :ACTIVE custom_code: !ruby/object:Provider::Terraform::CustomCode constants: templates/terraform/constants/workbench_instance.go post_create: templates/terraform/post_create/workbench_instance.go.erb @@ -231,7 +238,6 @@ properties: - !ruby/object:Api::Type::Enum name: diskEncryption default_from_api: true - custom_flatten: templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb values: - GMEK - CMEK @@ -242,11 +248,11 @@ properties: - !ruby/object:Api::Type::String name: kmsKey description: | - 'Optional. Input only. The KMS key used to encrypt the disks, only + 'Optional. The KMS key used to encrypt the disks, only applicable if disk_encryption is CMEK. Format: `projects/{project_id}/locations/{location}/keyRings/{key_ring_id}/cryptoKeys/{key_id}` Learn more about using your own encryption keys.' immutable: true - custom_flatten: templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb + diff_suppress_func: WorkbenchInstanceKmsDiffSuppress - !ruby/object:Api::Type::Array name: dataDisks description: Data disks attached to the VM instance. Currently supports only one data disk. @@ -276,7 +282,6 @@ properties: - !ruby/object:Api::Type::Enum name: diskEncryption default_from_api: true - custom_flatten: templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb values: - GMEK - CMEK @@ -287,11 +292,11 @@ properties: - !ruby/object:Api::Type::String name: kmsKey description: | - 'Optional. Input only. The KMS key used to encrypt the disks, + 'Optional. The KMS key used to encrypt the disks, only applicable if disk_encryption is CMEK. Format: `projects/{project_id}/locations/{location}/keyRings/{key_ring_id}/cryptoKeys/{key_id}` Learn more about using your own encryption keys.' immutable: true - custom_flatten: templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb + diff_suppress_func: WorkbenchInstanceKmsDiffSuppress description: | Optional. Data disks attached to the VM instance. Currently supports only one data disk. diff --git a/mmv1/templates/terraform/constants/workbench_instance.go b/mmv1/templates/terraform/constants/workbench_instance.go index 6ae6d20dca67..4462c0e5baa7 100644 --- a/mmv1/templates/terraform/constants/workbench_instance.go +++ b/mmv1/templates/terraform/constants/workbench_instance.go @@ -140,3 +140,42 @@ func waitForWorkbenchInstanceActive(d *schema.ResourceData, config *transport_tp }) } <% end -%> + +func modifyWorkbenchInstanceState(config *transport_tpg.Config, d *schema.ResourceData, project string, billingProject string, userAgent string, state string) (map[string]interface{}, error) { + url, err := tpgresource.ReplaceVars(d, config, "{{WorkbenchBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}:"+state) + if err != nil { + return nil, err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return nil, fmt.Errorf("Unable to %q google_workbench_instance %q: %s", state, d.Id(), err) + } + return res, nil +} + +func WorkbenchInstanceKmsDiffSuppress(_, old, new string, _ *schema.ResourceData) bool { + if strings.HasPrefix(old, new) { + return true + } + return false +} + +<% unless compiler == "terraformgoogleconversion-codegen" -%> +func waitForWorkbenchOperation(config *transport_tpg.Config, d *schema.ResourceData, project string, billingProject string, userAgent string, response map[string]interface{}) error { + var opRes map[string]interface{} + err := WorkbenchOperationWaitTimeWithResponse( + config, response, &opRes, project, "Modifying Workbench Instance state", userAgent, + d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return err + } + return nil +} +<% end -%> diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb deleted file mode 100644 index eb44d9657f33..000000000000 --- a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2023 Google Inc. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. --%> -func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return d.Get("gce_setup.0.boot_disk.0.disk_encryption") -} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb deleted file mode 100644 index 70c27a7661e2..000000000000 --- a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2023 Google Inc. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. --%> -func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return d.Get("gce_setup.0.boot_disk.0.kms_key") -} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb deleted file mode 100644 index d93558a3db76..000000000000 --- a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2023 Google Inc. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. --%> -func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return d.Get("gce_setup.0.data_disks.0.disk_encryption") -} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb deleted file mode 100644 index b6a7b9649db0..000000000000 --- a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2023 Google Inc. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. --%> -func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return d.Get("gce_setup.0.data_disks.0.kms_key") -} diff --git a/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb index 2ec579cba8dc..270f73d23abc 100644 --- a/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb +++ b/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb @@ -30,14 +30,14 @@ resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { boot_disk { disk_size_gb = 310 disk_type = "PD_SSD" - disk_encryption = "GMEK" + disk_encryption = "CMEK" kms_key = "<%= ctx[:vars]['key_name'] %>" } data_disks { disk_size_gb = 330 disk_type = "PD_SSD" - disk_encryption = "GMEK" + disk_encryption = "CMEK" kms_key = "<%= ctx[:vars]['key_name'] %>" } @@ -65,4 +65,6 @@ resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { k = "val" } + desired_state = "ACTIVE" + } diff --git a/mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_labels_stopped.tf.erb similarity index 93% rename from mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb rename to mmv1/templates/terraform/examples/workbench_instance_labels_stopped.tf.erb index 3a0d9afda853..78e6c11ce6b7 100644 --- a/mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb +++ b/mmv1/templates/terraform/examples/workbench_instance_labels_stopped.tf.erb @@ -21,4 +21,6 @@ resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { k = "val" } + desired_state = "STOPPED" + } diff --git a/mmv1/templates/terraform/post_create/workbench_instance.go.erb b/mmv1/templates/terraform/post_create/workbench_instance.go.erb index e3a968e4a6b2..25128f95f821 100644 --- a/mmv1/templates/terraform/post_create/workbench_instance.go.erb +++ b/mmv1/templates/terraform/post_create/workbench_instance.go.erb @@ -1,3 +1,13 @@ if err := waitForWorkbenchInstanceActive(d, config, d.Timeout(schema.TimeoutCreate) - time.Minute); err != nil { return fmt.Errorf("Workbench instance %q did not reach ACTIVE state: %q", d.Get("name").(string), err) } + +if p, ok := d.GetOk("desired_state"); ok && p.(string) == "STOPPED" { + dRes, err := modifyWorkbenchInstanceState(config, d, project, billingProject, userAgent, "stop") + if err != nil { + return err + } + if err := waitForWorkbenchOperation(config, d, project, billingProject, userAgent, dRes); err != nil { + return fmt.Errorf("Error stopping Workbench Instance: %s", err) + } +} diff --git a/mmv1/templates/terraform/post_update/workbench_instance.go.erb b/mmv1/templates/terraform/post_update/workbench_instance.go.erb index fa994a3aacb4..cd216f018387 100644 --- a/mmv1/templates/terraform/post_update/workbench_instance.go.erb +++ b/mmv1/templates/terraform/post_update/workbench_instance.go.erb @@ -1,33 +1,18 @@ state := d.Get("state").(string) +desired_state := d.Get("desired_state").(string) -if state != "ACTIVE" { - startURL, err := tpgresource.ReplaceVars(d, config, "{{WorkbenchBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}:start") - if err != nil { - return err +if state != desired_state { + verb := "start" + if desired_state == "STOPPED" { + verb = "stop" } - - log.Printf("[DEBUG] Starting Workbench Instance: %q", name) - - emptyReqBody := make(map[string]interface{}) - - pRes, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ - Config: config, - Method: "POST", - Project: billingProject, - RawURL: startURL, - UserAgent: userAgent, - Body: emptyReqBody, - }) + pRes, err := modifyWorkbenchInstanceState(config, d, project, billingProject, userAgent, verb) if err != nil { - return fmt.Errorf("Error Starting Workbench Instance: %s", err) + return err } - var opResp map[string]interface{} - err = WorkbenchOperationWaitTimeWithResponse( - config, pRes, &opResp, project, "Starting Workbench Instance", userAgent, - d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return fmt.Errorf("Error waiting to start Workbench Instance: %s", err) + if err := waitForWorkbenchOperation(config, d, project, billingProject, userAgent, pRes); err != nil { + return fmt.Errorf("Error waiting to modify Workbench Instance state: %s", err) } } else { diff --git a/mmv1/templates/terraform/pre_update/workbench_instance.go.erb b/mmv1/templates/terraform/pre_update/workbench_instance.go.erb index 2b33205942a7..71ef1d976501 100644 --- a/mmv1/templates/terraform/pre_update/workbench_instance.go.erb +++ b/mmv1/templates/terraform/pre_update/workbench_instance.go.erb @@ -1,34 +1,15 @@ name := d.Get("name").(string) if d.HasChange("gce_setup.0.machine_type") || d.HasChange("gce_setup.0.accelerator_configs") { state := d.Get("state").(string) - if state != "STOPPED" { - stopURL, err := tpgresource.ReplaceVars(d, config, "{{WorkbenchBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}:stop") - if err != nil { - return err - } - - log.Printf("[DEBUG] Stopping Workbench Instance: %q", name) - - emptyReqBody := make(map[string]interface{}) - dRes, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ - Config: config, - Method: "POST", - Project: billingProject, - RawURL: stopURL, - UserAgent: userAgent, - Body: emptyReqBody, - }) + if state != "STOPPED" { + dRes, err := modifyWorkbenchInstanceState(config, d, project, billingProject, userAgent, "stop") if err != nil { - return fmt.Errorf("Error Stopping Workbench Instance: %s", err) + return err } - var opRes map[string]interface{} - err = WorkbenchOperationWaitTimeWithResponse( - config, dRes, &opRes, project, "Stopping Workbench Instance", userAgent, - d.Timeout(schema.TimeoutUpdate)) - if err != nil { - return fmt.Errorf("Error waiting to stop Workbench Instance: %s", err) + if err := waitForWorkbenchOperation(config, d, project, billingProject, userAgent, dRes); err != nil { + return fmt.Errorf("Error stopping Workbench Instance: %s", err) } } else { diff --git a/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb b/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_test.go.erb similarity index 80% rename from mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb rename to mmv1/third_party/terraform/services/workbench/resource_workbench_instance_test.go.erb index c1914881b2a6..42f21d425404 100644 --- a/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb +++ b/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_test.go.erb @@ -270,3 +270,57 @@ resource "google_workbench_instance" "instance" { } `, context) } + +func TestAccWorkbenchInstance_updateState(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkbenchInstance_basic(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels","desired_state"}, + }, + { + Config: testAccWorkbenchInstance_updateState(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels","desired_state"}, + }, + { + Config: testAccWorkbenchInstance_basic(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels","desired_state"}, + }, + }, + }) +} + +func testAccWorkbenchInstance_updateState(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + + desired_state = "STOPPED" + +} +`, context) +}