diff --git a/build/ansible b/build/ansible index 4766041fc8ec..ab45d3ee51a7 160000 --- a/build/ansible +++ b/build/ansible @@ -1 +1 @@ -Subproject commit 4766041fc8ecea0fc4e8217345b33a337ccf57c5 +Subproject commit ab45d3ee51a74f496f9d548fe142838891f58769 diff --git a/build/inspec b/build/inspec index d2f9ecacbe4a..f54ad07d4874 160000 --- a/build/inspec +++ b/build/inspec @@ -1 +1 @@ -Subproject commit d2f9ecacbe4ac7cfc16fff0c6267e8be19ff2e5d +Subproject commit f54ad07d48746a1d5fc44cce3ba9eb9e467052c8 diff --git a/build/terraform b/build/terraform index 95ce360790e9..6c3be98e3a34 160000 --- a/build/terraform +++ b/build/terraform @@ -1 +1 @@ -Subproject commit 95ce360790e95978f883086798e9833811189e64 +Subproject commit 6c3be98e3a34f3afdaf45a9e791ec50907582422 diff --git a/build/terraform-beta b/build/terraform-beta index 172a328714f6..bb6089efcf5b 160000 --- a/build/terraform-beta +++ b/build/terraform-beta @@ -1 +1 @@ -Subproject commit 172a328714f66c7c8acdc37309d4803d84cb85a7 +Subproject commit bb6089efcf5baaa2815b88bd8cfb49c7dcb05c8f diff --git a/build/terraform-mapper b/build/terraform-mapper index f7d6e97a7778..b576441baa87 160000 --- a/build/terraform-mapper +++ b/build/terraform-mapper @@ -1 +1 @@ -Subproject commit f7d6e97a77786c74471e4b381a4d9d5092edbb99 +Subproject commit b576441baa87db803b0e069cadb7d9029513a8c8 diff --git a/products/compute/api.yaml b/products/compute/api.yaml index 0334eefc37c8..e5c787195028 100644 --- a/products/compute/api.yaml +++ b/products/compute/api.yaml @@ -620,6 +620,7 @@ objects: and CONNECTION (for TCP/SSL). - !ruby/object:Api::Type::Double name: 'capacityScaler' + send_empty_value: true default_value: 1.0 description: | A multiplier applied to the group's maximum servicing capacity @@ -656,14 +657,17 @@ objects: partial URL. - !ruby/object:Api::Type::Integer name: 'maxConnections' + send_empty_value: true description: | The max number of simultaneous connections for the group. Can be used with either CONNECTION or UTILIZATION balancing modes. - For CONNECTION mode, either maxConnections or - maxConnectionsPerInstance must be set. + For CONNECTION mode, either maxConnections or one + of maxConnectionsPerInstance or maxConnectionsPerEndpoint, + as appropriate for group type, must be set. - !ruby/object:Api::Type::Integer name: 'maxConnectionsPerInstance' + send_empty_value: true description: | The max number of simultaneous connections that a single backend instance can handle. This is used to calculate the @@ -672,23 +676,46 @@ objects: For CONNECTION mode, either maxConnections or maxConnectionsPerInstance must be set. + - !ruby/object:Api::Type::Integer + name: 'maxConnectionsPerEndpoint' + send_empty_value: 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. + + For CONNECTION mode, either + maxConnections or maxConnectionsPerEndpoint must be set. - !ruby/object:Api::Type::Integer name: 'maxRate' + send_empty_value: true description: | The max requests per second (RPS) of the group. Can be used with either RATE or UTILIZATION balancing modes, - but required if RATE mode. For RATE mode, either maxRate or - maxRatePerInstance must be set. + but required if RATE mode. For RATE mode, either maxRate or one + of maxRatePerInstance or maxRatePerEndpoint, as appropriate for + group type, must be set. - !ruby/object:Api::Type::Double name: 'maxRatePerInstance' + send_empty_value: true 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. + - !ruby/object:Api::Type::Double + name: 'maxRatePerEndpoint' + send_empty_value: true + 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. - !ruby/object:Api::Type::Double name: 'maxUtilization' + send_empty_value: true default_value: 0.8 description: | Used when balancingMode is UTILIZATION. This ratio defines the @@ -4974,6 +5001,7 @@ objects: kind: 'compute#networkEndpointGroup' base_url: 'projects/{{project}}/zones/{{zone}}/networkEndpointGroups' input: true + has_self_link: true references: !ruby/object:Api::Resource::ReferenceLinks guides: 'Official Documentation': 'https://cloud.google.com/load-balancing/docs/negs/' diff --git a/templates/terraform/constants/backend_service.go.erb b/templates/terraform/constants/backend_service.go.erb index 743d9bf9c5a7..aeb847122815 100644 --- a/templates/terraform/constants/backend_service.go.erb +++ b/templates/terraform/constants/backend_service.go.erb @@ -94,6 +94,23 @@ func resourceGoogleComputeBackendServiceBackendHash(v interface{}) int { // the hash function doesn't return something else. buf.WriteString(fmt.Sprintf("%f-", v.(float64))) } + if v, ok := m["max_connections_per_endpoint"]; ok { + if v == nil { + v = 0 + } + + buf.WriteString(fmt.Sprintf("%v-", v)) + } + if v, ok := m["max_rate_per_endpoint"]; ok { + if v == nil { + v = 0.0 + } + + // floats can't be added to the hash with %v as the other values are because + // %v and %f are not equivalent strings so this must remain as a float so that + // the hash function doesn't return something else. + buf.WriteString(fmt.Sprintf("%f-", v.(float64))) + } log.Printf("[DEBUG] computed hash value of %v from %v", hashcode.String(buf.String()), buf.String()) return hashcode.String(buf.String()) diff --git a/third_party/terraform/tests/resource_compute_backend_service_test.go.erb b/third_party/terraform/tests/resource_compute_backend_service_test.go.erb index 095aed004048..afbf22267951 100644 --- a/third_party/terraform/tests/resource_compute_backend_service_test.go.erb +++ b/third_party/terraform/tests/resource_compute_backend_service_test.go.erb @@ -604,6 +604,80 @@ func TestAccComputeBackendService_withMaxConnectionsPerInstance(t *testing.T) { } } +func TestAccComputeBackendService_withMaxRatePerEndpoint(t *testing.T) { + t.Parallel() + + randSuffix := acctest.RandString(10) + service := fmt.Sprintf("tf-test-%s", randSuffix) + instance := fmt.Sprintf("tf-test-%s", randSuffix) + neg := fmt.Sprintf("tf-test-%s", randSuffix) + network := fmt.Sprintf("tf-test-%s", randSuffix) + check := fmt.Sprintf("tf-test-%s", randSuffix) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeBackendServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeBackendService_withMaxRatePerEndpoint( + service, instance, neg, network, check, 0.2), + }, + { + ResourceName: "google_compute_backend_service.lipsum", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeBackendService_withMaxRatePerEndpoint( + service, instance, neg, network, check, 0.4), + }, + { + ResourceName: "google_compute_backend_service.lipsum", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeBackendService_withMaxConnectionsPerEndpoint(t *testing.T) { + t.Parallel() + + randSuffix := acctest.RandString(10) + service := fmt.Sprintf("tf-test-%s", randSuffix) + instance := fmt.Sprintf("tf-test-%s", randSuffix) + neg := fmt.Sprintf("tf-test-%s", randSuffix) + network := fmt.Sprintf("tf-test-%s", randSuffix) + check := fmt.Sprintf("tf-test-%s", randSuffix) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeBackendServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeBackendService_withMaxConnectionsPerEndpoint( + service, instance, neg, network, check, 5), + }, + { + ResourceName: "google_compute_backend_service.lipsum", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeBackendService_withMaxConnectionsPerEndpoint( + service, instance, neg, network, check, 10), + }, + { + ResourceName: "google_compute_backend_service.lipsum", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + <% unless version == 'ga' -%> func TestAccComputeBackendService_withCustomHeaders(t *testing.T) { t.Parallel() @@ -1087,6 +1161,163 @@ resource "google_compute_health_check" "default" { `, serviceName, maxConnectionsPerInstance, igName, itName, checkName) } + +func testAccComputeBackendService_withMaxConnectionsPerEndpoint( + service, instance, neg, network, check string, maxConnections int64) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "lipsum" { + name = "%s" + description = "Hello World 1234" + port_name = "http" + protocol = "TCP" + + backend { + group = "${google_compute_network_endpoint_group.lb-neg.self_link}" + balancing_mode = "CONNECTION" + max_connections_per_endpoint = %v + } + + health_checks = ["${google_compute_health_check.default.self_link}"] +} + +data "google_compute_image" "my_image" { + family = "debian-9" + project = "debian-cloud" +} + +resource "google_compute_instance" "endpoint-instance" { + name = "%s" + machine_type = "n1-standard-1" + + boot_disk { + initialize_params{ + image = "${data.google_compute_image.my_image.self_link}" + } + } + + network_interface { + subnetwork = "${google_compute_subnetwork.default.self_link}" + access_config { } + } +} + +resource "google_compute_network_endpoint_group" "lb-neg" { + name = "%s" + network = "${google_compute_network.default.self_link}" + subnetwork = "${google_compute_subnetwork.default.self_link}" + default_port = "90" + zone = "us-central1-a" +} + +resource "google_compute_network_endpoint" "lb-endpoint" { + network_endpoint_group = "${google_compute_network_endpoint_group.lb-neg.name}" + + instance = "${google_compute_instance.endpoint-instance.name}" + port = "${google_compute_network_endpoint_group.lb-neg.default_port}" + ip_address = "${google_compute_instance.endpoint-instance.network_interface.0.network_ip}" +} + +resource "google_compute_network" "default" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + name = "%s" + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" + network = "${google_compute_network.default.self_link}" +} + +resource "google_compute_health_check" "default" { + name = "%s" + tcp_health_check { + port = "110" + } +} +`, service, maxConnections, instance, neg, network, network, check) +} + +func testAccComputeBackendService_withMaxRatePerEndpoint( + service, instance, neg, network, check string, maxRate float64) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "lipsum" { + name = "%s" + description = "Hello World 1234" + port_name = "https" + protocol = "HTTPS" + + backend { + group = "${google_compute_network_endpoint_group.lb-neg.self_link}" + balancing_mode = "RATE" + max_rate_per_endpoint = %v + } + + health_checks = ["${google_compute_health_check.default.self_link}"] +} + +data "google_compute_image" "my_image" { + family = "debian-9" + project = "debian-cloud" +} + +resource "google_compute_instance" "endpoint-instance" { + name = "%s" + machine_type = "n1-standard-1" + + boot_disk { + initialize_params{ + image = "${data.google_compute_image.my_image.self_link}" + } + } + + network_interface { + subnetwork = "${google_compute_subnetwork.default.self_link}" + access_config { } + } +} + +resource "google_compute_network_endpoint_group" "lb-neg" { + name = "%s" + network = "${google_compute_network.default.self_link}" + subnetwork = "${google_compute_subnetwork.default.self_link}" + default_port = "90" + zone = "us-central1-a" +} + +resource "google_compute_network_endpoint" "lb-endpoint" { + network_endpoint_group = "${google_compute_network_endpoint_group.lb-neg.name}" + + instance = "${google_compute_instance.endpoint-instance.name}" + port = "${google_compute_network_endpoint_group.lb-neg.default_port}" + ip_address = "${google_compute_instance.endpoint-instance.network_interface.0.network_ip}" +} + +resource "google_compute_network" "default" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + name = "%s" + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" + network = "${google_compute_network.default.self_link}" +} + +resource "google_compute_health_check" "default" { + name = "%s" + check_interval_sec = 3 + healthy_threshold = 3 + timeout_sec = 2 + unhealthy_threshold = 3 + https_health_check { + port = "443" + } +} +`, service, maxRate, instance, neg, network, network, check) +} + <% unless version == 'ga' -%> func testAccComputeBackendService_withCustomHeaders(serviceName, checkName string) string { return fmt.Sprintf(`