diff --git a/.changelog/3289.txt b/.changelog/3289.txt new file mode 100644 index 00000000000..42e1a26196a --- /dev/null +++ b/.changelog/3289.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +compute: added field `network` to `google_compute_region_backend_service`, which allows internal load balancers to target the non-primary interface of an instance. (GA only) +``` diff --git a/google/resource_compute_region_backend_service.go b/google/resource_compute_region_backend_service.go index 10316c2000d..e4e9a55c092 100644 --- a/google/resource_compute_region_backend_service.go +++ b/google/resource_compute_region_backend_service.go @@ -190,6 +190,13 @@ balancing cannot be used with the other(s). Must be 'INTERNAL' or 'INTERNAL_MANAGED'. Defaults to 'INTERNAL'.`, Default: "INTERNAL", }, + "network": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `The URL of the network to which this backend service belongs. +This field can only be specified when the load balancing scheme is set to INTERNAL.`, + }, "protocol": { Type: schema.TypeString, Computed: true, @@ -442,6 +449,12 @@ func resourceComputeRegionBackendServiceCreate(d *schema.ResourceData, meta inte } else if v, ok := d.GetOkExists("timeout_sec"); !isEmptyValue(reflect.ValueOf(timeoutSecProp)) && (ok || !reflect.DeepEqual(v, timeoutSecProp)) { obj["timeoutSec"] = timeoutSecProp } + networkProp, err := expandComputeRegionBackendServiceNetwork(d.Get("network"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("network"); !isEmptyValue(reflect.ValueOf(networkProp)) && (ok || !reflect.DeepEqual(v, networkProp)) { + obj["network"] = networkProp + } regionProp, err := expandComputeRegionBackendServiceRegion(d.Get("region"), d, config) if err != nil { return err @@ -552,6 +565,9 @@ func resourceComputeRegionBackendServiceRead(d *schema.ResourceData, meta interf if err := d.Set("timeout_sec", flattenComputeRegionBackendServiceTimeoutSec(res["timeoutSec"], d, config)); err != nil { return fmt.Errorf("Error reading RegionBackendService: %s", err) } + if err := d.Set("network", flattenComputeRegionBackendServiceNetwork(res["network"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionBackendService: %s", err) + } if err := d.Set("region", flattenComputeRegionBackendServiceRegion(res["region"], d, config)); err != nil { return fmt.Errorf("Error reading RegionBackendService: %s", err) } @@ -631,6 +647,12 @@ func resourceComputeRegionBackendServiceUpdate(d *schema.ResourceData, meta inte } else if v, ok := d.GetOkExists("timeout_sec"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, timeoutSecProp)) { obj["timeoutSec"] = timeoutSecProp } + networkProp, err := expandComputeRegionBackendServiceNetwork(d.Get("network"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("network"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, networkProp)) { + obj["network"] = networkProp + } regionProp, err := expandComputeRegionBackendServiceRegion(d.Get("region"), d, config) if err != nil { return err @@ -929,6 +951,13 @@ func flattenComputeRegionBackendServiceTimeoutSec(v interface{}, d *schema.Resou return v // let terraform core handle it otherwise } +func flattenComputeRegionBackendServiceNetwork(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + func flattenComputeRegionBackendServiceRegion(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return v @@ -1122,6 +1151,14 @@ func expandComputeRegionBackendServiceTimeoutSec(v interface{}, d TerraformResou return v, nil } +func expandComputeRegionBackendServiceNetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + f, err := parseGlobalFieldValue("networks", v.(string), "project", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for network: %s", err) + } + return f.RelativeLink(), nil +} + func expandComputeRegionBackendServiceRegion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true) if err != nil { diff --git a/google/resource_compute_region_backend_service_test.go b/google/resource_compute_region_backend_service_test.go index 06d9a76bf39..6ab3bb5a873 100644 --- a/google/resource_compute_region_backend_service_test.go +++ b/google/resource_compute_region_backend_service_test.go @@ -112,6 +112,33 @@ func TestAccComputeRegionBackendService_withBackendInternalManaged(t *testing.T) }) } +func TestAccComputeRegionBackendService_withBackendMultiNic(t *testing.T) { + t.Parallel() + + serviceName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + net1Name := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + net2Name := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + igName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + itName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + checkName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeRegionBackendServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionBackendService_withBackendMultiNic( + serviceName, net1Name, net2Name, igName, itName, checkName, 10), + }, + { + ResourceName: "google_compute_region_backend_service.lipsum", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccComputeRegionBackendService_withConnectionDrainingAndUpdate(t *testing.T) { t.Parallel() @@ -253,6 +280,98 @@ resource "google_compute_health_check" "default" { `, serviceName, timeout, igName, itName, checkName) } +func testAccComputeRegionBackendService_withBackendMultiNic( + serviceName, net1Name, net2Name, igName, itName, checkName string, timeout int64) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-9" + project = "debian-cloud" +} + +resource "google_compute_region_backend_service" "lipsum" { + name = "%s" + description = "Hello World 1234" + protocol = "TCP" + region = "us-central1" + timeout_sec = %v + + backend { + group = google_compute_instance_group_manager.foobar.instance_group + } + + network = google_compute_network.network2.self_link + + health_checks = [google_compute_health_check.default.self_link] +} + +resource "google_compute_network" "network1" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "subnet1" { + name = "%s" + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + private_ip_google_access = true + network = google_compute_network.network1.self_link +} + +resource "google_compute_network" "network2" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "subnet2" { + name = "%s" + ip_cidr_range = "10.0.2.0/24" + region = "us-central1" + private_ip_google_access = true + network = google_compute_network.network2.self_link +} + +resource "google_compute_instance_group_manager" "foobar" { + name = "%s" + version { + instance_template = google_compute_instance_template.foobar.self_link + name = "primary" + } + base_instance_name = "foobar" + zone = "us-central1-f" + target_size = 1 +} + +resource "google_compute_instance_template" "foobar" { + name = "%s" + machine_type = "n1-standard-1" + + network_interface { + subnetwork = google_compute_subnetwork.subnet1.self_link + } + + network_interface { + subnetwork = google_compute_subnetwork.subnet2.self_link + } + + disk { + source_image = data.google_compute_image.my_image.self_link + auto_delete = true + boot = true + } +} + +resource "google_compute_health_check" "default" { + name = "%s" + check_interval_sec = 1 + timeout_sec = 1 + + tcp_health_check { + port = 443 + } +} +`, serviceName, timeout, net1Name, net1Name, net2Name, net2Name, igName, itName, checkName) +} + func testAccComputeRegionBackendService_withInvalidInternalBackend( serviceName, igName, itName, checkName string) string { return fmt.Sprintf(` diff --git a/website/docs/r/compute_region_backend_service.html.markdown b/website/docs/r/compute_region_backend_service.html.markdown index ac121548286..f4852415837 100644 --- a/website/docs/r/compute_region_backend_service.html.markdown +++ b/website/docs/r/compute_region_backend_service.html.markdown @@ -292,6 +292,11 @@ The following arguments are supported: How many seconds to wait for the backend before considering it a failed request. Default is 30 seconds. Valid range is [1, 86400]. +* `network` - + (Optional) + The URL of the network to which this backend service belongs. + This field can only be specified when the load balancing scheme is set to INTERNAL. + * `region` - (Optional) The Region in which the created backend service should reside.