diff --git a/mmv1/third_party/terraform/resources/resource_compute_instance.go.erb b/mmv1/third_party/terraform/resources/resource_compute_instance.go.erb index a1c301cd7448..07cb9f74f9cd 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_instance.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_instance.go.erb @@ -661,6 +661,28 @@ func resourceComputeInstance() *schema.Resource { }, }, }, + "advanced_machine_features": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: `Controls for advanced machine-related behavior features.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_nested_virtualization": { + Type: schema.TypeBool, + Optional: true, + AtLeastOneOf: []string{"advanced_machine_features.0.enable_nested_virtualization","advanced_machine_features.0.threads_per_core"} + Description: `Whether to enable nested virtualization or not.`, + }, + "threads_per_core": { + Type: schema.TypeInt, + Optional: true, + AtLeastOneOf: []string{"advanced_machine_features.0.enable_nested_virtualization","advanced_machine_features.0.threads_per_core"} + Description: `The number of threads per physical core. To disable simultaneous multithreading (SMT) set this to 1. If unset, the maximum number of threads supported per core by the underlying processor is assumed.`, + }, + }, + }, + }, "confidential_instance_config": { Type: schema.TypeList, MaxItems: 1, @@ -953,6 +975,7 @@ func expandComputeInstance(project string, d *schema.ResourceData, config *Confi Hostname: d.Get("hostname").(string), ForceSendFields: []string{"CanIpForward", "DeletionProtection"}, ConfidentialInstanceConfig: expandConfidentialInstanceConfig(d), + AdvancedMachineFeatures: expandAdvancedMachineFeatures(d), ShieldedInstanceConfig: expandShieldedVmConfigs(d), DisplayDevice: expandDisplayDevice(d), ResourcePolicies: convertStringArr(d.Get("resource_policies").([]interface{})), @@ -1314,6 +1337,9 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("confidential_instance_config", flattenConfidentialInstanceConfig(instance.ConfidentialInstanceConfig)); err != nil { return fmt.Errorf("Error setting confidential_instance_config: %s", err) } + if err := d.Set("advanced_machine_features", flattenAdvancedMachineFeatures(instance.AdvancedMachineFeatures)); err != nil { + return fmt.Errorf("Error setting advanced_machine_config: %s", err) + } if d.Get("desired_status") != "" { if err := d.Set("desired_status", instance.Status); err != nil { return fmt.Errorf("Error setting desired_status: %s", err) @@ -1718,7 +1744,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } } - needToStopInstanceBeforeUpdating := scopesChange || d.HasChange("service_account.0.email") || d.HasChange("machine_type") || d.HasChange("min_cpu_platform") || d.HasChange("enable_display") || d.HasChange("shielded_instance_config") || len(updatesToNIWhileStopped) > 0 || bootRequiredSchedulingChange + needToStopInstanceBeforeUpdating := scopesChange || d.HasChange("service_account.0.email") || d.HasChange("machine_type") || d.HasChange("min_cpu_platform") || d.HasChange("enable_display") || d.HasChange("shielded_instance_config") || len(updatesToNIWhileStopped) > 0 || bootRequiredSchedulingChange || d.HasChange("advanced_machine_features") if d.HasChange("desired_status") && !needToStopInstanceBeforeUpdating { desiredStatus := d.Get("desired_status").(string) @@ -1753,7 +1779,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if statusBeforeUpdate == "RUNNING" && desiredStatus != "TERMINATED" && !d.Get("allow_stopping_for_update").(bool) { return fmt.Errorf("Changing the machine_type, min_cpu_platform, service_account, enable_display, shielded_instance_config, scheduling.node_affinities " + - "or network_interface.[#d].(network/subnetwork/subnetwork_project) on a started instance requires stopping it. " + + "or network_interface.[#d].(network/subnetwork/subnetwork_project) or advanced_machine_config on a started instance requires stopping it. " + "To acknowledge this, please set allow_stopping_for_update = true in your config. " + "You can also stop it by setting desired_status = \"TERMINATED\", but the instance will not be restarted after the update.") } @@ -1877,6 +1903,37 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } } + if d.HasChange("advanced_machine_features") { + err = retry( + func() error { + // retrieve up-to-date instance from the API in case several updates hit simultaneously. instances + // sometimes but not always share metadata fingerprints. + instance, err := config.NewComputeBetaClient(userAgent).Instances.Get(project, zone, instance.Name).Do() + if err != nil { + return fmt.Errorf("Error retrieving instance: %s", err) + } + + instance.AdvancedMachineFeatures = expandAdvancedMachineFeatures(d) + + op, err := config.NewComputeBetaClient(userAgent).Instances.Update(project, zone, instance.Name, instance).Do() + if err != nil { + return fmt.Errorf("Error updating instance: %s", err) + } + + opErr := computeOperationWaitTime(config, op, project, "advanced_machine_features to update", userAgent, d.Timeout(schema.TimeoutUpdate)) + if opErr != nil { + return opErr + } + + return nil + }, + ) + + if err != nil { + return err + } + } + // If the instance stops it can invalidate the fingerprint for network interface. // refresh the instance to get a new fingerprint if len(updatesToNIWhileStopped) > 0 { diff --git a/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb index d14258820288..0ca02bc62b80 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb @@ -925,6 +925,37 @@ func TestAccComputeInstance_scheduling(t *testing.T) { }) } +func TestAccComputeInstance_advancedMachineFeatures(t *testing.T) { + t.Parallel() + + var instance compute.Instance + var instanceName = fmt.Sprintf("tf-test-%s", randString(t, 10)) + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_advancedMachineFeatures(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{"allow_stopping_for_update"}), + { + Config: testAccComputeInstance_advancedMachineFeaturesUpdated(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{"allow_stopping_for_update"}), + }, + }) +} + func TestAccComputeInstance_soleTenantNodeAffinities(t *testing.T) { t.Parallel() @@ -1681,7 +1712,7 @@ func TestAccComputeInstance_updateRunning_desiredStatusRunning_allowStoppingForU }) } -const errorAllowStoppingMsg = "Changing the machine_type, min_cpu_platform, service_account, enable_display, shielded_instance_config, scheduling.node_affinities or network_interface.\\[#d\\].\\(network/subnetwork/subnetwork_project\\) on a started instance requires stopping it. To acknowledge this, please set allow_stopping_for_update = true in your config. You can also stop it by setting desired_status = \"TERMINATED\", but the instance will not be restarted after the update." +const errorAllowStoppingMsg = "Changing the machine_type, min_cpu_platform, service_account, enable_display, shielded_instance_config, scheduling.node_affinities, network_interface.\\[#d\\].\\(network/subnetwork/subnetwork_project\\) or advanced_machine_config on a started instance requires stopping it. To acknowledge this, please set allow_stopping_for_update = true in your config. You can also stop it by setting desired_status = \"TERMINATED\", but the instance will not be restarted after the update." func TestAccComputeInstance_updateRunning_desiredStatusNotSet_notAllowStoppingForUpdate(t *testing.T) { t.Parallel() @@ -4246,6 +4277,64 @@ resource "google_compute_instance" "foobar" { `, instance) } +func testAccComputeInstance_advancedMachineFeatures(instance string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-10" + project = "debian-cloud" +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "n1-standard-2" // Nested Virt isn't supported on E2 and N2Ds https://cloud.google.com/compute/docs/instances/nested-virtualization/overview#restrictions and https://cloud.google.com/compute/docs/instances/disabling-smt#limitations + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + network_interface { + network = "default" + } + + allow_stopping_for_update = true + +} +`, instance) +} + +func testAccComputeInstance_advancedMachineFeaturesUpdated(instance string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-10" + project = "debian-cloud" +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "n1-standard-2" // Nested Virt isn't supported on E2 and N2Ds https://cloud.google.com/compute/docs/instances/nested-virtualization/overview#restrictions and https://cloud.google.com/compute/docs/instances/disabling-smt#limitations + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + network_interface { + network = "default" + } + advanced_machine_features { + threads_per_core = 1 + enable_nested_virtualization = true + } + allow_stopping_for_update = true +} +`, instance) +} + func testAccComputeInstance_subnet_auto(suffix, instance string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { diff --git a/mmv1/third_party/terraform/utils/compute_instance_helpers.go.erb b/mmv1/third_party/terraform/utils/compute_instance_helpers.go.erb index 34d7f0ff6e71..64a853e95bb8 100644 --- a/mmv1/third_party/terraform/utils/compute_instance_helpers.go.erb +++ b/mmv1/third_party/terraform/utils/compute_instance_helpers.go.erb @@ -332,7 +332,6 @@ func expandConfidentialInstanceConfig(d TerraformResourceData) *computeBeta.Conf prefix := "confidential_instance_config.0" return &computeBeta.ConfidentialInstanceConfig{ EnableConfidentialCompute: d.Get(prefix + ".enable_confidential_compute").(bool), - ForceSendFields: []string{"EnableSecureBoot"}, } } @@ -355,7 +354,6 @@ func expandAdvancedMachineFeatures(d TerraformResourceData) *computeBeta.Advance return &computeBeta.AdvancedMachineFeatures{ EnableNestedVirtualization: d.Get(prefix + ".enable_nested_virtualization").(bool), ThreadsPerCore: int64(d.Get(prefix + ".threads_per_core").(int)), - // ForceSendFields: []string{"EnableSecureBoot"}, } } diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index 7f28800d50dd..fdc78698858c 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -176,6 +176,8 @@ The following arguments are supported: * `confidential_instance_config` (Optional) - Enable [Confidential Mode](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) on this VM. +* `advanced_machine_config` (Optional) - Configure Nested Virtualisation and Simultaneous Hyper Threading on this VM. + * `network_performance_config` (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html) Configures network performance settings for the instance. Structure is documented below. **Note**: [`machine_type`](#machine_type) must be a [supported type](https://cloud.google.com/compute/docs/networking/configure-vm-with-high-bandwidth-configuration), @@ -380,6 +382,12 @@ The `confidential_instance_config` block supports: * `enable_confidential_compute` (Optional) Defines whether the instance should have confidential compute enabled. [`on_host_maintenance`](#on_host_maintenance) has to be set to TERMINATE or this will fail to create the VM. +The `advanced_machine_features` block supports: + +* `enable_nested_virtualization` (Optional) Defines whether the instance should have [nested virtualization](#on_host_maintenance) enabled. Defaults to false. + +* `threads_per_core` (Optional) he number of threads per physical core. To disable [simultaneous multithreading (SMT)](https://cloud.google.com/compute/docs/instances/disabling-smt) set this to 1. + The `reservation_affinity` block supports: * `type` - (Required) The type of reservation from which this instance can consume resources. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index 9bb64b080a01..c3abf4b4677e 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -282,7 +282,7 @@ The following arguments are supported: * `confidential_instance_config` (Optional) - Enable [Confidential Mode](https://cloud.google.com/compute/confidential-vm/docs/about-cvm) on this VM. -* `advanced_machine_features` (Optional) - Configure Nested Virtualisation and Simultaneous Hyper Threading on this VM. +* `advanced_machine_features` (Optional) - Configure Nested Virtualisation and Simultaneous Hyper Threading on this VM. The `disk` block supports: @@ -477,7 +477,7 @@ The `network_performance_config` block supports: The `advanced_machine_features` block supports: -* `enable_nested_virtualization` (Optional) Defines whether the instance should have [nested virtualization](#on_host_maintenance) enabled. Defaults to false. +* `enable_nested_virtualization` (Optional) Defines whether the instance should have [nested virtualization](#on_host_maintenance) enabled. Defaults to false. * `threads_per_core` (Optional) he number of threads per physical core. To disable [simultaneous multithreading (SMT)](https://cloud.google.com/compute/docs/instances/disabling-smt) set this to 1.