From 33a8d9120686f9d13e40e7f39d68d9f5c188ded4 Mon Sep 17 00:00:00 2001 From: The Magician Date: Mon, 15 Jul 2024 12:40:11 -0700 Subject: [PATCH] workbench instances support for static external IP (#10934) (#18737) [upstream:ef027b1a25205b7b981c568dd0c489838dc53b75] Signed-off-by: Modular Magician --- .changelog/10934.txt | 3 + .../workbench/resource_workbench_instance.go | 86 ++++++++++++++++++- ...ource_workbench_instance_generated_test.go | 7 ++ .../docs/r/workbench_instance.html.markdown | 26 ++++++ 4 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 .changelog/10934.txt diff --git a/.changelog/10934.txt b/.changelog/10934.txt new file mode 100644 index 00000000000..4eccd5c5c8b --- /dev/null +++ b/.changelog/10934.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +workbench: added `access_configs` to `google_workbench_instance` resource +``` \ No newline at end of file diff --git a/google/services/workbench/resource_workbench_instance.go b/google/services/workbench/resource_workbench_instance.go index 67dd0156921..c65946389c3 100644 --- a/google/services/workbench/resource_workbench_instance.go +++ b/google/services/workbench/resource_workbench_instance.go @@ -491,6 +491,30 @@ https://cloud.google.com/vpc/docs/using-routes#canipforward`, Description: `The network interfaces for the VM. Supports only one interface.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "access_configs": { + Type: schema.TypeList, + Computed: true, + Optional: true, + ForceNew: true, + Description: `Optional. An array of configurations for this interface. Currently, only one access +config, ONE_TO_ONE_NAT, is supported. If no accessConfigs specified, the +instance will have an external internet access through an ephemeral +external IP address.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "external_ip": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `An external IP address associated with this instance. Specify an unused +static external IP address available to the project or leave this field +undefined to use an IP from a shared ephemeral IP address pool. If you +specify a static external IP address, it must live in the same region as +the zone of the instance.`, + }, + }, + }, + }, "network": { Type: schema.TypeString, Computed: true, @@ -1488,9 +1512,10 @@ func flattenWorkbenchInstanceGceSetupNetworkInterfaces(v interface{}, d *schema. continue } transformed = append(transformed, map[string]interface{}{ - "network": flattenWorkbenchInstanceGceSetupNetworkInterfacesNetwork(original["network"], d, config), - "subnet": flattenWorkbenchInstanceGceSetupNetworkInterfacesSubnet(original["subnet"], d, config), - "nic_type": flattenWorkbenchInstanceGceSetupNetworkInterfacesNicType(original["nicType"], d, config), + "network": flattenWorkbenchInstanceGceSetupNetworkInterfacesNetwork(original["network"], d, config), + "subnet": flattenWorkbenchInstanceGceSetupNetworkInterfacesSubnet(original["subnet"], d, config), + "nic_type": flattenWorkbenchInstanceGceSetupNetworkInterfacesNicType(original["nicType"], d, config), + "access_configs": flattenWorkbenchInstanceGceSetupNetworkInterfacesAccessConfigs(original["accessConfigs"], d, config), }) } return transformed @@ -1507,6 +1532,28 @@ func flattenWorkbenchInstanceGceSetupNetworkInterfacesNicType(v interface{}, d * return v } +func flattenWorkbenchInstanceGceSetupNetworkInterfacesAccessConfigs(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "external_ip": flattenWorkbenchInstanceGceSetupNetworkInterfacesAccessConfigsExternalIp(original["externalIp"], d, config), + }) + } + return transformed +} +func flattenWorkbenchInstanceGceSetupNetworkInterfacesAccessConfigsExternalIp(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenWorkbenchInstanceGceSetupDisablePublicIp(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { return v } @@ -2115,6 +2162,13 @@ func expandWorkbenchInstanceGceSetupNetworkInterfaces(v interface{}, d tpgresour transformed["nicType"] = transformedNicType } + transformedAccessConfigs, err := expandWorkbenchInstanceGceSetupNetworkInterfacesAccessConfigs(original["access_configs"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAccessConfigs); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["accessConfigs"] = transformedAccessConfigs + } + req = append(req, transformed) } return req, nil @@ -2132,6 +2186,32 @@ func expandWorkbenchInstanceGceSetupNetworkInterfacesNicType(v interface{}, d tp return v, nil } +func expandWorkbenchInstanceGceSetupNetworkInterfacesAccessConfigs(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedExternalIp, err := expandWorkbenchInstanceGceSetupNetworkInterfacesAccessConfigsExternalIp(original["external_ip"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedExternalIp); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["externalIp"] = transformedExternalIp + } + + req = append(req, transformed) + } + return req, nil +} + +func expandWorkbenchInstanceGceSetupNetworkInterfacesAccessConfigsExternalIp(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandWorkbenchInstanceGceSetupDisablePublicIp(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/google/services/workbench/resource_workbench_instance_generated_test.go b/google/services/workbench/resource_workbench_instance_generated_test.go index 8ecb2dc647d..878e02f153e 100644 --- a/google/services/workbench/resource_workbench_instance_generated_test.go +++ b/google/services/workbench/resource_workbench_instance_generated_test.go @@ -255,6 +255,10 @@ resource "google_compute_subnetwork" "my_subnetwork" { ip_cidr_range = "10.0.1.0/24" } +resource "google_compute_address" "static" { + name = "tf-test-wbi-test-default%{random_suffix}" +} + resource "google_workbench_instance" "instance" { name = "tf-test-workbench-instance%{random_suffix}" location = "us-central1-a" @@ -296,6 +300,9 @@ resource "google_workbench_instance" "instance" { network = google_compute_network.my_network.id subnet = google_compute_subnetwork.my_subnetwork.id nic_type = "GVNIC" + access_configs { + external_ip = google_compute_address.static.address + } } metadata = { diff --git a/website/docs/r/workbench_instance.html.markdown b/website/docs/r/workbench_instance.html.markdown index 60cc1052f83..d886562a084 100644 --- a/website/docs/r/workbench_instance.html.markdown +++ b/website/docs/r/workbench_instance.html.markdown @@ -136,6 +136,10 @@ resource "google_compute_subnetwork" "my_subnetwork" { ip_cidr_range = "10.0.1.0/24" } +resource "google_compute_address" "static" { + name = "wbi-test-default" +} + resource "google_workbench_instance" "instance" { name = "workbench-instance" location = "us-central1-a" @@ -177,6 +181,9 @@ resource "google_workbench_instance" "instance" { network = google_compute_network.my_network.id subnet = google_compute_subnetwork.my_subnetwork.id nic_type = "GVNIC" + access_configs { + external_ip = google_compute_address.static.address + } } metadata = { @@ -459,6 +466,25 @@ The following arguments are supported: may be gVNIC or VirtioNet. Possible values are: `VIRTIO_NET`, `GVNIC`. +* `access_configs` - + (Optional) + Optional. An array of configurations for this interface. Currently, only one access + config, ONE_TO_ONE_NAT, is supported. If no accessConfigs specified, the + instance will have an external internet access through an ephemeral + external IP address. + Structure is [documented below](#nested_access_configs). + + +The `access_configs` block supports: + +* `external_ip` - + (Required) + An external IP address associated with this instance. Specify an unused + static external IP address available to the project or leave this field + undefined to use an IP from a shared ephemeral IP address pool. If you + specify a static external IP address, it must live in the same region as + the zone of the instance. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: