Skip to content

Commit afbf87a

Browse files
Add maxUtilization field to hash function of BackendService (#3938) (#2620)
Co-authored-by: Dana Hoffman <[email protected]> Signed-off-by: Modular Magician <[email protected]> Co-authored-by: Dana Hoffman <[email protected]>
1 parent b6cab47 commit afbf87a

File tree

3 files changed

+126
-10
lines changed

3 files changed

+126
-10
lines changed

.changelog/3938.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:bug
2+
compute: fixed issue where `google_compute_[region_]backend_service.backend.max_utilization` could not be updated
3+
```

google-beta/resource_compute_backend_service.go

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ import (
3030
"google.golang.org/api/googleapi"
3131
)
3232

33+
// Whether the backend is a global or regional NEG
34+
func isNegBackend(backend map[string]interface{}) bool {
35+
backendGroup, ok := backend["group"]
36+
if !ok {
37+
return false
38+
}
39+
40+
match, err := regexp.MatchString("(?:global|regions/[^/]+)/networkEndpointGroups", backendGroup.(string))
41+
if err != nil {
42+
// should not happen as long as the regexp pattern compiled correctly
43+
return false
44+
}
45+
return match
46+
}
47+
3348
func resourceGoogleComputeBackendServiceBackendHash(v interface{}) int {
3449
if v == nil {
3550
return 0
@@ -129,6 +144,16 @@ func resourceGoogleComputeBackendServiceBackendHash(v interface{}) int {
129144
// the hash function doesn't return something else.
130145
buf.WriteString(fmt.Sprintf("%f-", v.(float64)))
131146
}
147+
if v, ok := m["max_utilization"]; ok && !isNegBackend(m) {
148+
if v == nil {
149+
v = 0.0
150+
}
151+
152+
// floats can't be added to the hash with %v as the other values are because
153+
// %v and %f are not equivalent strings so this must remain as a float so that
154+
// the hash function doesn't return something else.
155+
buf.WriteString(fmt.Sprintf("%f-", v.(float64)))
156+
}
132157

133158
// This is in region backend service, but not in backend service. Should be a no-op
134159
// if it's not present.
@@ -3312,17 +3337,9 @@ func resourceComputeBackendServiceEncoder(d *schema.ResourceData, meta interface
33123337
backends := backendsRaw.([]interface{})
33133338
for _, backendRaw := range backends {
33143339
backend := backendRaw.(map[string]interface{})
3315-
backendGroup, ok := backend["group"]
3316-
if !ok {
3317-
continue
3318-
}
33193340

3320-
match, err := regexp.MatchString("(?:global|regions/[^/]+)/networkEndpointGroups", backendGroup.(string))
3321-
if err != nil {
3322-
return nil, err
3323-
}
3324-
if match {
3325-
// Remove `max_utilization` from any backend that belongs to a serverless NEG. This field
3341+
if isNegBackend(backend) {
3342+
// Remove `max_utilization` from any backend that belongs to an NEG. This field
33263343
// has a default value and causes API validation errors
33273344
backend["maxUtilization"] = nil
33283345
}

google-beta/resource_compute_backend_service_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,44 @@ func TestAccComputeBackendService_withBackend(t *testing.T) {
7474
})
7575
}
7676

77+
func TestAccComputeBackendService_withBackendAndMaxUtilization(t *testing.T) {
78+
serviceName := fmt.Sprintf("tf-test-%s", randString(t, 10))
79+
igName := fmt.Sprintf("tf-test-%s", randString(t, 10))
80+
itName := fmt.Sprintf("tf-test-%s", randString(t, 10))
81+
checkName := fmt.Sprintf("tf-test-%s", randString(t, 10))
82+
vcrTest(t, resource.TestCase{
83+
PreCheck: func() { testAccPreCheck(t) },
84+
Providers: testAccProviders,
85+
CheckDestroy: testAccCheckComputeBackendServiceDestroyProducer(t),
86+
Steps: []resource.TestStep{
87+
{
88+
Config: testAccComputeBackendService_withBackend(
89+
serviceName, igName, itName, checkName, 10),
90+
},
91+
{
92+
ResourceName: "google_compute_backend_service.lipsum",
93+
ImportState: true,
94+
ImportStateVerify: true,
95+
},
96+
{
97+
Config: testAccComputeBackendService_withBackendAndMaxUtilization(
98+
serviceName, igName, itName, checkName, 10),
99+
PlanOnly: true,
100+
ExpectNonEmptyPlan: true,
101+
},
102+
{
103+
Config: testAccComputeBackendService_withBackendAndMaxUtilization(
104+
serviceName, igName, itName, checkName, 10),
105+
},
106+
{
107+
ResourceName: "google_compute_backend_service.lipsum",
108+
ImportState: true,
109+
ImportStateVerify: true,
110+
},
111+
},
112+
})
113+
}
114+
77115
func TestAccComputeBackendService_withBackendAndIAP(t *testing.T) {
78116
serviceName := fmt.Sprintf("tf-test-%s", randString(t, 10))
79117
igName := fmt.Sprintf("tf-test-%s", randString(t, 10))
@@ -929,6 +967,64 @@ resource "google_compute_http_health_check" "default" {
929967
`, serviceName, timeout, igName, itName, checkName)
930968
}
931969

970+
func testAccComputeBackendService_withBackendAndMaxUtilization(
971+
serviceName, igName, itName, checkName string, timeout int64) string {
972+
return fmt.Sprintf(`
973+
data "google_compute_image" "my_image" {
974+
family = "debian-9"
975+
project = "debian-cloud"
976+
}
977+
978+
resource "google_compute_backend_service" "lipsum" {
979+
name = "%s"
980+
description = "Hello World 1234"
981+
port_name = "http"
982+
protocol = "HTTP"
983+
timeout_sec = %v
984+
985+
backend {
986+
group = google_compute_instance_group_manager.foobar.instance_group
987+
max_utilization = 1.0
988+
}
989+
990+
health_checks = [google_compute_http_health_check.default.self_link]
991+
}
992+
993+
resource "google_compute_instance_group_manager" "foobar" {
994+
name = "%s"
995+
version {
996+
instance_template = google_compute_instance_template.foobar.self_link
997+
name = "primary"
998+
}
999+
base_instance_name = "foobar"
1000+
zone = "us-central1-f"
1001+
target_size = 1
1002+
}
1003+
1004+
resource "google_compute_instance_template" "foobar" {
1005+
name = "%s"
1006+
machine_type = "e2-medium"
1007+
1008+
network_interface {
1009+
network = "default"
1010+
}
1011+
1012+
disk {
1013+
source_image = data.google_compute_image.my_image.self_link
1014+
auto_delete = true
1015+
boot = true
1016+
}
1017+
}
1018+
1019+
resource "google_compute_http_health_check" "default" {
1020+
name = "%s"
1021+
request_path = "/"
1022+
check_interval_sec = 1
1023+
timeout_sec = 1
1024+
}
1025+
`, serviceName, timeout, igName, itName, checkName)
1026+
}
1027+
9321028
func testAccComputeBackendService_withBackendAndIAP(
9331029
serviceName, igName, itName, checkName string, timeout int64) string {
9341030
return fmt.Sprintf(`

0 commit comments

Comments
 (0)