From da5fffe8f01542fc856c1802834d42d02d03c08a Mon Sep 17 00:00:00 2001 From: nsamartsev Date: Thu, 7 May 2026 23:51:50 +0200 Subject: [PATCH 1/9] Add _v2 expand helpers returning map[string]interface{} for REST migration --- .../compute/compute_instance_helpers.go.tmpl | 234 ++++++++++++++++++ 1 file changed, 234 insertions(+) diff --git a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl index 3863236b923a..5b4ef4977ef5 100644 --- a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl @@ -1221,3 +1221,237 @@ func flattenComputeInstanceSourceEncryptionKey(v *compute.CustomerEncryptionKey) }, } } + +// _v2 expand functions return map[string]interface{} / []interface{} for direct +// HTTP JSON serialization via transport_tpg.SendRequest, replacing Apiary struct usage. + +func expandAliasIpRanges_v2(ranges []interface{}) []interface{} { + ipRanges := make([]interface{}, 0, len(ranges)) + for _, raw := range ranges { + data := raw.(map[string]interface{}) + ipRanges = append(ipRanges, map[string]interface{}{ + "ipCidrRange": data["ip_cidr_range"].(string), + "subnetworkRangeName": data["subnetwork_range_name"].(string), + }) + } + return ipRanges +} + +func expandAccessConfigs_v2(configs []interface{}) []interface{} { + acs := make([]interface{}, len(configs)) + for i, raw := range configs { + ac := map[string]interface{}{ + "type": "ONE_TO_ONE_NAT", + } + if raw != nil { + data := raw.(map[string]interface{}) + ac["natIP"] = data["nat_ip"].(string) + ac["networkTier"] = data["network_tier"].(string) + if ptr, ok := data["public_ptr_domain_name"]; ok && ptr != "" { + ac["setPublicPtr"] = true + ac["publicPtrDomainName"] = ptr.(string) + } + } + acs[i] = ac + } + return acs +} + +func expandIpv6AccessConfigs_v2(configs []interface{}) []interface{} { + iacs := make([]interface{}, len(configs)) + for i, raw := range configs { + iac := map[string]interface{}{ + "type": "DIRECT_IPV6", + } + if raw != nil { + data := raw.(map[string]interface{}) + iac["networkTier"] = data["network_tier"].(string) + if ptr, ok := data["public_ptr_domain_name"]; ok && ptr != "" { + iac["publicPtrDomainName"] = ptr.(string) + } + if eip, ok := data["external_ipv6"]; ok && eip != "" { + iac["externalIpv6"] = eip.(string) + } + if eipl, ok := data["external_ipv6_prefix_length"]; ok && eipl != "" { + if strVal, ok := eipl.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + iac["externalIpv6PrefixLength"] = intVal + } + } + } + if name, ok := data["name"]; ok && name != "" { + iac["name"] = name.(string) + } + } + iacs[i] = iac + } + return iacs +} + +func expandServiceAccounts_v2(configs []interface{}) []interface{} { + accounts := make([]interface{}, len(configs)) + for i, raw := range configs { + data := raw.(map[string]interface{}) + email := data["email"].(string) + if email == "" { + email = "default" + } + accounts[i] = map[string]interface{}{ + "email": email, + "scopes": tpgresource.CanonicalizeServiceScopes(tpgresource.ConvertStringSet(data["scopes"].(*schema.Set))), + } + } + return accounts +} + +func resourceInstanceTags_v2(d tpgresource.TerraformResourceData) map[string]interface{} { + if v := d.Get("tags"); v != nil { + vs := v.(*schema.Set) + items := make([]string, vs.Len()) + for i, v := range vs.List() { + items[i] = v.(string) + } + return map[string]interface{}{ + "items": items, + "fingerprint": d.Get("tags_fingerprint").(string), + } + } + return nil +} + +func expandShieldedVmConfigs_v2(d tpgresource.TerraformResourceData) map[string]interface{} { + if _, ok := d.GetOk("shielded_instance_config"); !ok { + return nil + } + prefix := "shielded_instance_config.0" + return map[string]interface{}{ + "enableSecureBoot": d.Get(prefix + ".enable_secure_boot").(bool), + "enableVtpm": d.Get(prefix + ".enable_vtpm").(bool), + "enableIntegrityMonitoring": d.Get(prefix + ".enable_integrity_monitoring").(bool), + } +} + +func expandConfidentialInstanceConfig_v2(d tpgresource.TerraformResourceData) map[string]interface{} { + if _, ok := d.GetOk("confidential_instance_config"); !ok { + return nil + } + prefix := "confidential_instance_config.0" + return map[string]interface{}{ + "enableConfidentialCompute": d.Get(prefix + ".enable_confidential_compute").(bool), + "confidentialInstanceType": d.Get(prefix + ".confidential_instance_type").(string), + } +} + +func expandAdvancedMachineFeatures_v2(d tpgresource.TerraformResourceData) map[string]interface{} { + if _, ok := d.GetOk("advanced_machine_features"); !ok { + return nil + } + prefix := "advanced_machine_features.0" + return map[string]interface{}{ + "enableNestedVirtualization": d.Get(prefix + ".enable_nested_virtualization").(bool), + "threadsPerCore": int64(d.Get(prefix + ".threads_per_core").(int)), + "turboMode": d.Get(prefix + ".turbo_mode").(string), + "visibleCoreCount": int64(d.Get(prefix + ".visible_core_count").(int)), + "performanceMonitoringUnit": d.Get(prefix + ".performance_monitoring_unit").(string), + "enableUefiNetworking": d.Get(prefix + ".enable_uefi_networking").(bool), + } +} + +func expandDisplayDevice_v2(d tpgresource.TerraformResourceData) map[string]interface{} { + if _, ok := d.GetOk("enable_display"); !ok { + return nil + } + return map[string]interface{}{ + "enableDisplay": d.Get("enable_display").(bool), + } +} + +func expandNetworkPerformanceConfig_v2(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]interface{}, error) { + configs, ok := d.GetOk("network_performance_config") + if !ok { + return nil, nil + } + npcSlice := configs.([]interface{}) + if len(npcSlice) > 1 { + return nil, fmt.Errorf("cannot specify multiple network_performance_configs") + } + if len(npcSlice) == 0 || npcSlice[0] == nil { + return nil, nil + } + npc := npcSlice[0].(map[string]interface{}) + return map[string]interface{}{ + "totalEgressBandwidthTier": npc["total_egress_bandwidth_tier"].(string), + }, nil +} + +func expandComputeInstanceEncryptionKey_v2(d tpgresource.TerraformResourceData) map[string]interface{} { + iek, ok := d.GetOk("instance_encryption_key") + if !ok { + return nil + } + iekRes := iek.([]interface{})[0].(map[string]interface{}) + return map[string]interface{}{ + "kmsKeyName": iekRes["kms_key_self_link"].(string), + "sha256": iekRes["sha256"].(string), + "kmsKeyServiceAccount": iekRes["kms_key_service_account"].(string), + } +} + +func expandComputeInstanceSourceEncryptionKey_v2(d tpgresource.TerraformResourceData, field string) map[string]interface{} { + cek, ok := d.GetOk(field) + if !ok { + return nil + } + cekRes := cek.([]interface{})[0].(map[string]interface{}) + return map[string]interface{}{ + "rsaEncryptedKey": cekRes["rsa_encrypted_key"].(string), + "rawKey": cekRes["raw_key"].(string), + "kmsKeyName": cekRes["kms_key_self_link"].(string), + "sha256": cekRes["sha256"].(string), + "kmsKeyServiceAccount": cekRes["kms_key_service_account"].(string), + } +} + +func expandComputeInstanceGuestOsFeatures_v2(v interface{}) []interface{} { + if v == nil { + return nil + } + var result []interface{} + for _, feature := range v.([]interface{}) { + result = append(result, map[string]interface{}{ + "type": feature.(string), + }) + } + return result +} + +func expandReservationAffinity_v2(d tpgresource.TerraformResourceData) (map[string]interface{}, error) { + _, ok := d.GetOk("reservation_affinity") + if !ok { + return nil, nil + } + + prefix := "reservation_affinity.0" + reservationAffinityType := d.Get(prefix + ".type").(string) + + affinity := map[string]interface{}{ + "consumeReservationType": reservationAffinityType, + } + + _, hasSpecificReservation := d.GetOk(prefix + ".specific_reservation") + if (reservationAffinityType == "SPECIFIC_RESERVATION") != hasSpecificReservation { + return nil, fmt.Errorf("specific_reservation must be set when reservation_affinity is SPECIFIC_RESERVATION, and not set otherwise") + } + + if hasSpecificReservation { + specificPrefix := prefix + ".specific_reservation.0" + var values []string + for _, v := range d.Get(specificPrefix + ".values").([]interface{}) { + values = append(values, v.(string)) + } + affinity["key"] = d.Get(specificPrefix + ".key").(string) + affinity["values"] = values + } + + return affinity, nil +} From 59ad2dfa7e34d8002a0092babe978982059e886f Mon Sep 17 00:00:00 2001 From: nsamartsev Date: Thu, 7 May 2026 23:58:17 +0200 Subject: [PATCH 2/9] add _v2 scheduling and Duration expand helpers for REST migration --- .../compute/compute_instance_helpers.go.tmpl | 221 ++++++++++++++++++ 1 file changed, 221 insertions(+) diff --git a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl index 5b4ef4977ef5..e37c32a5f13e 100644 --- a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl @@ -1455,3 +1455,224 @@ func expandReservationAffinity_v2(d tpgresource.TerraformResourceData) (map[stri return affinity, nil } + +func expandComputeMaxRunDuration_v2(v interface{}) (map[string]interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + original := l[0].(map[string]interface{}) + duration := map[string]interface{}{} + + if nanos := original["nanos"]; reflect.ValueOf(nanos).IsValid() && !tpgresource.IsEmptyValue(reflect.ValueOf(nanos)) { + duration["nanos"] = int64(nanos.(int)) + } + if seconds := original["seconds"]; reflect.ValueOf(seconds).IsValid() && !tpgresource.IsEmptyValue(reflect.ValueOf(seconds)) { + duration["seconds"] = int64(seconds.(int)) + } + return duration, nil +} + +func expandComputeOnInstanceStopAction_v2(v interface{}) (map[string]interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + original := l[0].(map[string]interface{}) + d, ok := original["discard_local_ssd"] + if !ok { + return nil, nil + } + return map[string]interface{}{ + "discardLocalSsd": d.(bool), + }, nil +} + +func expandComputeLocalSsdRecoveryTimeout_v2(v interface{}) (map[string]interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + original := l[0].(map[string]interface{}) + duration := map[string]interface{}{} + + if nanos := original["nanos"]; reflect.ValueOf(nanos).IsValid() && !tpgresource.IsEmptyValue(reflect.ValueOf(nanos)) { + duration["nanos"] = int64(nanos.(int)) + } + if seconds := original["seconds"]; reflect.ValueOf(seconds).IsValid() && !tpgresource.IsEmptyValue(reflect.ValueOf(seconds)) { + duration["seconds"] = int64(seconds.(int)) + } + return duration, nil +} + +{{ if ne $.TargetVersionName `ga` -}} +func expandGracefulShutdownMaxDuration_v2(v interface{}) (map[string]interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + maxDurationMap := l[0].(map[string]interface{}) + // Always include seconds to mirror ForceSendFields["Seconds"] in the Apiary version. + duration := map[string]interface{}{ + "seconds": int64(maxDurationMap["seconds"].(int)), + } + if nanos := maxDurationMap["nanos"]; reflect.ValueOf(nanos).IsValid() && !tpgresource.IsEmptyValue(reflect.ValueOf(nanos)) { + duration["nanos"] = int64(nanos.(int)) + } + return duration, nil +} + +func expandGracefulShutdown_v2(v interface{}) (map[string]interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + original := l[0].(map[string]interface{}) + gracefulShutdown := map[string]interface{}{ + "enabled": original["enabled"].(bool), + } + maxDuration, err := expandGracefulShutdownMaxDuration_v2(original["max_duration"].([]interface{})) + if err != nil { + return nil, err + } + if maxDuration != nil { + gracefulShutdown["maxDuration"] = maxDuration + } + return gracefulShutdown, nil +} + +func expandComputePreemptionNoticeDuration_v2(v interface{}) (map[string]interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + original := l[0].(map[string]interface{}) + duration := map[string]interface{}{} + if nanos, ok := original["nanos"]; ok && nanos != nil { + duration["nanos"] = int64(nanos.(int)) + } + if seconds, ok := original["seconds"]; ok && seconds != nil { + duration["seconds"] = int64(seconds.(int)) + } + return duration, nil +} +{{- end }} + +func expandScheduling_v2(v interface{}) (map[string]interface{}, error) { + if v == nil { + return map[string]interface{}{"automaticRestart": true}, nil + } + ls := v.([]interface{}) + if len(ls) == 0 { + return map[string]interface{}{"automaticRestart": true}, nil + } + if len(ls) > 1 || ls[0] == nil { + return nil, fmt.Errorf("expected exactly one scheduling block") + } + + original := ls[0].(map[string]interface{}) + scheduling := map[string]interface{}{} + + if v, ok := original["automatic_restart"]; ok { + scheduling["automaticRestart"] = v.(bool) + } + if v, ok := original["preemptible"]; ok { + scheduling["preemptible"] = v.(bool) + } + if v, ok := original["on_host_maintenance"]; ok { + scheduling["onHostMaintenance"] = v.(string) + } + if v, ok := original["node_affinities"]; ok && v != nil { + naSet := v.(*schema.Set).List() + nodeAffinities := make([]interface{}, 0, len(naSet)) + for _, nodeAffRaw := range naSet { + if nodeAffRaw == nil { + continue + } + nodeAff := nodeAffRaw.(map[string]interface{}) + nodeAffinities = append(nodeAffinities, map[string]interface{}{ + "key": nodeAff["key"].(string), + "operator": nodeAff["operator"].(string), + "values": tpgresource.ConvertStringArr(nodeAff["values"].(*schema.Set).List()), + }) + } + scheduling["nodeAffinities"] = nodeAffinities + } + if v, ok := original["min_node_cpus"]; ok { + scheduling["minNodeCpus"] = int64(v.(int)) + } + if v, ok := original["provisioning_model"]; ok { + scheduling["provisioningModel"] = v.(string) + } + if v, ok := original["instance_termination_action"]; ok { + scheduling["instanceTerminationAction"] = v.(string) + } + if v, ok := original["availability_domain"]; ok && v != nil { + scheduling["availabilityDomain"] = int64(v.(int)) + } + if v, ok := original["max_run_duration"]; ok { + transformed, err := expandComputeMaxRunDuration_v2(v) + if err != nil { + return nil, err + } + if transformed != nil { + scheduling["maxRunDuration"] = transformed + } + } + if v, ok := original["on_instance_stop_action"]; ok { + transformed, err := expandComputeOnInstanceStopAction_v2(v) + if err != nil { + return nil, err + } + if transformed != nil { + scheduling["onInstanceStopAction"] = transformed + } + } +{{- if ne $.TargetVersionName "ga" }} + if v, ok := original["host_error_timeout_seconds"]; ok { + // API bug: SetScheduling doesn't clear this field when set to 0; send null explicitly. + if v == 0 || v == nil { + scheduling["hostErrorTimeoutSeconds"] = nil + } else { + scheduling["hostErrorTimeoutSeconds"] = int64(v.(int)) + } + } + if v, ok := original["maintenance_interval"]; ok { + scheduling["maintenanceInterval"] = v.(string) + } + if v, ok := original["graceful_shutdown"]; ok { + transformed, err := expandGracefulShutdown_v2(v) + if err != nil { + return nil, err + } + if transformed != nil { + scheduling["gracefulShutdown"] = transformed + } + } + if v, ok := original["skip_guest_os_shutdown"]; ok { + scheduling["skipGuestOsShutdown"] = v.(bool) + } + if v, ok := original["preemption_notice_duration"]; ok { + transformed, err := expandComputePreemptionNoticeDuration_v2(v) + if err != nil { + return nil, err + } + if transformed != nil { + scheduling["preemptionNoticeDuration"] = transformed + } + } +{{- end }} + if v, ok := original["local_ssd_recovery_timeout"]; ok { + transformed, err := expandComputeLocalSsdRecoveryTimeout_v2(v) + if err != nil { + return nil, err + } + if transformed != nil { + scheduling["localSsdRecoveryTimeout"] = transformed + } + } + if v, ok := original["termination_time"]; ok { + scheduling["terminationTime"] = v.(string) + } + return scheduling, nil +} From 0692ed9948fc03234f6727c555e7a4ccfc085d5f Mon Sep 17 00:00:00 2001 From: nsamartsev Date: Fri, 8 May 2026 00:01:26 +0200 Subject: [PATCH 3/9] Add expandNetworkInterfaces_v2 completing helpers migration --- .../compute/compute_instance_helpers.go.tmpl | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl index e37c32a5f13e..54769d688ee0 100644 --- a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl @@ -1676,3 +1676,56 @@ func expandScheduling_v2(v interface{}) (map[string]interface{}, error) { } return scheduling, nil } + +func expandNetworkInterfaces_v2(d tpgresource.TerraformResourceData, config *transport_tpg.Config) ([]interface{}, error) { + configs := d.Get("network_interface").([]interface{}) + ifaces := make([]interface{}, len(configs)) + for i, raw := range configs { + data := raw.(map[string]interface{}) + + var networkAttachment string + network := data["network"].(string) + subnetwork := data["subnetwork"].(string) + if networkAttachmentObj, ok := data["network_attachment"]; ok { + networkAttachment = networkAttachmentObj.(string) + } + if networkAttachment == "" && network == "" && subnetwork == "" { + return nil, fmt.Errorf("exactly one of network, subnetwork, or network_attachment must be provided") + } + + nf, err := tpgresource.ParseNetworkFieldValue(network, d, config) + if err != nil { + return nil, fmt.Errorf("cannot determine self_link for network %q: %s", network, err) + } + + subnetProjectField := fmt.Sprintf("network_interface.%d.subnetwork_project", i) + sf, err := tpgresource.ParseSubnetworkFieldValueWithProjectField(subnetwork, subnetProjectField, d, config) + if err != nil { + return nil, fmt.Errorf("cannot determine self_link for subnetwork %q: %s", subnetwork, err) + } + + iface := map[string]interface{}{ + "networkIP": data["network_ip"].(string), + "network": nf.RelativeLink(), + "networkAttachment": networkAttachment, + "vlan": int64(data["vlan"].(int)), + "subnetwork": sf.RelativeLink(), + "accessConfigs": expandAccessConfigs_v2(data["access_config"].([]interface{})), + "aliasIpRanges": expandAliasIpRanges_v2(data["alias_ip_range"].([]interface{})), + "nicType": data["nic_type"].(string), + "stackType": data["stack_type"].(string), + "queueCount": int64(data["queue_count"].(int)), + "ipv6AccessConfigs": expandIpv6AccessConfigs_v2(data["ipv6_access_config"].([]interface{})), + "ipv6Address": data["ipv6_address"].(string), + "internalIpv6PrefixLength": int64(data["internal_ipv6_prefix_length"].(int)), + "igmpQuery": data["igmp_query"].(string), + } +{{- if ne $.TargetVersionName "ga" }} + if macAddress, ok := data["mac_address"]; ok { + iface["macAddress"] = macAddress.(string) + } +{{- end }} + ifaces[i] = iface + } + return ifaces, nil +} From 96198fb570bd8c8aba184bd7fa70357d9bdd83d7 Mon Sep 17 00:00:00 2001 From: nsamartsev Date: Fri, 8 May 2026 00:51:51 +0200 Subject: [PATCH 4/9] Migrate apiary calls --- .../compute/resource_compute_instance.go.tmpl | 416 +++++++++++++----- 1 file changed, 303 insertions(+), 113 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index 1a3e3c2b7d61..ed770dea00a7 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -1900,6 +1900,115 @@ func expandComputeInstance(project string, d *schema.ResourceData, config *trans }, nil } +// expandComputeInstance_v2 builds the instance request body as map[string]interface{} +// for direct serialization via transport_tpg.SendRequest. +// Disk-related fields (expandBootDisk, expandScratchDisks, expandAttachedDisk) are not yet +// migrated; they serialize correctly via encoding/json since none use ForceSendFields. +func expandComputeInstance_v2(project string, d *schema.ResourceData, config *transport_tpg.Config) (map[string]interface{}, error) { + var machineTypeUrl string + if mt, ok := d.GetOk("machine_type"); ok { + machineType, err := tpgresource.ParseMachineTypesFieldValue(mt.(string), d, config) + if err != nil { + return nil, fmt.Errorf("Error loading machine type: %s", err) + } + machineTypeUrl = machineType.RelativeLink() + } + + var disks []interface{} + if _, hasBootDisk := d.GetOk("boot_disk"); hasBootDisk { + bootDisk, err := expandBootDisk(d, config, project) + if err != nil { + return nil, err + } + disks = append(disks, bootDisk) + } + if _, hasScratchDisk := d.GetOk("scratch_disk"); hasScratchDisk { + scratchDisks, err := expandScratchDisks(d, config, project) + if err != nil { + return nil, err + } + for _, sd := range scratchDisks { + disks = append(disks, sd) + } + } + for i := 0; i < d.Get("attached_disk.#").(int); i++ { + diskConfig := d.Get(fmt.Sprintf("attached_disk.%d", i)).(map[string]interface{}) + disk, err := expandAttachedDisk(diskConfig, d, config) + if err != nil { + return nil, err + } + disks = append(disks, disk) + } + + scheduling, err := expandScheduling_v2(d.Get("scheduling")) + if err != nil { + return nil, fmt.Errorf("Error creating scheduling: %s", err) + } + params, err := expandParams(d) + if err != nil { + return nil, fmt.Errorf("Error creating params: %s", err) + } + metadata, err := resourceInstanceMetadata(d) + if err != nil { + return nil, fmt.Errorf("Error creating metadata: %s", err) + } + {{ if ne $.TargetVersionName `ga` -}} + partnerMetadataMap, err := resourceInstancePartnerMetadata(d) + if err != nil { + return nil, fmt.Errorf("Error creating partner metadata: %s", err) + } + {{- end }} + networkInterfaces, err := expandNetworkInterfaces_v2(d, config) + if err != nil { + return nil, fmt.Errorf("Error creating network interfaces: %s", err) + } + networkPerformanceConfig, err := expandNetworkPerformanceConfig_v2(d, config) + if err != nil { + return nil, fmt.Errorf("Error creating network performance config: %s", err) + } + accels, err := expandInstanceGuestAccelerators(d, config) + if err != nil { + return nil, fmt.Errorf("Error creating guest accelerators: %s", err) + } + reservationAffinity, err := expandReservationAffinity_v2(d) + if err != nil { + return nil, fmt.Errorf("Error creating reservation affinity: %s", err) + } + + instance := map[string]interface{}{ + "canIpForward": d.Get("can_ip_forward").(bool), + "description": d.Get("description").(string), + "disks": disks, + "machineType": machineTypeUrl, + "metadata": metadata, + "name": d.Get("name").(string), + "networkInterfaces": networkInterfaces, + "networkPerformanceConfig": networkPerformanceConfig, + "tags": resourceInstanceTags_v2(d), + "params": params, + "labels": tpgresource.ExpandEffectiveLabels(d), + "serviceAccounts": expandServiceAccounts_v2(d.Get("service_account").([]interface{})), + "guestAccelerators": accels, + "minCpuPlatform": d.Get("min_cpu_platform").(string), + "scheduling": scheduling, + "deletionProtection": d.Get("deletion_protection").(bool), + "hostname": d.Get("hostname").(string), + "confidentialInstanceConfig": expandConfidentialInstanceConfig_v2(d), + "advancedMachineFeatures": expandAdvancedMachineFeatures_v2(d), + "shieldedInstanceConfig": expandShieldedVmConfigs_v2(d), + "displayDevice": expandDisplayDevice_v2(d), + "resourcePolicies": tpgresource.ConvertStringArr(d.Get("resource_policies").([]interface{})), + "reservationAffinity": reservationAffinity, + "keyRevocationActionType": d.Get("key_revocation_action_type").(string), + "instanceEncryptionKey": expandComputeInstanceEncryptionKey_v2(d), + } +{{- if ne $.TargetVersionName `ga` }} + instance["eraseWindowsVssSignature"] = d.Get("erase_windows_vss_signature").(bool) + instance["partnerMetadata"] = partnerMetadataMap +{{- end }} + return instance, nil +} + var computeInstanceStatus = []string{ "PROVISIONING", "REPAIRING", @@ -1925,6 +2034,7 @@ func getAllStatusBut(status string) []string { func changeInstanceStatusOnCreation(config *transport_tpg.Config, d *schema.ResourceData, project, zone, status, userAgent string) error { var res map[string]interface{} var err error + name := d.Get("name").(string) if status == "TERMINATED" { var url string url, err = tpgresource.ReplaceVars(d, config, "{{"{{"}}ComputeBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/zones/{{"{{"}}zone{{"}}"}}/instances/{{"{{"}}name{{"}}"}}/stop") @@ -2023,7 +2133,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error loading zone '%s': %s", z, err) } - instance, err := expandComputeInstance(project, d, config) + instanceBody, err := expandComputeInstance_v2(project, d, config) if err != nil { return err } @@ -2057,7 +2167,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err } // Store the ID now - d.SetId(fmt.Sprintf("projects/%s/zones/%s/instances/%s", project, z, instance.Name)) + d.SetId(fmt.Sprintf("projects/%s/zones/%s/instances/%s", project, z, d.Get("name").(string))) // Wait for the operation to complete waitErr := ComputeOperationWaitTime(config, res, project, "instance to create", userAgent, d.Timeout(schema.TimeoutCreate)) @@ -2068,7 +2178,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err } {{ if ne $.TargetVersionName `ga` -}} - err = computeInstanceAddSecurityPolicy(d, config, securityPolicies, project, z, userAgent, instance.Name) + err = computeInstanceAddSecurityPolicy(d, config, securityPolicies, project, z, userAgent, d.Get("name").(string)) if err != nil { return fmt.Errorf("Error creating instance while setting the security policies: %s", err) } @@ -2464,10 +2574,19 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("Error retrieving instance: %s", err) } - - instance.Description = d.Get("description").(string) - - op, err := NewClient(config, userAgent).Instances.Update(project, zone, instance.Name, instance).Do() + instanceMap, err := tpgresource.ConvertToMap(instance) + if err != nil { + return fmt.Errorf("Error converting instance: %s", err) + } + instanceMap["description"] = d.Get("description").(string) + op, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PUT", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + Body: instanceMap, + }) if err != nil { return fmt.Errorf("Error updating instance: %s", err) } @@ -2491,10 +2610,9 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("Error parsing metadata: %s", err) } - - metadataV1 := &compute.Metadata{} - if err := tpgresource.Convert(metadata, metadataV1); err != nil { - return err + metadataMap, err := tpgresource.ConvertToMap(metadata) + if err != nil { + return fmt.Errorf("Error converting metadata: %s", err) } // We're retrying for an error 412 where the metadata fingerprint is out of date @@ -2507,9 +2625,16 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error retrieving metadata: %s", err) } - metadataV1.Fingerprint = instance.Metadata.Fingerprint + metadataMap["fingerprint"] = instance.Metadata.Fingerprint - op, err := NewClient(config, userAgent).Instances.SetMetadata(project, zone, instance.Name, metadataV1).Do() + op, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/setMetadata", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + Body: metadataMap, + }) if err != nil { return fmt.Errorf("Error updating metadata: %s", err) } @@ -2536,16 +2661,30 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("Error retrieving partner_metadata: %s", err) } - instance.Fingerprint = instance.Fingerprint patchedPM := resourceInstancePatchPartnerMetadata(d, convertPartnerMetadataFromCompute(instance.PartnerMetadata)) - computePM, err := convertPartnerMetadataToCompute(patchedPM) + // Deleted namespaces have nil values; convert to {} so the API clears them. + partnerMetadataBody := make(map[string]interface{}) + for k, v := range patchedPM { + if v == nil { + partnerMetadataBody[k] = map[string]interface{}{} + } else { + partnerMetadataBody[k] = v + } + } + instanceMap, err := tpgresource.ConvertToMap(instance) if err != nil { - return fmt.Errorf("Error converting partner metadata: %s", err) + return fmt.Errorf("Error converting instance: %s", err) } - instance.PartnerMetadata = computePM - instance.NullFields = []string{"partnerMetadata"} + instanceMap["partnerMetadata"] = partnerMetadataBody - op, err := NewClient(config, userAgent).Instances.Update(project, zone, instance.Name, instance).Do() + op, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PUT", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + Body: instanceMap, + }) if err != nil { return fmt.Errorf("Error updating partner_metadata: %s", err) } @@ -2634,15 +2773,27 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("Error retrieving instance: %s", err) } - params, err := expandParams(d) if err != nil { return fmt.Errorf("Error updating params: %s", err) } - - instance.Params = params - - op, err := NewClient(config, userAgent).Instances.Update(project, zone, instance.Name, instance).Do() + paramsMap, err := tpgresource.ConvertToMap(params) + if err != nil { + return fmt.Errorf("Error converting params: %s", err) + } + instanceMap, err := tpgresource.ConvertToMap(instance) + if err != nil { + return fmt.Errorf("Error converting instance: %s", err) + } + instanceMap["params"] = paramsMap + op, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PUT", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + Body: instanceMap, + }) if err != nil { return fmt.Errorf("Error updating instance: %s", err) } @@ -2725,7 +2876,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err bootRequiredSchedulingChange := schedulingHasChangeRequiringReboot(d) bootNotRequiredSchedulingChange := schedulingHasChangeWithoutReboot(d) if bootNotRequiredSchedulingChange { - scheduling, err := expandScheduling(d.Get("scheduling")) + scheduling, err := expandScheduling_v2(d.Get("scheduling")) if err != nil { return fmt.Errorf("Error creating request data to update scheduling: %s", err) } @@ -2758,7 +2909,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } } - networkInterfaces, err := expandNetworkInterfaces(d, config) + networkInterfaces, err := expandNetworkInterfaces_v2(d, config) if err != nil { return fmt.Errorf("Error getting network interface from config: %s", err) } @@ -2795,11 +2946,11 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err var updatesToNIWhileStopped []func(inst map[string]interface{}) error for i := 0; i < len(networkInterfaces); i++ { prefix := fmt.Sprintf("network_interface.%d", i) - networkInterface := networkInterfaces[i] + networkInterface := networkInterfaces[i].(map[string]interface{}) instNetworkInterface := instance.NetworkInterfaces[i] networkName := d.Get(prefix + ".name").(string) - subnetwork := networkInterface.Subnetwork + subnetwork := networkInterface["subnetwork"].(string) updateDuringStop := d.HasChange(prefix+".subnetwork") || d.HasChange(prefix+".network") || d.HasChange(prefix+".subnetwork_project") // Sanity check @@ -2829,7 +2980,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("Cannot determine self_link for network %q: %s", resp.Network, err) } - networkInterface.Network = nf.RelativeLink() + networkInterface["network"] = nf.RelativeLink() } } @@ -2851,14 +3002,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } // Create new ones - acMaps := make([]interface{}, len(networkInterface.AccessConfigs)) - for j, ac := range networkInterface.AccessConfigs { - acMap, err := tpgresource.ConvertToMap(ac) - if err != nil { - return fmt.Errorf("Error converting access config to map: %w", err) - } - acMaps[j] = acMap - } + acMaps := networkInterface["accessConfigs"].([]interface{}) err = computeInstanceAddAccessConfigs(d, config, instNiMap, acMaps, project, zone, userAgent, instance.Name) if err != nil { return err @@ -2918,9 +3062,9 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err instNetworkInterface = instance.NetworkInterfaces[i] } - networkInterfacePatchObj := &compute.NetworkInterface{ - AliasIpRanges: networkInterface.AliasIpRanges, - Fingerprint: instNetworkInterface.Fingerprint, + networkInterfacePatchObj := map[string]interface{}{ + "aliasIpRanges": networkInterface["aliasIpRanges"].([]interface{}), + "fingerprint": instNetworkInterface.Fingerprint, } niBody, err := tpgresource.ConvertToMap(networkInterfacePatchObj) if err != nil { @@ -2952,10 +3096,9 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } if !updateDuringStop && d.HasChange(prefix+".stack_type") { - - networkInterfacePatchObj := &compute.NetworkInterface{ - StackType: d.Get(prefix+".stack_type").(string), - Fingerprint: instNetworkInterface.Fingerprint, + networkInterfacePatchObj := map[string]interface{}{ + "stackType": d.Get(prefix + ".stack_type").(string), + "fingerprint": instNetworkInterface.Fingerprint, } niBody, err := tpgresource.ConvertToMap(networkInterfacePatchObj) if err != nil { @@ -2987,10 +3130,9 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } if !updateDuringStop && d.HasChange(prefix+".igmp_query") { - - networkInterfacePatchObj := &compute.NetworkInterface{ - IgmpQuery: d.Get(prefix+".igmp_query").(string), - Fingerprint: instNetworkInterface.Fingerprint, + networkInterfacePatchObj := map[string]interface{}{ + "igmpQuery": d.Get(prefix + ".igmp_query").(string), + "fingerprint": instNetworkInterface.Fingerprint, } niBody, err := tpgresource.ConvertToMap(networkInterfacePatchObj) if err != nil { @@ -3022,10 +3164,9 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } if !updateDuringStop && d.HasChange(prefix+".ipv6_address") { - - networkInterfacePatchObj := &compute.NetworkInterface{ - Ipv6Address: d.Get(prefix+".ipv6_address").(string), - Fingerprint: instNetworkInterface.Fingerprint, + networkInterfacePatchObj := map[string]interface{}{ + "ipv6Address": d.Get(prefix + ".ipv6_address").(string), + "fingerprint": instNetworkInterface.Fingerprint, } niBody, err := tpgresource.ConvertToMap(networkInterfacePatchObj) if err != nil { @@ -3057,10 +3198,9 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } if !updateDuringStop && d.HasChange(prefix+".internal_ipv6_prefix_length") { - - networkInterfacePatchObj := &compute.NetworkInterface{ - InternalIpv6PrefixLength: d.Get(prefix+".internal_ipv6_prefix_length").(int64), - Fingerprint: instNetworkInterface.Fingerprint, + networkInterfacePatchObj := map[string]interface{}{ + "internalIpv6PrefixLength": int64(d.Get(prefix + ".internal_ipv6_prefix_length").(int)), + "fingerprint": instNetworkInterface.Fingerprint, } niBody, err := tpgresource.ConvertToMap(networkInterfacePatchObj) if err != nil { @@ -3093,24 +3233,26 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if updateDuringStop { // Lets be explicit about what we are changing in the patch call - networkInterfacePatchObj := &compute.NetworkInterface{ - Network: networkInterface.Network, - Subnetwork: networkInterface.Subnetwork, - AliasIpRanges: networkInterface.AliasIpRanges, + networkInterfacePatchObj := map[string]interface{}{ + "network": networkInterface["network"].(string), + "subnetwork": networkInterface["subnetwork"].(string), + } + if aliasIps, ok := networkInterface["aliasIpRanges"].([]interface{}); ok && len(aliasIps) > 0 { + networkInterfacePatchObj["aliasIpRanges"] = aliasIps } // network_ip can be inferred if not declared. Let's only patch if it's being changed by user // otherwise this could fail if the network ip is not compatible with the new Subnetwork/Network. if d.HasChange(prefix + ".network_ip") { - networkInterfacePatchObj.NetworkIP = networkInterface.NetworkIP + networkInterfacePatchObj["networkIP"] = networkInterface["networkIP"].(string) } if d.HasChange(prefix+".internal_ipv6_prefix_length") { - networkInterfacePatchObj.Ipv6Address = networkInterface.Ipv6Address + networkInterfacePatchObj["ipv6Address"] = networkInterface["ipv6Address"].(string) } if d.HasChange(prefix+".ipv6_address") { - networkInterfacePatchObj.Ipv6Address = networkInterface.Ipv6Address + networkInterfacePatchObj["ipv6Address"] = networkInterface["ipv6Address"].(string) } // Access config can run into some issues since we can't tell the difference between @@ -3119,21 +3261,8 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err // with the subnetwork/network we are transitioning to. Due to this we only change access // configs if we notice the configuration (user intent) changes. accessConfigsHaveChanged := d.HasChange(prefix + ".access_config") - - acMaps := make([]interface{}, len(networkInterface.AccessConfigs)) - for j, ac := range networkInterface.AccessConfigs { - acMap, err := tpgresource.ConvertToMap(ac) - if err != nil { - return fmt.Errorf("Error converting access config to map: %w", err) - } - acMaps[j] = acMap - } - niPatchMap, err := tpgresource.ConvertToMap(networkInterfacePatchObj) - if err != nil { - return fmt.Errorf("Error converting network interface patch object to map: %w", err) - } - - updateCall := computeInstanceCreateUpdateWhileStoppedCall(d, config, niPatchMap, acMaps, accessConfigsHaveChanged, i, project, zone, userAgent, instance.Name) + acMaps := networkInterface["accessConfigs"].([]interface{}) + updateCall := computeInstanceCreateUpdateWhileStoppedCall(d, config, networkInterfacePatchObj, acMaps, accessConfigsHaveChanged, i, project, zone, userAgent, instance.Name) updatesToNIWhileStopped = append(updatesToNIWhileStopped, updateCall) } } @@ -3380,10 +3509,19 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("Error retrieving instance: %s", err) } - - instance.CanIpForward = d.Get("can_ip_forward").(bool) - - op, err := NewClient(config, userAgent).Instances.Update(project, zone, instance.Name, instance).Do() + instanceMap, err := tpgresource.ConvertToMap(instance) + if err != nil { + return fmt.Errorf("Error converting instance: %s", err) + } + instanceMap["canIpForward"] = d.Get("can_ip_forward").(bool) + op, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PUT", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + Body: instanceMap, + }) if err != nil { return fmt.Errorf("Error updating instance: %s", err) } @@ -3409,15 +3547,17 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err previousStatus, desiredStatus := d.GetChange("desired_status") if desiredStatus != "" { - var op *compute.Operation + var op interface{} if desiredStatus == "RUNNING" { if previousStatus == "SUSPENDED" { -{{- if ne $.TargetVersionName "ga" }} - op, err = NewClient(config, userAgent).Instances.Resume(project, zone, instance.Name, &compute.InstancesResumeRequest{}).Do() -{{- else }} - op, err = NewClient(config, userAgent).Instances.Resume(project, zone, instance.Name).Do() -{{- end }} + op, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/resume", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + }) if err != nil { return err } @@ -3428,12 +3568,24 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } } } else if desiredStatus == "TERMINATED" { - op, err = NewClient(config, userAgent).Instances.Stop(project, zone, instance.Name).Do() + op, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/stop", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + }) if err != nil { return err } } else if desiredStatus == "SUSPENDED" { - op, err = NewClient(config, userAgent).Instances.Suspend(project, zone, instance.Name).Do() + op, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/suspend", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + }) if err != nil { return err } @@ -3546,11 +3698,11 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if d.HasChange("service_account.0.email") || scopesChange { sa := d.Get("service_account").([]interface{}) - req := &compute.InstancesSetServiceAccountRequest{ForceSendFields: []string{"email"}} + saBody := map[string]interface{}{"email": ""} if !isEmptyServiceAccountBlock(d) && len(sa) > 0 && sa[0] != nil { saMap := sa[0].(map[string]interface{}) - req.Email = saMap["email"].(string) - req.Scopes = tpgresource.CanonicalizeServiceScopes(tpgresource.ConvertStringSet(saMap["scopes"].(*schema.Set))) + saBody["email"] = saMap["email"].(string) + saBody["scopes"] = tpgresource.CanonicalizeServiceScopes(tpgresource.ConvertStringSet(saMap["scopes"].(*schema.Set))) } body, err := tpgresource.ConvertToMap(req) if err != nil { @@ -3638,7 +3790,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } if bootRequiredSchedulingChange { - scheduling, err := expandScheduling(d.Get("scheduling")) + scheduling, err := expandScheduling_v2(d.Get("scheduling")) if err != nil { return fmt.Errorf("Error creating request data to update scheduling: %s", err) } @@ -3680,10 +3832,19 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("Error retrieving instance: %s", err) } - - instance.AdvancedMachineFeatures = expandAdvancedMachineFeatures(d) - - op, err := NewClient(config, userAgent).Instances.Update(project, zone, instance.Name, instance).Do() + instanceMap, err := tpgresource.ConvertToMap(instance) + if err != nil { + return fmt.Errorf("Error converting instance: %s", err) + } + instanceMap["advancedMachineFeatures"] = expandAdvancedMachineFeatures_v2(d) + op, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PUT", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + Body: instanceMap, + }) if err != nil { return fmt.Errorf("Error updating instance: %s", err) } @@ -3750,7 +3911,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err return resourceComputeInstanceRead(d, meta) } -func startInstanceOperation(d *schema.ResourceData, config *transport_tpg.Config) (*compute.Operation, error) { +func startInstanceOperation(d *schema.ResourceData, config *transport_tpg.Config) (interface{}, error) { project, err := tpgresource.GetProject(d, config) if err != nil { return nil, err @@ -3761,7 +3922,7 @@ func startInstanceOperation(d *schema.ResourceData, config *transport_tpg.Config return nil, err } - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return nil, err } @@ -3779,25 +3940,36 @@ func startInstanceOperation(d *schema.ResourceData, config *transport_tpg.Config return nil, err } - var encrypted []*compute.CustomerEncryptionKeyProtectedDisk + var encryptedDisks []interface{} for _, disk := range instanceFromConfig.Disks { if disk.DiskEncryptionKey != nil { - key := compute.CustomerEncryptionKey{RawKey: disk.DiskEncryptionKey.RawKey, KmsKeyName: disk.DiskEncryptionKey.KmsKeyName} - eDisk := compute.CustomerEncryptionKeyProtectedDisk{Source: disk.Source, DiskEncryptionKey: &key} - encrypted = append(encrypted, &eDisk) + encryptedDisks = append(encryptedDisks, map[string]interface{}{ + "source": disk.Source, + "diskEncryptionKey": map[string]interface{}{ + "rawKey": disk.DiskEncryptionKey.RawKey, + "kmsKeyName": disk.DiskEncryptionKey.KmsKeyName, + }, + }) } } - var op *compute.Operation - - if len(encrypted) > 0 { - request := compute.InstancesStartWithEncryptionKeyRequest{Disks: encrypted} - op, err = NewClient(config, userAgent).Instances.StartWithEncryptionKey(project, zone, instance.Name, &request).Do() - } else { - op, err = NewClient(config, userAgent).Instances.Start(project, zone, instance.Name).Do() + if len(encryptedDisks) > 0 { + return transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/startWithEncryptionKey", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + Body: map[string]interface{}{"disks": encryptedDisks}, + }) } - - return op, err + return transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/start", config.ComputeBasePath, project, zone, instance.Name), + UserAgent: userAgent, + }) } func expandAttachedDisk(diskConfig map[string]interface{}, d *schema.ResourceData, meta interface{}) (*compute.AttachedDisk, error) { @@ -4485,6 +4657,24 @@ func CheckForCommonAliasIp(old, new *compute.NetworkInterface) []*compute.AliasI return resultAliasIpRanges } +func CheckForCommonAliasIp_v2(old *compute.NetworkInterface, newAliasIpRanges []interface{}) []interface{} { + newAliasIpMap := make(map[string]bool) + for _, raw := range newAliasIpRanges { + if m, ok := raw.(map[string]interface{}); ok { + if cidr, ok := m["ipCidrRange"].(string); ok { + newAliasIpMap[cidr] = true + } + } + } + result := make([]interface{}, 0) + for _, val := range old.AliasIpRanges { + if newAliasIpMap[val.IpCidrRange] { + result = append(result, map[string]interface{}{"ipCidrRange": val.IpCidrRange}) + } + } + return result +} + func updateDisk(d *schema.ResourceData, config *transport_tpg.Config, userAgent, project, patchUrl string, obj map[string]interface{}) error { billingProject := project url, err := tpgresource.ReplaceVars(d, config, patchUrl) From 98211e829c5882ac6e933f311774a39e187a8d79 Mon Sep 17 00:00:00 2001 From: nsamartsev Date: Fri, 8 May 2026 05:07:55 +0200 Subject: [PATCH 5/9] Replace apiary calls --- .../compute/compute_instance_helpers.go.tmpl | 166 +++++++++++++----- .../compute/resource_compute_instance.go.tmpl | 52 ++++-- ...e_instance_from_machine_image_test.go.tmpl | 10 +- 3 files changed, 167 insertions(+), 61 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl index 54769d688ee0..2a068b8eb37c 100644 --- a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl @@ -1229,10 +1229,13 @@ func expandAliasIpRanges_v2(ranges []interface{}) []interface{} { ipRanges := make([]interface{}, 0, len(ranges)) for _, raw := range ranges { data := raw.(map[string]interface{}) - ipRanges = append(ipRanges, map[string]interface{}{ - "ipCidrRange": data["ip_cidr_range"].(string), - "subnetworkRangeName": data["subnetwork_range_name"].(string), - }) + entry := map[string]interface{}{ + "ipCidrRange": data["ip_cidr_range"].(string), + } + if v := data["subnetwork_range_name"].(string); v != "" { + entry["subnetworkRangeName"] = v + } + ipRanges = append(ipRanges, entry) } return ipRanges } @@ -1245,8 +1248,12 @@ func expandAccessConfigs_v2(configs []interface{}) []interface{} { } if raw != nil { data := raw.(map[string]interface{}) - ac["natIP"] = data["nat_ip"].(string) - ac["networkTier"] = data["network_tier"].(string) + if v := data["nat_ip"].(string); v != "" { + ac["natIP"] = v + } + if v := data["network_tier"].(string); v != "" { + ac["networkTier"] = v + } if ptr, ok := data["public_ptr_domain_name"]; ok && ptr != "" { ac["setPublicPtr"] = true ac["publicPtrDomainName"] = ptr.(string) @@ -1265,7 +1272,9 @@ func expandIpv6AccessConfigs_v2(configs []interface{}) []interface{} { } if raw != nil { data := raw.(map[string]interface{}) - iac["networkTier"] = data["network_tier"].(string) + if v := data["network_tier"].(string); v != "" { + iac["networkTier"] = v + } if ptr, ok := data["public_ptr_domain_name"]; ok && ptr != "" { iac["publicPtrDomainName"] = ptr.(string) } @@ -1336,10 +1345,13 @@ func expandConfidentialInstanceConfig_v2(d tpgresource.TerraformResourceData) ma return nil } prefix := "confidential_instance_config.0" - return map[string]interface{}{ + result := map[string]interface{}{ "enableConfidentialCompute": d.Get(prefix + ".enable_confidential_compute").(bool), - "confidentialInstanceType": d.Get(prefix + ".confidential_instance_type").(string), } + if v := d.Get(prefix + ".confidential_instance_type").(string); v != "" { + result["confidentialInstanceType"] = v + } + return result } func expandAdvancedMachineFeatures_v2(d tpgresource.TerraformResourceData) map[string]interface{} { @@ -1347,14 +1359,26 @@ func expandAdvancedMachineFeatures_v2(d tpgresource.TerraformResourceData) map[s return nil } prefix := "advanced_machine_features.0" - return map[string]interface{}{ - "enableNestedVirtualization": d.Get(prefix + ".enable_nested_virtualization").(bool), - "threadsPerCore": int64(d.Get(prefix + ".threads_per_core").(int)), - "turboMode": d.Get(prefix + ".turbo_mode").(string), - "visibleCoreCount": int64(d.Get(prefix + ".visible_core_count").(int)), - "performanceMonitoringUnit": d.Get(prefix + ".performance_monitoring_unit").(string), - "enableUefiNetworking": d.Get(prefix + ".enable_uefi_networking").(bool), + result := map[string]interface{}{} + if v := d.Get(prefix + ".enable_nested_virtualization").(bool); v { + result["enableNestedVirtualization"] = v + } + if v := int64(d.Get(prefix + ".threads_per_core").(int)); v > 0 { + result["threadsPerCore"] = v } + if v := d.Get(prefix + ".turbo_mode").(string); v != "" { + result["turboMode"] = v + } + if v := int64(d.Get(prefix + ".visible_core_count").(int)); v > 0 { + result["visibleCoreCount"] = v + } + if v := d.Get(prefix + ".performance_monitoring_unit").(string); v != "" { + result["performanceMonitoringUnit"] = v + } + if v := d.Get(prefix + ".enable_uefi_networking").(bool); v { + result["enableUefiNetworking"] = v + } + return result } func expandDisplayDevice_v2(d tpgresource.TerraformResourceData) map[string]interface{} { @@ -1390,11 +1414,14 @@ func expandComputeInstanceEncryptionKey_v2(d tpgresource.TerraformResourceData) return nil } iekRes := iek.([]interface{})[0].(map[string]interface{}) - return map[string]interface{}{ - "kmsKeyName": iekRes["kms_key_self_link"].(string), - "sha256": iekRes["sha256"].(string), - "kmsKeyServiceAccount": iekRes["kms_key_service_account"].(string), + result := map[string]interface{}{} + if v := iekRes["kms_key_self_link"].(string); v != "" { + result["kmsKeyName"] = v + } + if v := iekRes["kms_key_service_account"].(string); v != "" { + result["kmsKeyServiceAccount"] = v } + return result } func expandComputeInstanceSourceEncryptionKey_v2(d tpgresource.TerraformResourceData, field string) map[string]interface{} { @@ -1403,13 +1430,20 @@ func expandComputeInstanceSourceEncryptionKey_v2(d tpgresource.TerraformResource return nil } cekRes := cek.([]interface{})[0].(map[string]interface{}) - return map[string]interface{}{ - "rsaEncryptedKey": cekRes["rsa_encrypted_key"].(string), - "rawKey": cekRes["raw_key"].(string), - "kmsKeyName": cekRes["kms_key_self_link"].(string), - "sha256": cekRes["sha256"].(string), - "kmsKeyServiceAccount": cekRes["kms_key_service_account"].(string), + result := map[string]interface{}{} + if v := cekRes["rsa_encrypted_key"].(string); v != "" { + result["rsaEncryptedKey"] = v + } + if v := cekRes["raw_key"].(string); v != "" { + result["rawKey"] = v } + if v := cekRes["kms_key_self_link"].(string); v != "" { + result["kmsKeyName"] = v + } + if v := cekRes["kms_key_service_account"].(string); v != "" { + result["kmsKeyServiceAccount"] = v + } + return result } func expandComputeInstanceGuestOsFeatures_v2(v interface{}) []interface{} { @@ -1580,7 +1614,9 @@ func expandScheduling_v2(v interface{}) (map[string]interface{}, error) { scheduling["preemptible"] = v.(bool) } if v, ok := original["on_host_maintenance"]; ok { - scheduling["onHostMaintenance"] = v.(string) + if s := v.(string); s != "" { + scheduling["onHostMaintenance"] = s + } } if v, ok := original["node_affinities"]; ok && v != nil { naSet := v.(*schema.Set).List() @@ -1599,16 +1635,24 @@ func expandScheduling_v2(v interface{}) (map[string]interface{}, error) { scheduling["nodeAffinities"] = nodeAffinities } if v, ok := original["min_node_cpus"]; ok { - scheduling["minNodeCpus"] = int64(v.(int)) + if n := int64(v.(int)); n > 0 { + scheduling["minNodeCpus"] = n + } } if v, ok := original["provisioning_model"]; ok { - scheduling["provisioningModel"] = v.(string) + if s := v.(string); s != "" { + scheduling["provisioningModel"] = s + } } if v, ok := original["instance_termination_action"]; ok { - scheduling["instanceTerminationAction"] = v.(string) + if s := v.(string); s != "" { + scheduling["instanceTerminationAction"] = s + } } if v, ok := original["availability_domain"]; ok && v != nil { - scheduling["availabilityDomain"] = int64(v.(int)) + if n := int64(v.(int)); n > 0 { + scheduling["availabilityDomain"] = n + } } if v, ok := original["max_run_duration"]; ok { transformed, err := expandComputeMaxRunDuration_v2(v) @@ -1638,7 +1682,9 @@ func expandScheduling_v2(v interface{}) (map[string]interface{}, error) { } } if v, ok := original["maintenance_interval"]; ok { - scheduling["maintenanceInterval"] = v.(string) + if s := v.(string); s != "" { + scheduling["maintenanceInterval"] = s + } } if v, ok := original["graceful_shutdown"]; ok { transformed, err := expandGracefulShutdown_v2(v) @@ -1672,7 +1718,9 @@ func expandScheduling_v2(v interface{}) (map[string]interface{}, error) { } } if v, ok := original["termination_time"]; ok { - scheduling["terminationTime"] = v.(string) + if s := v.(string); s != "" { + scheduling["terminationTime"] = s + } } return scheduling, nil } @@ -1705,20 +1753,44 @@ func expandNetworkInterfaces_v2(d tpgresource.TerraformResourceData, config *tra } iface := map[string]interface{}{ - "networkIP": data["network_ip"].(string), - "network": nf.RelativeLink(), - "networkAttachment": networkAttachment, - "vlan": int64(data["vlan"].(int)), - "subnetwork": sf.RelativeLink(), - "accessConfigs": expandAccessConfigs_v2(data["access_config"].([]interface{})), - "aliasIpRanges": expandAliasIpRanges_v2(data["alias_ip_range"].([]interface{})), - "nicType": data["nic_type"].(string), - "stackType": data["stack_type"].(string), - "queueCount": int64(data["queue_count"].(int)), - "ipv6AccessConfigs": expandIpv6AccessConfigs_v2(data["ipv6_access_config"].([]interface{})), - "ipv6Address": data["ipv6_address"].(string), - "internalIpv6PrefixLength": int64(data["internal_ipv6_prefix_length"].(int)), - "igmpQuery": data["igmp_query"].(string), + "accessConfigs": expandAccessConfigs_v2(data["access_config"].([]interface{})), + "aliasIpRanges": expandAliasIpRanges_v2(data["alias_ip_range"].([]interface{})), + "ipv6AccessConfigs": expandIpv6AccessConfigs_v2(data["ipv6_access_config"].([]interface{})), + } + // Only include optional string/numeric fields when non-zero to match omitempty + // semantics of the Apiary struct — sending empty values can cause API validation errors. + if v := nf.RelativeLink(); v != "" { + iface["network"] = v + } + if v := sf.RelativeLink(); v != "" { + iface["subnetwork"] = v + } + if v := data["network_ip"].(string); v != "" { + iface["networkIP"] = v + } + if networkAttachment != "" { + iface["networkAttachment"] = networkAttachment + } + if v := int64(data["vlan"].(int)); v != 0 { + iface["vlan"] = v + } + if v := data["nic_type"].(string); v != "" { + iface["nicType"] = v + } + if v := data["stack_type"].(string); v != "" { + iface["stackType"] = v + } + if v := int64(data["queue_count"].(int)); v != 0 { + iface["queueCount"] = v + } + if v := data["ipv6_address"].(string); v != "" { + iface["ipv6Address"] = v + } + if v := int64(data["internal_ipv6_prefix_length"].(int)); v != 0 { + iface["internalIpv6PrefixLength"] = v + } + if v := data["igmp_query"].(string); v != "" { + iface["igmpQuery"] = v } {{- if ne $.TargetVersionName "ga" }} if macAddress, ok := data["mac_address"]; ok { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index ed770dea00a7..f39d460a665a 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -8,7 +8,6 @@ import ( "fmt" "log" "net/http" - "strconv" "strings" "time" @@ -1989,19 +1988,25 @@ func expandComputeInstance_v2(project string, d *schema.ResourceData, config *tr "labels": tpgresource.ExpandEffectiveLabels(d), "serviceAccounts": expandServiceAccounts_v2(d.Get("service_account").([]interface{})), "guestAccelerators": accels, - "minCpuPlatform": d.Get("min_cpu_platform").(string), "scheduling": scheduling, "deletionProtection": d.Get("deletion_protection").(bool), - "hostname": d.Get("hostname").(string), "confidentialInstanceConfig": expandConfidentialInstanceConfig_v2(d), "advancedMachineFeatures": expandAdvancedMachineFeatures_v2(d), "shieldedInstanceConfig": expandShieldedVmConfigs_v2(d), "displayDevice": expandDisplayDevice_v2(d), "resourcePolicies": tpgresource.ConvertStringArr(d.Get("resource_policies").([]interface{})), "reservationAffinity": reservationAffinity, - "keyRevocationActionType": d.Get("key_revocation_action_type").(string), "instanceEncryptionKey": expandComputeInstanceEncryptionKey_v2(d), } + if v := d.Get("min_cpu_platform").(string); v != "" { + instance["minCpuPlatform"] = v + } + if v := d.Get("hostname").(string); v != "" { + instance["hostname"] = v + } + if v := d.Get("key_revocation_action_type").(string); v != "" { + instance["keyRevocationActionType"] = v + } {{- if ne $.TargetVersionName `ga` }} instance["eraseWindowsVssSignature"] = d.Get("erase_windows_vss_signature").(bool) instance["partnerMetadata"] = partnerMetadataMap @@ -3943,12 +3948,16 @@ func startInstanceOperation(d *schema.ResourceData, config *transport_tpg.Config var encryptedDisks []interface{} for _, disk := range instanceFromConfig.Disks { if disk.DiskEncryptionKey != nil { + keyMap := map[string]interface{}{} + if v := disk.DiskEncryptionKey.RawKey; v != "" { + keyMap["rawKey"] = v + } + if v := disk.DiskEncryptionKey.KmsKeyName; v != "" { + keyMap["kmsKeyName"] = v + } encryptedDisks = append(encryptedDisks, map[string]interface{}{ - "source": disk.Source, - "diskEncryptionKey": map[string]interface{}{ - "rawKey": disk.DiskEncryptionKey.RawKey, - "kmsKeyName": disk.DiskEncryptionKey.KmsKeyName, - }, + "source": disk.Source, + "diskEncryptionKey": keyMap, }) } } @@ -4201,7 +4210,13 @@ func resourceComputeInstanceDelete(d *schema.ResourceData, meta interface{}) err if d.Get("deletion_protection").(bool) { return fmt.Errorf("Cannot delete instance %s: instance Deletion Protection is enabled. Set deletion_protection to false for this resource and run \"terraform apply\" before attempting to delete it.", d.Get("name").(string)) } else { - op, err := NewClient(config, userAgent).Instances.Delete(project, zone, d.Get("name").(string)).Do() + op, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, d.Get("name").(string)), + UserAgent: userAgent, + }) if err != nil { return fmt.Errorf("Error deleting instance: %s", err) } @@ -4210,9 +4225,16 @@ func resourceComputeInstanceDelete(d *schema.ResourceData, meta interface{}) err opErr := ComputeOperationWaitTime(config, op, project, "instance to delete", userAgent, d.Timeout(schema.TimeoutDelete)) if opErr != nil { // Refresh operation to check status - op, _ = NewClient(config, userAgent).ZoneOperations.Get(project, zone, strconv.FormatUint(op.Id, 10)).Do() + opName, _ := op["name"].(string) + refreshedOp, _ := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: project, + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/operations/%s", config.ComputeBasePath, project, zone, opName), + UserAgent: userAgent, + }) // Do not return an error if the operation actually completed - if op == nil || op.Status != "DONE" { + if status, ok := refreshedOp["status"].(string); !ok || status != "DONE" { return opErr } } @@ -4669,7 +4691,11 @@ func CheckForCommonAliasIp_v2(old *compute.NetworkInterface, newAliasIpRanges [] result := make([]interface{}, 0) for _, val := range old.AliasIpRanges { if newAliasIpMap[val.IpCidrRange] { - result = append(result, map[string]interface{}{"ipCidrRange": val.IpCidrRange}) + entry := map[string]interface{}{"ipCidrRange": val.IpCidrRange} + if val.SubnetworkRangeName != "" { + entry["subnetworkRangeName"] = val.SubnetworkRangeName + } + result = append(result, entry) } } return result diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_test.go.tmpl index f9882090001f..cfefc6095fbd 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_test.go.tmpl @@ -1246,6 +1246,14 @@ resource "google_project_service" "monitoring" { depends_on = [google_project_service.service] } +resource "google_compute_network" "vpc" { + provider = google-beta + project = google_project.project.project_id + name = "tf-test-vpc" + auto_create_subnetworks = true + depends_on = [google_project_service.service] +} + resource "google_compute_instance" "vm" { provider = google-beta project = google_project.project.project_id @@ -1259,7 +1267,7 @@ resource "google_compute_instance" "vm" { machine_type = "n1-standard-1" network_interface { - network = "default" + network = google_compute_network.vpc.name } metadata = { From 5d48b350ad57927d4468c20e94d3f3cba0d0fcba Mon Sep 17 00:00:00 2001 From: nsamartsev Date: Thu, 14 May 2026 13:51:11 +0200 Subject: [PATCH 6/9] Fix --- .../compute/compute_instance_helpers.go.tmpl | 2 +- .../compute/resource_compute_instance.go.tmpl | 172 +++--------------- 2 files changed, 22 insertions(+), 152 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl index 2a068b8eb37c..5814d7425e86 100644 --- a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl @@ -1793,7 +1793,7 @@ func expandNetworkInterfaces_v2(d tpgresource.TerraformResourceData, config *tra iface["igmpQuery"] = v } {{- if ne $.TargetVersionName "ga" }} - if macAddress, ok := data["mac_address"]; ok { + if macAddress, ok := data["mac_address"]; ok && macAddress.(string) != "" { iface["macAddress"] = macAddress.(string) } {{- end }} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index f39d460a665a..7b5a1b512d6b 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -8,6 +8,7 @@ import ( "fmt" "log" "net/http" + "strconv" "strings" "time" @@ -1774,131 +1775,6 @@ func getDisk(diskUri string, d *schema.ResourceData, config *transport_tpg.Confi return disk, err } -func expandComputeInstance(project string, d *schema.ResourceData, config *transport_tpg.Config) (*compute.Instance, error) { - // Get the machine type - var machineTypeUrl string - if mt, ok := d.GetOk("machine_type"); ok { - machineType, err := tpgresource.ParseMachineTypesFieldValue(mt.(string), d, config) - if err != nil { - return nil, fmt.Errorf( - "Error loading machine type: %s", - err) - } - machineTypeUrl = machineType.RelativeLink() - } - - // Build up the list of disks - - disks := []*compute.AttachedDisk{} - if _, hasBootDisk := d.GetOk("boot_disk"); hasBootDisk { - bootDisk, err := expandBootDisk(d, config, project) - if err != nil { - return nil, err - } - disks = append(disks, bootDisk) - } - - if _, hasScratchDisk := d.GetOk("scratch_disk"); hasScratchDisk { - scratchDisks, err := expandScratchDisks(d, config, project) - if err != nil { - return nil, err - } - disks = append(disks, scratchDisks...) - } - - attachedDisksCount := d.Get("attached_disk.#").(int) - - for i := 0; i < attachedDisksCount; i++ { - diskConfig := d.Get(fmt.Sprintf("attached_disk.%d", i)).(map[string]interface{}) - disk, err := expandAttachedDisk(diskConfig, d, config) - if err != nil { - return nil, err - } - - disks = append(disks, disk) - } - - scheduling, err := expandScheduling(d.Get("scheduling")) - if err != nil { - return nil, fmt.Errorf("Error creating scheduling: %s", err) - } - - params, err := expandParams(d) - if err != nil { - return nil, fmt.Errorf("Error creating params: %s", err) - } - - metadata, err := resourceInstanceMetadata(d) - if err != nil { - return nil, fmt.Errorf("Error creating metadata: %s", err) - } - - {{ if ne $.TargetVersionName `ga` -}} - partnerMetadataMap, err := resourceInstancePartnerMetadata(d) - if err != nil { - return nil, fmt.Errorf("Error creating partner metadata: %s", err) - } - PartnerMetadata, err := convertPartnerMetadataToCompute(partnerMetadataMap) - if err != nil { - return nil, fmt.Errorf("Error converting partner metadata: %s", err) - } - {{- end }} - - networkInterfaces, err := expandNetworkInterfaces(d, config) - if err != nil { - return nil, fmt.Errorf("Error creating network interfaces: %s", err) - } - networkPerformanceConfig, err := expandNetworkPerformanceConfig(d, config) - if err != nil { - return nil, fmt.Errorf("Error creating network performance config: %s", err) - } - accels, err := expandInstanceGuestAccelerators(d, config) - if err != nil { - return nil, fmt.Errorf("Error creating guest accelerators: %s", err) - } - - reservationAffinity, err := expandReservationAffinity(d) - if err != nil { - return nil, fmt.Errorf("Error creating reservation affinity: %s", err) - } - - // Create the instance information - return &compute.Instance{ - CanIpForward: d.Get("can_ip_forward").(bool), - Description: d.Get("description").(string), - Disks: disks, - MachineType: machineTypeUrl, - Metadata: metadata, - {{- if ne $.TargetVersionName "ga" }} - PartnerMetadata: PartnerMetadata, - {{- end }} - Name: d.Get("name").(string), - NetworkInterfaces: networkInterfaces, - NetworkPerformanceConfig: networkPerformanceConfig, - Tags: resourceInstanceTags(d), - Params: params, - Labels: tpgresource.ExpandEffectiveLabels(d), - ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})), - GuestAccelerators: accels, - MinCpuPlatform: d.Get("min_cpu_platform").(string), - Scheduling: scheduling, - DeletionProtection: d.Get("deletion_protection").(bool), - Hostname: d.Get("hostname").(string), - ForceSendFields: []string{"CanIpForward", "DeletionProtection"}, - ConfidentialInstanceConfig: expandConfidentialInstanceConfig(d), - AdvancedMachineFeatures: expandAdvancedMachineFeatures(d), - ShieldedInstanceConfig: expandShieldedVmConfigs(d), - DisplayDevice: expandDisplayDevice(d), - ResourcePolicies: tpgresource.ConvertStringArr(d.Get("resource_policies").([]interface{})), - ReservationAffinity: reservationAffinity, - KeyRevocationActionType: d.Get("key_revocation_action_type").(string), - InstanceEncryptionKey: expandComputeInstanceEncryptionKey(d), - {{- if ne $.TargetVersionName `ga` }} - EraseWindowsVssSignature: d.Get("erase_windows_vss_signature").(bool), - {{- end }} - }, nil -} - // expandComputeInstance_v2 builds the instance request body as map[string]interface{} // for direct serialization via transport_tpg.SendRequest. // Disk-related fields (expandBootDisk, expandScratchDisks, expandAttachedDisk) are not yet @@ -2039,7 +1915,6 @@ func getAllStatusBut(status string) []string { func changeInstanceStatusOnCreation(config *transport_tpg.Config, d *schema.ResourceData, project, zone, status, userAgent string) error { var res map[string]interface{} var err error - name := d.Get("name").(string) if status == "TERMINATED" { var url string url, err = tpgresource.ReplaceVars(d, config, "{{"{{"}}ComputeBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/zones/{{"{{"}}zone{{"}}"}}/instances/{{"{{"}}name{{"}}"}}/stop") @@ -2151,10 +2026,6 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err {{- end }} log.Printf("[INFO] Requesting instance creation") - instanceBody, err := tpgresource.ConvertToMap(instance) - if err != nil { - return fmt.Errorf("Error converting instance: %s", err) - } insertUrl, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}ComputeBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/zones/{{"{{"}}zone{{"}}"}}/instances") if err != nil { return fmt.Errorf("Error generating URL: %s", err) @@ -2955,7 +2826,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err instNetworkInterface := instance.NetworkInterfaces[i] networkName := d.Get(prefix + ".name").(string) - subnetwork := networkInterface["subnetwork"].(string) + subnetwork, _ := networkInterface["subnetwork"].(string) updateDuringStop := d.HasChange(prefix+".subnetwork") || d.HasChange(prefix+".network") || d.HasChange(prefix+".subnetwork_project") // Sanity check @@ -3025,16 +2896,14 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err // Alias IP ranges cannot be updated; they must be removed and then added // unless you are changing subnetwork/network if len(instNetworkInterface.AliasIpRanges) > 0 { - ni := &compute.NetworkInterface{ - Fingerprint: instNetworkInterface.Fingerprint, - ForceSendFields: []string{"AliasIpRanges"}, - } - if commonAliasIpRanges := CheckForCommonAliasIp(instNetworkInterface, networkInterface); len(commonAliasIpRanges) > 0 { - ni.AliasIpRanges = commonAliasIpRanges - } - niBody, err := tpgresource.ConvertToMap(ni) - if err != nil { - return errwrap.Wrapf("Error converting network interface: {{"{{"}}err{{"}}"}}", err) + newAliasIps := networkInterface["aliasIpRanges"].([]interface{}) + // During the clear phase keep only ranges already on the instance (intersection). + // Always send aliasIpRanges in the body (even when empty) to clear the field — + // this mirrors ForceSendFields["AliasIpRanges"] from the prior Apiary approach. + clearAliasIps := CheckForCommonAliasIp_v2(instNetworkInterface, newAliasIps) + niBody := map[string]interface{}{ + "aliasIpRanges": clearAliasIps, + "fingerprint": instNetworkInterface.Fingerprint, } url, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}ComputeBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/zones/{{"{{"}}zone{{"}}"}}/instances/{{"{{"}}name{{"}}"}}/updateNetworkInterface") if err != nil { @@ -3238,9 +3107,11 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err if updateDuringStop { // Lets be explicit about what we are changing in the patch call + network, _ := networkInterface["network"].(string) + subnetwork, _ := networkInterface["subnetwork"].(string) networkInterfacePatchObj := map[string]interface{}{ - "network": networkInterface["network"].(string), - "subnetwork": networkInterface["subnetwork"].(string), + "network": network, + "subnetwork": subnetwork, } if aliasIps, ok := networkInterface["aliasIpRanges"].([]interface{}); ok && len(aliasIps) > 0 { networkInterfacePatchObj["aliasIpRanges"] = aliasIps @@ -3249,15 +3120,18 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err // network_ip can be inferred if not declared. Let's only patch if it's being changed by user // otherwise this could fail if the network ip is not compatible with the new Subnetwork/Network. if d.HasChange(prefix + ".network_ip") { - networkInterfacePatchObj["networkIP"] = networkInterface["networkIP"].(string) + networkIP, _ := networkInterface["networkIP"].(string) + networkInterfacePatchObj["networkIP"] = networkIP } if d.HasChange(prefix+".internal_ipv6_prefix_length") { - networkInterfacePatchObj["ipv6Address"] = networkInterface["ipv6Address"].(string) + ipv6Address, _ := networkInterface["ipv6Address"].(string) + networkInterfacePatchObj["ipv6Address"] = ipv6Address } if d.HasChange(prefix+".ipv6_address") { - networkInterfacePatchObj["ipv6Address"] = networkInterface["ipv6Address"].(string) + ipv6Address, _ := networkInterface["ipv6Address"].(string) + networkInterfacePatchObj["ipv6Address"] = ipv6Address } // Access config can run into some issues since we can't tell the difference between @@ -3709,10 +3583,6 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err saBody["email"] = saMap["email"].(string) saBody["scopes"] = tpgresource.CanonicalizeServiceScopes(tpgresource.ConvertStringSet(saMap["scopes"].(*schema.Set))) } - body, err := tpgresource.ConvertToMap(req) - if err != nil { - return fmt.Errorf("Error converting service account request: %s", err) - } url, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}ComputeBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/zones/{{"{{"}}zone{{"}}"}}/instances/{{"{{"}}name{{"}}"}}/setServiceAccount") if err != nil { return fmt.Errorf("Error generating URL: %s", err) @@ -3723,7 +3593,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Project: project, RawURL: url, UserAgent: userAgent, - Body: body, + Body: saBody, }) if err != nil { return err From 6fa1cb1f2b0d882787e49da83ad48a08fdaffb47 Mon Sep 17 00:00:00 2001 From: nsamartsev Date: Thu, 14 May 2026 14:05:48 +0200 Subject: [PATCH 7/9] Fix --- .../compute/resource_compute_instance.go.tmpl | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index 7b5a1b512d6b..4375b4a5b87d 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -2459,7 +2459,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Config: config, Method: "PUT", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, Body: instanceMap, }) @@ -2507,7 +2507,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Config: config, Method: "POST", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/setMetadata", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/setMetadata", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, Body: metadataMap, }) @@ -2557,7 +2557,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Config: config, Method: "PUT", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, Body: instanceMap, }) @@ -2666,7 +2666,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Config: config, Method: "PUT", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, Body: instanceMap, }) @@ -3397,7 +3397,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Config: config, Method: "PUT", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, Body: instanceMap, }) @@ -3434,7 +3434,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Config: config, Method: "POST", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/resume", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/resume", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, }) if err != nil { @@ -3451,7 +3451,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Config: config, Method: "POST", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/stop", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/stop", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, }) if err != nil { @@ -3462,7 +3462,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Config: config, Method: "POST", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/suspend", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/suspend", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, }) if err != nil { @@ -3716,7 +3716,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Config: config, Method: "PUT", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, Body: instanceMap, }) @@ -3809,14 +3809,17 @@ func startInstanceOperation(d *schema.ResourceData, config *transport_tpg.Config return nil, transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Instance %s", instance.Name)) } - // Retrieve instance from config to pull encryption keys if necessary - instanceFromConfig, err := expandComputeInstance(project, d, config) + // Retrieve instance from config to pull encryption keys if necessary. + // expandComputeInstance_v2 stores *compute.AttachedDisk values in the disks + // slice, so we can type-assert them back to read DiskEncryptionKey. + instanceBody, err := expandComputeInstance_v2(project, d, config) if err != nil { return nil, err } var encryptedDisks []interface{} - for _, disk := range instanceFromConfig.Disks { + for _, diskRaw := range instanceBody["disks"].([]interface{}) { + disk := diskRaw.(*compute.AttachedDisk) if disk.DiskEncryptionKey != nil { keyMap := map[string]interface{}{} if v := disk.DiskEncryptionKey.RawKey; v != "" { @@ -3837,7 +3840,7 @@ func startInstanceOperation(d *schema.ResourceData, config *transport_tpg.Config Config: config, Method: "POST", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/startWithEncryptionKey", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/startWithEncryptionKey", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, Body: map[string]interface{}{"disks": encryptedDisks}, }) @@ -3846,7 +3849,7 @@ func startInstanceOperation(d *schema.ResourceData, config *transport_tpg.Config Config: config, Method: "POST", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/start", config.ComputeBasePath, project, zone, instance.Name), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s/start", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, instance.Name), UserAgent: userAgent, }) } @@ -4084,7 +4087,7 @@ func resourceComputeInstanceDelete(d *schema.ResourceData, meta interface{}) err Config: config, Method: "DELETE", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", config.ComputeBasePath, project, zone, d.Get("name").(string)), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/instances/%s", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, d.Get("name").(string)), UserAgent: userAgent, }) if err != nil { @@ -4100,7 +4103,7 @@ func resourceComputeInstanceDelete(d *schema.ResourceData, meta interface{}) err Config: config, Method: "GET", Project: project, - RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/operations/%s", config.ComputeBasePath, project, zone, opName), + RawURL: fmt.Sprintf("%sprojects/%s/zones/%s/operations/%s", transport_tpg.BaseUrl(registry.GetProduct("compute"), config), project, zone, opName), UserAgent: userAgent, }) // Do not return an error if the operation actually completed From 648c4e7a9b71bf1405a75c6a789194cfeadedbd2 Mon Sep 17 00:00:00 2001 From: nsamartsev Date: Thu, 14 May 2026 14:20:34 +0200 Subject: [PATCH 8/9] Fix --- .../compute/resource_compute_instance.go.tmpl | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index 4375b4a5b87d..e7e28fa0acf3 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -1775,6 +1775,127 @@ func getDisk(diskUri string, d *schema.ResourceData, config *transport_tpg.Confi return disk, err } +func expandComputeInstance(project string, d *schema.ResourceData, config *transport_tpg.Config) (*compute.Instance, error) { + var machineTypeUrl string + if mt, ok := d.GetOk("machine_type"); ok { + machineType, err := tpgresource.ParseMachineTypesFieldValue(mt.(string), d, config) + if err != nil { + return nil, fmt.Errorf( + "Error loading machine type: %s", + err) + } + machineTypeUrl = machineType.RelativeLink() + } + + disks := []*compute.AttachedDisk{} + if _, hasBootDisk := d.GetOk("boot_disk"); hasBootDisk { + bootDisk, err := expandBootDisk(d, config, project) + if err != nil { + return nil, err + } + disks = append(disks, bootDisk) + } + + if _, hasScratchDisk := d.GetOk("scratch_disk"); hasScratchDisk { + scratchDisks, err := expandScratchDisks(d, config, project) + if err != nil { + return nil, err + } + disks = append(disks, scratchDisks...) + } + + attachedDisksCount := d.Get("attached_disk.#").(int) + + for i := 0; i < attachedDisksCount; i++ { + diskConfig := d.Get(fmt.Sprintf("attached_disk.%d", i)).(map[string]interface{}) + disk, err := expandAttachedDisk(diskConfig, d, config) + if err != nil { + return nil, err + } + + disks = append(disks, disk) + } + + scheduling, err := expandScheduling(d.Get("scheduling")) + if err != nil { + return nil, fmt.Errorf("Error creating scheduling: %s", err) + } + + params, err := expandParams(d) + if err != nil { + return nil, fmt.Errorf("Error creating params: %s", err) + } + + metadata, err := resourceInstanceMetadata(d) + if err != nil { + return nil, fmt.Errorf("Error creating metadata: %s", err) + } + + {{ if ne $.TargetVersionName `ga` -}} + partnerMetadataMap, err := resourceInstancePartnerMetadata(d) + if err != nil { + return nil, fmt.Errorf("Error creating partner metadata: %s", err) + } + PartnerMetadata, err := convertPartnerMetadataToCompute(partnerMetadataMap) + if err != nil { + return nil, fmt.Errorf("Error converting partner metadata: %s", err) + } + {{- end }} + + networkInterfaces, err := expandNetworkInterfaces(d, config) + if err != nil { + return nil, fmt.Errorf("Error creating network interfaces: %s", err) + } + networkPerformanceConfig, err := expandNetworkPerformanceConfig(d, config) + if err != nil { + return nil, fmt.Errorf("Error creating network performance config: %s", err) + } + accels, err := expandInstanceGuestAccelerators(d, config) + if err != nil { + return nil, fmt.Errorf("Error creating guest accelerators: %s", err) + } + + reservationAffinity, err := expandReservationAffinity(d) + if err != nil { + return nil, fmt.Errorf("Error creating reservation affinity: %s", err) + } + + return &compute.Instance{ + CanIpForward: d.Get("can_ip_forward").(bool), + Description: d.Get("description").(string), + Disks: disks, + MachineType: machineTypeUrl, + Metadata: metadata, + {{- if ne $.TargetVersionName "ga" }} + PartnerMetadata: PartnerMetadata, + {{- end }} + Name: d.Get("name").(string), + NetworkInterfaces: networkInterfaces, + NetworkPerformanceConfig: networkPerformanceConfig, + Tags: resourceInstanceTags(d), + Params: params, + Labels: tpgresource.ExpandEffectiveLabels(d), + ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})), + GuestAccelerators: accels, + MinCpuPlatform: d.Get("min_cpu_platform").(string), + Scheduling: scheduling, + DeletionProtection: d.Get("deletion_protection").(bool), + Hostname: d.Get("hostname").(string), + ForceSendFields: []string{"CanIpForward", "DeletionProtection"}, + ConfidentialInstanceConfig: expandConfidentialInstanceConfig(d), + AdvancedMachineFeatures: expandAdvancedMachineFeatures(d), + ShieldedInstanceConfig: expandShieldedVmConfigs(d), + DisplayDevice: expandDisplayDevice(d), + ResourcePolicies: tpgresource.ConvertStringArr(d.Get("resource_policies").([]interface{})), + ReservationAffinity: reservationAffinity, + KeyRevocationActionType: d.Get("key_revocation_action_type").(string), + InstanceEncryptionKey: expandComputeInstanceEncryptionKey(d), + {{- if ne $.TargetVersionName `ga` }} + EraseWindowsVssSignature: d.Get("erase_windows_vss_signature").(bool), + {{- end }} + }, nil +} + // expandComputeInstance_v2 builds the instance request body as map[string]interface{} // for direct serialization via transport_tpg.SendRequest. // Disk-related fields (expandBootDisk, expandScratchDisks, expandAttachedDisk) are not yet From f9b0a1ea68d4bcec4bf5f214d4cdb7388efcea42 Mon Sep 17 00:00:00 2001 From: nsamartsev Date: Thu, 14 May 2026 14:36:27 +0200 Subject: [PATCH 9/9] Fix --- ...ce_compute_instance_from_machine_image_test.go.tmpl | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_test.go.tmpl index cfefc6095fbd..f9882090001f 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_test.go.tmpl @@ -1246,14 +1246,6 @@ resource "google_project_service" "monitoring" { depends_on = [google_project_service.service] } -resource "google_compute_network" "vpc" { - provider = google-beta - project = google_project.project.project_id - name = "tf-test-vpc" - auto_create_subnetworks = true - depends_on = [google_project_service.service] -} - resource "google_compute_instance" "vm" { provider = google-beta project = google_project.project.project_id @@ -1267,7 +1259,7 @@ resource "google_compute_instance" "vm" { machine_type = "n1-standard-1" network_interface { - network = google_compute_network.vpc.name + network = "default" } metadata = {