From 2a5fac5ef116372c94d38c9033623164c05ed4a3 Mon Sep 17 00:00:00 2001 From: The Magician Date: Fri, 31 Jan 2020 14:46:41 -0800 Subject: [PATCH] Add conditional validation, allow sending empty capacity scaler for regional backend service (#3033) (#5561) * fix region backend service capacity scaler * add capacity scaler to fr example * remove recopied handwritten test * move constant list into expanders for tpg conversion * change licenses Signed-off-by: Modular Magician --- .changelog/3033.txt | 9 + ...resource_compute_region_backend_service.go | 178 ++++++++-- ...e_region_backend_service_generated_test.go | 4 +- ...rce_compute_region_backend_service_test.go | 314 +++++++++++++++++- google/utils.go | 5 + .../r/compute_forwarding_rule.html.markdown | 1 + ...mpute_region_backend_service.html.markdown | 60 ++-- 7 files changed, 512 insertions(+), 59 deletions(-) create mode 100644 .changelog/3033.txt diff --git a/.changelog/3033.txt b/.changelog/3033.txt new file mode 100644 index 00000000000..0b90930cc46 --- /dev/null +++ b/.changelog/3033.txt @@ -0,0 +1,9 @@ +```release-note:breakingchange +compute: Added conditional requirement of `google_compute_**region**_backend_service` `backend.capacity_scaler` to no longer accept the API default if not INTERNAL. Non-INTERNAL backend services must now specify `capacity_scaler` explicitly and have a total capacity greater than 0. In addition, API default of 1.0 must now be explicitly set and will be treated as nil or zero if not set in config. +``` +```release-note:bug +compute: Fixed `google_compute_**region**_backend_service` so it no longer has a permadiff if `backend.capacity_scaler` is unset in config by requiring capacity scaler. +``` +```release-note:bug +compute: Fixed `backend.capacity_scaler` to actually set zero (0.0) value. +``` diff --git a/google/resource_compute_region_backend_service.go b/google/resource_compute_region_backend_service.go index 905dcc14541..ca5f496aed9 100644 --- a/google/resource_compute_region_backend_service.go +++ b/google/resource_compute_region_backend_service.go @@ -23,11 +23,93 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" - "github.com/hashicorp/terraform-plugin-sdk/terraform" ) -func migrateStateNoop(v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) { - return is, nil +// Fields in "backends" that are not allowed for INTERNAL backend services +// (loadBalancingScheme) - the API returns an error if they are set at all +// in the request. +var backendServiceOnlyNonInternalFieldNames = []string{ + "capacity_scaler", + "max_connections", + "max_connections_per_instance", + "max_connections_per_endpoint", + "max_rate", + "max_rate_per_instance", + "max_rate_per_endpoint", + "max_utilization", +} + +// validateNonInternalBackendServiceBackends ensures capacity_scaler is set for each backend in an non-INTERNAL +// backend service. To prevent a permadiff, we decided to override the API behavior and require the +//// capacity_scaler value in this case. +// +// The API: +// - requires the sum of the backends' capacity_scalers be > 0 +// - defaults to 1 if capacity_scaler is omitted from the request +// +// However, the schema.Set Hash function defaults to 0 if not given, which we chose because it's the default +// float and because INTERNAL backends can't have the value set, so there will be a permadiff for a +// situational non-zero default returned from the API. We can't diff suppress or customdiff a +// field inside a set object in ResourceDiff, since the value also determines the hash for that set object. +func validateNonInternalBackendServiceBackends(backends []interface{}, d *schema.ResourceDiff) error { + sum := 0.0 + + for _, b := range backends { + if b == nil { + continue + } + backend := b.(map[string]interface{}) + if v, ok := backend["capacity_scaler"]; ok && v != nil { + sum += v.(float64) + } else { + return fmt.Errorf("capacity_scaler is required for each backend in non-INTERNAL backend service") + } + } + if sum == 0.0 { + return fmt.Errorf("non-INTERNAL backend service must have at least one non-zero capacity_scaler for backends") + } + return nil +} + +// If INTERNAL, make sure the user did not provide values for any of the fields that cannot be sent. +// We ignore these values regardless when sent to the API, but this adds plan-time validation if a +// user sets the value to non-zero. We can't validate for empty but set because +// of how the SDK handles set objects (on any read, nil fields will get set to empty values) +func validateInternalBackendServiceBackends(backends []interface{}, d *schema.ResourceDiff) error { + for _, b := range backends { + if b == nil { + continue + } + backend := b.(map[string]interface{}) + for _, fn := range backendServiceOnlyNonInternalFieldNames { + if v, ok := backend[fn]; ok && !isEmptyValue(reflect.ValueOf(v)) { + return fmt.Errorf("%q cannot be set for INTERNAL backend service, found value %v", fn, v) + } + } + } + return nil +} + +func customDiffRegionBackendService(d *schema.ResourceDiff, meta interface{}) error { + v, ok := d.GetOk("backend") + if !ok { + return nil + } + if v == nil { + return nil + } + + backends := v.(*schema.Set).List() + if len(backends) == 0 { + return nil + } + + switch d.Get("load_balancing_scheme").(string) { + case "INTERNAL": + return validateInternalBackendServiceBackends(backends, d) + default: + return validateNonInternalBackendServiceBackends(backends, d) + } } func resourceComputeRegionBackendService() *schema.Resource { @@ -49,6 +131,7 @@ func resourceComputeRegionBackendService() *schema.Resource { SchemaVersion: 1, MigrateState: migrateStateNoop, + CustomizeDiff: customDiffRegionBackendService, Schema: map[string]*schema.Schema{ "health_checks": { @@ -202,13 +285,15 @@ partial URL.`, }, "capacity_scaler": { Type: schema.TypeFloat, - Computed: true, Optional: true, Description: `A multiplier applied to the group's maximum servicing capacity (based on UTILIZATION, RATE or CONNECTION). -Default value is 1, which means the group will serve up to 100% -of its configured capacity (depending on balancingMode). +~>**NOTE**: This field cannot be set for +INTERNAL region backend services (default loadBalancingScheme), +but is required for non-INTERNAL backend service. The total +capacity_scaler for all backends must be non-zero. + A setting of 0 means the group is completely drained, offering 0% of its available Capacity. Valid range is [0.0,1.0].`, }, @@ -223,6 +308,7 @@ Provide this property when you create the resource.`, Optional: true, Description: `The max number of simultaneous connections for the group. Can be used with either CONNECTION or UTILIZATION balancing modes. +Cannot be set for INTERNAL backend services. For CONNECTION mode, either maxConnections or one of maxConnectionsPerInstance or maxConnectionsPerEndpoint, @@ -232,28 +318,31 @@ as appropriate for group type, must be set.`, Type: schema.TypeInt, Optional: true, Description: `The max number of simultaneous connections that a single backend -network endpoint can handle. This is used to calculate the -capacity of the group. Can be used in either CONNECTION or -UTILIZATION balancing modes. +network endpoint can handle. Cannot be set +for INTERNAL backend services. -For CONNECTION mode, either -maxConnections or maxConnectionsPerEndpoint must be set.`, +This is used to calculate the capacity of the group. Can be +used in either CONNECTION or UTILIZATION balancing modes. For +CONNECTION mode, either maxConnections or +maxConnectionsPerEndpoint must be set.`, }, "max_connections_per_instance": { Type: schema.TypeInt, Optional: true, Description: `The max number of simultaneous connections that a single -backend instance can handle. This is used to calculate the -capacity of the group. Can be used in either CONNECTION or -UTILIZATION balancing modes. +backend instance can handle. Cannot be set for INTERNAL backend +services. +This is used to calculate the capacity of the group. +Can be used in either CONNECTION or UTILIZATION balancing modes. For CONNECTION mode, either maxConnections or maxConnectionsPerInstance must be set.`, }, "max_rate": { Type: schema.TypeInt, Optional: true, - Description: `The max requests per second (RPS) of the group. + Description: `The max requests per second (RPS) of the group. Cannot be set +for INTERNAL backend services. Can be used with either RATE or UTILIZATION balancing modes, but required if RATE mode. Either maxRate or one @@ -266,7 +355,8 @@ group type, must be set.`, Description: `The max requests per second (RPS) that a single backend network endpoint can handle. This is used to calculate the capacity of the group. Can be used in either balancing mode. For RATE mode, -either maxRate or maxRatePerEndpoint must be set.`, +either maxRate or maxRatePerEndpoint must be set. Cannot be set +for INTERNAL backend services.`, }, "max_rate_per_instance": { Type: schema.TypeFloat, @@ -274,13 +364,15 @@ either maxRate or maxRatePerEndpoint must be set.`, Description: `The max requests per second (RPS) that a single backend instance can handle. This is used to calculate the capacity of the group. Can be used in either balancing mode. For RATE mode, -either maxRate or maxRatePerInstance must be set.`, +either maxRate or maxRatePerInstance must be set. Cannot be set +for INTERNAL backend services.`, }, "max_utilization": { Type: schema.TypeFloat, Optional: true, Description: `Used when balancingMode is UTILIZATION. This ratio defines the -CPU utilization target for the group. Valid range is [0.0, 1.0].`, +CPU utilization target for the group. Valid range is [0.0, 1.0]. +Cannot be set for INTERNAL backend services.`, }, }, } @@ -357,6 +449,11 @@ func resourceComputeRegionBackendServiceCreate(d *schema.ResourceData, meta inte obj["region"] = regionProp } + obj, err = resourceComputeRegionBackendServiceEncoder(d, meta, obj) + if err != nil { + return err + } + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/backendServices") if err != nil { return err @@ -541,6 +638,11 @@ func resourceComputeRegionBackendServiceUpdate(d *schema.ResourceData, meta inte obj["region"] = regionProp } + obj, err = resourceComputeRegionBackendServiceEncoder(d, meta, obj) + if err != nil { + return err + } + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/backendServices/{{name}}") if err != nil { return err @@ -813,7 +915,7 @@ func expandComputeRegionBackendServiceBackend(v interface{}, d TerraformResource transformedCapacityScaler, err := expandComputeRegionBackendServiceBackendCapacityScaler(original["capacity_scaler"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedCapacityScaler); val.IsValid() && !isEmptyValue(val) { + } else { transformed["capacityScaler"] = transformedCapacityScaler } @@ -985,3 +1087,41 @@ func expandComputeRegionBackendServiceRegion(v interface{}, d TerraformResourceD } return f.RelativeLink(), nil } + +func resourceComputeRegionBackendServiceEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + if d.Get("load_balancing_scheme").(string) != "INTERNAL" { + return obj, nil + } + + backendServiceOnlyNonInternalApiFieldNames := []string{ + "capacityScaler", + "maxConnections", + "maxConnectionsPerInstance", + "maxConnectionsPerEndpoint", + "maxRate", + "maxRatePerInstance", + "maxRatePerEndpoint", + "maxUtilization", + } + + var backends []interface{} + if lsV := obj["backends"]; lsV != nil { + backends = lsV.([]interface{}) + } + for idx, v := range backends { + if v == nil { + continue + } + backend := v.(map[string]interface{}) + // Remove fields from backends that cannot be sent for INTERNAL + // backend services + for _, k := range backendServiceOnlyNonInternalApiFieldNames { + log.Printf("[DEBUG] Removing field %q for request for INTERNAL backend service %s", k, d.Get("name")) + delete(backend, k) + } + backends[idx] = backend + } + + obj["backends"] = backends + return obj, nil +} diff --git a/google/resource_compute_region_backend_service_generated_test.go b/google/resource_compute_region_backend_service_generated_test.go index 39ffdc766f3..00b98fe601c 100644 --- a/google/resource_compute_region_backend_service_generated_test.go +++ b/google/resource_compute_region_backend_service_generated_test.go @@ -51,7 +51,7 @@ func TestAccComputeRegionBackendService_regionBackendServiceBasicExample(t *test func testAccComputeRegionBackendService_regionBackendServiceBasicExample(context map[string]interface{}) string { return Nprintf(` resource "google_compute_region_backend_service" "default" { - name = "region-backend-service%{random_suffix}" + name = "tf-test-rbs%{random_suffix}" region = "us-central1" health_checks = [google_compute_health_check.default.self_link] connection_draining_timeout_sec = 10 @@ -59,7 +59,7 @@ resource "google_compute_region_backend_service" "default" { } resource "google_compute_health_check" "default" { - name = "health-check%{random_suffix}" + name = "tf-test-hc%{random_suffix}" check_interval_sec = 1 timeout_sec = 1 diff --git a/google/resource_compute_region_backend_service_test.go b/google/resource_compute_region_backend_service_test.go index 69caf840c82..06d9a76bf39 100644 --- a/google/resource_compute_region_backend_service_test.go +++ b/google/resource_compute_region_backend_service_test.go @@ -2,6 +2,7 @@ package google import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" @@ -41,7 +42,7 @@ func TestAccComputeRegionBackendService_basic(t *testing.T) { }) } -func TestAccComputeRegionBackendService_withBackend(t *testing.T) { +func TestAccComputeRegionBackendService_withBackendInternal(t *testing.T) { t.Parallel() serviceName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) @@ -53,6 +54,11 @@ func TestAccComputeRegionBackendService_withBackend(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckComputeRegionBackendServiceDestroy, Steps: []resource.TestStep{ + { + Config: testAccComputeRegionBackendService_withInvalidInternalBackend( + serviceName, igName, itName, checkName), + ExpectError: regexp.MustCompile(`capacity_scaler" cannot be set for INTERNAL backend service`), + }, { Config: testAccComputeRegionBackendService_withBackend( serviceName, igName, itName, checkName, 10), @@ -62,37 +68,43 @@ func TestAccComputeRegionBackendService_withBackend(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccComputeRegionBackendService_withBackend( + serviceName, igName, itName, checkName, 20), + }, + { + ResourceName: "google_compute_region_backend_service.lipsum", + ImportState: true, + ImportStateVerify: true, + }, }, }) } -func TestAccComputeRegionBackendService_withBackendAndUpdate(t *testing.T) { +func TestAccComputeRegionBackendService_withBackendInternalManaged(t *testing.T) { t.Parallel() serviceName := 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)) + igmName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + hcName := 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_withBackend( - serviceName, igName, itName, checkName, 10), + Config: testAccComputeRegionBackendService_internalManagedInvalidBackend(serviceName, igmName, hcName), + ExpectError: regexp.MustCompile("non-zero capacity_scaler"), }, { - ResourceName: "google_compute_region_backend_service.lipsum", - ImportState: true, - ImportStateVerify: true, + Config: testAccComputeRegionBackendService_internalManagedInvalidMultiBackends(serviceName, igmName, hcName), + ExpectError: regexp.MustCompile("non-zero capacity_scaler"), }, { - Config: testAccComputeRegionBackendService_withBackend( - serviceName, igName, itName, checkName, 20), + Config: testAccComputeRegionBackendService_internalManagedMultipleBackends(serviceName, igmName, hcName), }, { - ResourceName: "google_compute_region_backend_service.lipsum", + ResourceName: "google_compute_region_backend_service.default", ImportState: true, ImportStateVerify: true, }, @@ -241,6 +253,282 @@ resource "google_compute_health_check" "default" { `, serviceName, timeout, igName, itName, checkName) } +func testAccComputeRegionBackendService_withInvalidInternalBackend( + serviceName, igName, itName, checkName string) 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" + + backend { + group = google_compute_instance_group_manager.foobar.instance_group + capacity_scaler = 1.0 + } + + health_checks = [google_compute_health_check.default.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 { + network = "default" + } + + 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, igName, itName, checkName) +} + +func testAccComputeRegionBackendService_internalManagedInvalidBackend(serviceName, igmName, hcName string) string { + return fmt.Sprintf(` +resource "google_compute_region_backend_service" "default" { + name = "%s" + + load_balancing_scheme = "INTERNAL_MANAGED" + + backend { + group = google_compute_region_instance_group_manager.rigm.instance_group + balancing_mode = "UTILIZATION" + } + + region = "us-central1" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_region_health_check.default.self_link] +} + +data "google_compute_image" "debian_image" { + family = "debian-9" + project = "debian-cloud" +} + +resource "google_compute_region_instance_group_manager" "rigm" { + region = "us-central1" + name = "%s" + version { + instance_template = google_compute_instance_template.instance_template.self_link + name = "primary" + } + base_instance_name = "internal-glb" + target_size = 1 +} + +resource "google_compute_instance_template" "instance_template" { + name = "%s-template" + machine_type = "n1-standard-1" + + network_interface { + network = "default" + } + + disk { + source_image = data.google_compute_image.debian_image.self_link + auto_delete = true + boot = true + } +} + +resource "google_compute_region_health_check" "default" { + name = "%s" + region = "us-central1" + + http_health_check { + port_specification = "USE_SERVING_PORT" + } +} +`, serviceName, igmName, igmName, hcName) +} + +func testAccComputeRegionBackendService_internalManagedInvalidMultiBackends(serviceName, igmName, hcName string) string { + return fmt.Sprintf(` +resource "google_compute_region_backend_service" "default" { + name = "%s" + load_balancing_scheme = "INTERNAL_MANAGED" + + backend { + group = google_compute_region_instance_group_manager.rigm1.instance_group + balancing_mode = "UTILIZATION" + capacity_scaler = 0.0 + } + + backend { + group = google_compute_region_instance_group_manager.rigm2.instance_group + balancing_mode = "UTILIZATION" + capacity_scaler = 0.0 + } + + region = "us-central1" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_region_health_check.default.self_link] +} + +data "google_compute_image" "debian_image" { + family = "debian-9" + project = "debian-cloud" +} + +resource "google_compute_region_instance_group_manager" "rigm1" { + name = "%s-1" + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.self_link + name = "primary" + } + base_instance_name = "internal-glb" + target_size = 1 +} + +resource "google_compute_region_instance_group_manager" "rigm2" { + name = "%s-2" + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.self_link + name = "primary" + } + base_instance_name = "internal-glb" + target_size = 1 +} + +resource "google_compute_instance_template" "instance_template" { + name = "%s-template" + machine_type = "n1-standard-1" + + network_interface { + network = "default" + } + + disk { + source_image = data.google_compute_image.debian_image.self_link + auto_delete = true + boot = true + } +} + +resource "google_compute_region_health_check" "default" { + name = "%s" + region = "us-central1" + + http_health_check { + port_specification = "USE_SERVING_PORT" + } +} +`, serviceName, igmName, igmName, igmName, hcName) +} + +func testAccComputeRegionBackendService_internalManagedMultipleBackends(serviceName, igmName, hcName string) string { + return fmt.Sprintf(` +resource "google_compute_region_backend_service" "default" { + name = "%s" + load_balancing_scheme = "INTERNAL_MANAGED" + + backend { + group = google_compute_region_instance_group_manager.rigm1.instance_group + balancing_mode = "UTILIZATION" + } + + backend { + group = google_compute_region_instance_group_manager.rigm2.instance_group + balancing_mode = "UTILIZATION" + capacity_scaler = 1.0 + } + + region = "us-central1" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = [google_compute_region_health_check.default.self_link] +} + +data "google_compute_image" "debian_image" { + family = "debian-9" + project = "debian-cloud" +} + +resource "google_compute_region_instance_group_manager" "rigm1" { + name = "%s-1" + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.self_link + name = "primary" + } + base_instance_name = "internal-glb" + target_size = 1 +} + +resource "google_compute_region_instance_group_manager" "rigm2" { + name = "%s-2" + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.self_link + name = "primary" + } + base_instance_name = "internal-glb" + target_size = 1 +} + +resource "google_compute_instance_template" "instance_template" { + name = "%s-template" + machine_type = "n1-standard-1" + + network_interface { + network = "default" + } + + disk { + source_image = data.google_compute_image.debian_image.self_link + auto_delete = true + boot = true + } +} + +resource "google_compute_region_health_check" "default" { + name = "%s" + region = "us-central1" + + http_health_check { + port_specification = "USE_SERVING_PORT" + } +} +`, serviceName, igmName, igmName, igmName, hcName) +} + func testAccComputeRegionBackendService_withConnectionDraining(serviceName, checkName string, drainingTimeout int64) string { return fmt.Sprintf(` resource "google_compute_region_backend_service" "foobar" { diff --git a/google/utils.go b/google/utils.go index 9c9ce2deec6..1d8fa988b2e 100644 --- a/google/utils.go +++ b/google/utils.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/terraform" "google.golang.org/api/googleapi" ) @@ -572,3 +573,7 @@ func stringInSlice(arr []string, str string) bool { return false } + +func migrateStateNoop(v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) { + return is, nil +} diff --git a/website/docs/r/compute_forwarding_rule.html.markdown b/website/docs/r/compute_forwarding_rule.html.markdown index 2321150e030..95a8b7e074e 100644 --- a/website/docs/r/compute_forwarding_rule.html.markdown +++ b/website/docs/r/compute_forwarding_rule.html.markdown @@ -199,6 +199,7 @@ resource "google_compute_region_backend_service" "default" { backend { group = google_compute_region_instance_group_manager.rigm.instance_group balancing_mode = "UTILIZATION" + capacity_scaler = 1.0 } region = "us-central1" diff --git a/website/docs/r/compute_region_backend_service.html.markdown b/website/docs/r/compute_region_backend_service.html.markdown index 626c134b002..4b0358e7f2b 100644 --- a/website/docs/r/compute_region_backend_service.html.markdown +++ b/website/docs/r/compute_region_backend_service.html.markdown @@ -43,7 +43,7 @@ To get more information about RegionBackendService, see: ```hcl resource "google_compute_region_backend_service" "default" { - name = "region-backend-service" + name = "tf-test-rbs" region = "us-central1" health_checks = [google_compute_health_check.default.self_link] connection_draining_timeout_sec = 10 @@ -51,7 +51,7 @@ resource "google_compute_region_backend_service" "default" { } resource "google_compute_health_check" "default" { - name = "health-check" + name = "tf-test-hc" check_interval_sec = 1 timeout_sec = 1 @@ -73,7 +73,7 @@ resource "google_compute_region_backend_service" "default" { provider = "google-beta" region = "us-central1" - name = "region-backend-service" + name = "tf-test-rbs" health_checks = ["${google_compute_health_check.health_check.self_link}"] protocol = "HTTP" load_balancing_scheme = "INTERNAL_MANAGED" @@ -83,7 +83,7 @@ resource "google_compute_region_backend_service" "default" { resource "google_compute_health_check" "health_check" { provider = "google-beta" - name = "health-check" + name = "tf-test-hc" http_health_check { port = 80 } @@ -102,7 +102,7 @@ resource "google_compute_region_backend_service" "default" { provider = "google-beta" region = "us-central1" - name = "region-backend-service" + name = "tf-test-rbs" health_checks = ["${google_compute_health_check.health_check.self_link}"] load_balancing_scheme = "INTERNAL_MANAGED" locality_lb_policy = "RING_HASH" @@ -128,7 +128,7 @@ resource "google_compute_region_backend_service" "default" { resource "google_compute_health_check" "health_check" { provider = "google-beta" - name = "health-check" + name = "tf-test-hc" http_health_check { port = 80 } @@ -151,10 +151,11 @@ resource "google_compute_region_backend_service" "default" { backend { group = google_compute_region_instance_group_manager.rigm.instance_group balancing_mode = "UTILIZATION" + capacity_scaler = 1.0 } region = "us-central1" - name = "region-backend-service" + name = "tf-test-rbs" protocol = "HTTP" timeout_sec = 10 @@ -172,7 +173,7 @@ resource "google_compute_region_instance_group_manager" "rigm" { provider = google-beta region = "us-central1" - name = "rigm-internal" + name = "tf-test-rigm" version { instance_template = google_compute_instance_template.instance_template.self_link name = "primary" @@ -184,7 +185,7 @@ resource "google_compute_region_instance_group_manager" "rigm" { resource "google_compute_instance_template" "instance_template" { provider = google-beta - name = "template-region-backend-service" + name = "template-tf-test-rbs" machine_type = "n1-standard-1" network_interface { @@ -205,7 +206,7 @@ resource "google_compute_region_health_check" "default" { provider = google-beta region = "us-central1" - name = "health-check" + name = "tf-test-hc" http_health_check { port_specification = "USE_SERVING_PORT" } @@ -214,7 +215,7 @@ resource "google_compute_region_health_check" "default" { resource "google_compute_network" "default" { provider = google-beta - name = "net" + name = "tf-test-net" auto_create_subnetworks = false routing_mode = "REGIONAL" } @@ -222,7 +223,7 @@ resource "google_compute_network" "default" { resource "google_compute_subnetwork" "default" { provider = google-beta - name = "net-default" + name = "tf-test-net-default" ip_cidr_range = "10.1.2.0/24" region = "us-central1" network = google_compute_network.default.self_link @@ -310,8 +311,10 @@ The `backend` block supports: (Optional) A multiplier applied to the group's maximum servicing capacity (based on UTILIZATION, RATE or CONNECTION). - Default value is 1, which means the group will serve up to 100% - of its configured capacity (depending on balancingMode). + ~>**NOTE**: This field cannot be set for + INTERNAL region backend services (default loadBalancingScheme), + but is required for non-INTERNAL backend service. The total + capacity_scaler for all backends must be non-zero. A setting of 0 means the group is completely drained, offering 0% of its available Capacity. Valid range is [0.0,1.0]. @@ -343,6 +346,7 @@ The `backend` block supports: (Optional) The max number of simultaneous connections for the group. Can be used with either CONNECTION or UTILIZATION balancing modes. + Cannot be set for INTERNAL backend services. For CONNECTION mode, either maxConnections or one of maxConnectionsPerInstance or maxConnectionsPerEndpoint, as appropriate for group type, must be set. @@ -350,24 +354,27 @@ The `backend` block supports: * `max_connections_per_instance` - (Optional) The max number of simultaneous connections that a single - backend instance can handle. This is used to calculate the - capacity of the group. Can be used in either CONNECTION or - UTILIZATION balancing modes. + backend instance can handle. Cannot be set for INTERNAL backend + services. + This is used to calculate the capacity of the group. + Can be used in either CONNECTION or UTILIZATION balancing modes. For CONNECTION mode, either maxConnections or maxConnectionsPerInstance must be set. * `max_connections_per_endpoint` - (Optional) The max number of simultaneous connections that a single backend - network endpoint can handle. This is used to calculate the - capacity of the group. Can be used in either CONNECTION or - UTILIZATION balancing modes. - For CONNECTION mode, either - maxConnections or maxConnectionsPerEndpoint must be set. + network endpoint can handle. Cannot be set + for INTERNAL backend services. + This is used to calculate the capacity of the group. Can be + used in either CONNECTION or UTILIZATION balancing modes. For + CONNECTION mode, either maxConnections or + maxConnectionsPerEndpoint must be set. * `max_rate` - (Optional) - The max requests per second (RPS) of the group. + The max requests per second (RPS) of the group. Cannot be set + for INTERNAL backend services. Can be used with either RATE or UTILIZATION balancing modes, but required if RATE mode. Either maxRate or one of maxRatePerInstance or maxRatePerEndpoint, as appropriate for @@ -378,19 +385,22 @@ The `backend` block supports: The max requests per second (RPS) that a single backend instance can handle. This is used to calculate the capacity of the group. Can be used in either balancing mode. For RATE mode, - either maxRate or maxRatePerInstance must be set. + either maxRate or maxRatePerInstance must be set. Cannot be set + for INTERNAL backend services. * `max_rate_per_endpoint` - (Optional) The max requests per second (RPS) that a single backend network endpoint can handle. This is used to calculate the capacity of the group. Can be used in either balancing mode. For RATE mode, - either maxRate or maxRatePerEndpoint must be set. + either maxRate or maxRatePerEndpoint must be set. Cannot be set + for INTERNAL backend services. * `max_utilization` - (Optional) Used when balancingMode is UTILIZATION. This ratio defines the CPU utilization target for the group. Valid range is [0.0, 1.0]. + Cannot be set for INTERNAL backend services. ## Attributes Reference