Skip to content

Commit 1908975

Browse files
Promote health check resource field grpc_with_tls to GA (#15313) (#24872)
[upstream:604bcbe469671da2f305fa6c1e028d9d68d067a3] Signed-off-by: Modular Magician <[email protected]>
1 parent 1196736 commit 1908975

11 files changed

+702
-23
lines changed

.changelog/15313.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
compute: added `grpc_tls_health_check` field to `google_compute_healthcheck` resource (ga)
3+
```

google/services/compute/resource_compute_health_check.go

Lines changed: 173 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,55 @@ If not specified, gRPC health check follows behavior specified in 'port' and
223223
},
224224
},
225225
},
226-
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check"},
226+
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check", "grpc_tls_health_check"},
227+
},
228+
"grpc_tls_health_check": {
229+
Type: schema.TypeList,
230+
Optional: true,
231+
DiffSuppressFunc: portDiffSuppress,
232+
Description: `A nested object resource.`,
233+
MaxItems: 1,
234+
Elem: &schema.Resource{
235+
Schema: map[string]*schema.Schema{
236+
"grpc_service_name": {
237+
Type: schema.TypeString,
238+
Optional: true,
239+
Description: `The gRPC service name for the health check.
240+
The value of grpcServiceName has the following meanings by convention:
241+
- Empty serviceName means the overall status of all services at the backend.
242+
- Non-empty serviceName means the health of that gRPC service, as defined by the owner of the service.
243+
The grpcServiceName can only be ASCII.`,
244+
AtLeastOneOf: []string{"grpc_tls_health_check.0.port", "grpc_tls_health_check.0.port_specification", "grpc_tls_health_check.0.grpc_service_name"},
245+
},
246+
"port": {
247+
Type: schema.TypeInt,
248+
Optional: true,
249+
Description: `The port number for the health check request.
250+
Must be specified if port_specification is USE_FIXED_PORT. Valid values are 1 through 65535.`,
251+
AtLeastOneOf: []string{"grpc_tls_health_check.0.port", "grpc_tls_health_check.0.port_specification", "grpc_tls_health_check.0.grpc_service_name"},
252+
},
253+
"port_specification": {
254+
Type: schema.TypeString,
255+
Optional: true,
256+
ValidateFunc: verify.ValidateEnum([]string{"USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT", ""}),
257+
Description: `Specifies how port is selected for health checking, can be one of the
258+
following values:
259+
260+
* 'USE_FIXED_PORT': The port number in 'port' is used for health checking.
261+
262+
* 'USE_NAMED_PORT': Not supported for GRPC with TLS health checking.
263+
264+
* 'USE_SERVING_PORT': For NetworkEndpointGroup, the port specified for each
265+
network endpoint is used for health checking. For other backends, the
266+
port or named port specified in the Backend Service is used for health
267+
checking.
268+
269+
If not specified, gRPC with TLS health check follows behavior specified in the 'port' field. Possible values: ["USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT"]`,
270+
AtLeastOneOf: []string{"grpc_tls_health_check.0.port", "grpc_tls_health_check.0.port_specification", "grpc_tls_health_check.0.grpc_service_name"},
271+
},
272+
},
273+
},
274+
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check", "grpc_tls_health_check"},
227275
},
228276
"healthy_threshold": {
229277
Type: schema.TypeInt,
@@ -309,7 +357,7 @@ can only be ASCII.`,
309357
},
310358
},
311359
},
312-
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check"},
360+
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check", "grpc_tls_health_check"},
313361
},
314362
"http_health_check": {
315363
Type: schema.TypeList,
@@ -388,7 +436,7 @@ can only be ASCII.`,
388436
},
389437
},
390438
},
391-
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check"},
439+
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check", "grpc_tls_health_check"},
392440
},
393441
"https_health_check": {
394442
Type: schema.TypeList,
@@ -467,7 +515,7 @@ can only be ASCII.`,
467515
},
468516
},
469517
},
470-
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check"},
518+
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check", "grpc_tls_health_check"},
471519
},
472520
"log_config": {
473521
Type: schema.TypeList,
@@ -583,7 +631,7 @@ can only be ASCII.`,
583631
},
584632
},
585633
},
586-
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check"},
634+
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check", "grpc_tls_health_check"},
587635
},
588636
"tcp_health_check": {
589637
Type: schema.TypeList,
@@ -655,7 +703,7 @@ can only be ASCII.`,
655703
},
656704
},
657705
},
658-
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check"},
706+
ExactlyOneOf: []string{"http_health_check", "https_health_check", "http2_health_check", "tcp_health_check", "ssl_health_check", "grpc_health_check", "grpc_tls_health_check"},
659707
},
660708
"timeout_sec": {
661709
Type: schema.TypeInt,
@@ -783,6 +831,12 @@ func resourceComputeHealthCheckCreate(d *schema.ResourceData, meta interface{})
783831
} else if v, ok := d.GetOkExists("grpc_health_check"); !tpgresource.IsEmptyValue(reflect.ValueOf(grpcHealthCheckProp)) && (ok || !reflect.DeepEqual(v, grpcHealthCheckProp)) {
784832
obj["grpcHealthCheck"] = grpcHealthCheckProp
785833
}
834+
grpcTlsHealthCheckProp, err := expandComputeHealthCheckGrpcTlsHealthCheck(d.Get("grpc_tls_health_check"), d, config)
835+
if err != nil {
836+
return err
837+
} else if v, ok := d.GetOkExists("grpc_tls_health_check"); !tpgresource.IsEmptyValue(reflect.ValueOf(grpcTlsHealthCheckProp)) && (ok || !reflect.DeepEqual(v, grpcTlsHealthCheckProp)) {
838+
obj["grpcTlsHealthCheck"] = grpcTlsHealthCheckProp
839+
}
786840
logConfigProp, err := expandComputeHealthCheckLogConfig(d.Get("log_config"), d, config)
787841
if err != nil {
788842
return err
@@ -938,6 +992,9 @@ func resourceComputeHealthCheckRead(d *schema.ResourceData, meta interface{}) er
938992
if err := d.Set("grpc_health_check", flattenComputeHealthCheckGrpcHealthCheck(res["grpcHealthCheck"], d, config)); err != nil {
939993
return fmt.Errorf("Error reading HealthCheck: %s", err)
940994
}
995+
if err := d.Set("grpc_tls_health_check", flattenComputeHealthCheckGrpcTlsHealthCheck(res["grpcTlsHealthCheck"], d, config)); err != nil {
996+
return fmt.Errorf("Error reading HealthCheck: %s", err)
997+
}
941998
if err := d.Set("log_config", flattenComputeHealthCheckLogConfig(res["logConfig"], d, config)); err != nil {
942999
return fmt.Errorf("Error reading HealthCheck: %s", err)
9431000
}
@@ -1042,6 +1099,12 @@ func resourceComputeHealthCheckUpdate(d *schema.ResourceData, meta interface{})
10421099
} else if v, ok := d.GetOkExists("grpc_health_check"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, grpcHealthCheckProp)) {
10431100
obj["grpcHealthCheck"] = grpcHealthCheckProp
10441101
}
1102+
grpcTlsHealthCheckProp, err := expandComputeHealthCheckGrpcTlsHealthCheck(d.Get("grpc_tls_health_check"), d, config)
1103+
if err != nil {
1104+
return err
1105+
} else if v, ok := d.GetOkExists("grpc_tls_health_check"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, grpcTlsHealthCheckProp)) {
1106+
obj["grpcTlsHealthCheck"] = grpcTlsHealthCheckProp
1107+
}
10451108
logConfigProp, err := expandComputeHealthCheckLogConfig(d.Get("log_config"), d, config)
10461109
if err != nil {
10471110
return err
@@ -1625,6 +1688,48 @@ func flattenComputeHealthCheckGrpcHealthCheckGrpcServiceName(v interface{}, d *s
16251688
return v
16261689
}
16271690

1691+
func flattenComputeHealthCheckGrpcTlsHealthCheck(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1692+
if v == nil {
1693+
return nil
1694+
}
1695+
original := v.(map[string]interface{})
1696+
if len(original) == 0 {
1697+
return nil
1698+
}
1699+
transformed := make(map[string]interface{})
1700+
transformed["port"] =
1701+
flattenComputeHealthCheckGrpcTlsHealthCheckPort(original["port"], d, config)
1702+
transformed["port_specification"] =
1703+
flattenComputeHealthCheckGrpcTlsHealthCheckPortSpecification(original["portSpecification"], d, config)
1704+
transformed["grpc_service_name"] =
1705+
flattenComputeHealthCheckGrpcTlsHealthCheckGrpcServiceName(original["grpcServiceName"], d, config)
1706+
return []interface{}{transformed}
1707+
}
1708+
func flattenComputeHealthCheckGrpcTlsHealthCheckPort(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1709+
// Handles the string fixed64 format
1710+
if strVal, ok := v.(string); ok {
1711+
if intVal, err := tpgresource.StringToFixed64(strVal); err == nil {
1712+
return intVal
1713+
}
1714+
}
1715+
1716+
// number values are represented as float64
1717+
if floatVal, ok := v.(float64); ok {
1718+
intVal := int(floatVal)
1719+
return intVal
1720+
}
1721+
1722+
return v // let terraform core handle it otherwise
1723+
}
1724+
1725+
func flattenComputeHealthCheckGrpcTlsHealthCheckPortSpecification(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1726+
return v
1727+
}
1728+
1729+
func flattenComputeHealthCheckGrpcTlsHealthCheckGrpcServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1730+
return v
1731+
}
1732+
16281733
func flattenComputeHealthCheckLogConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
16291734
transformed := make(map[string]interface{})
16301735
if v == nil {
@@ -2163,6 +2268,54 @@ func expandComputeHealthCheckGrpcHealthCheckGrpcServiceName(v interface{}, d tpg
21632268
return v, nil
21642269
}
21652270

2271+
func expandComputeHealthCheckGrpcTlsHealthCheck(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2272+
if v == nil {
2273+
return nil, nil
2274+
}
2275+
l := v.([]interface{})
2276+
if len(l) == 0 || l[0] == nil {
2277+
return nil, nil
2278+
}
2279+
raw := l[0]
2280+
original := raw.(map[string]interface{})
2281+
transformed := make(map[string]interface{})
2282+
2283+
transformedPort, err := expandComputeHealthCheckGrpcTlsHealthCheckPort(original["port"], d, config)
2284+
if err != nil {
2285+
return nil, err
2286+
} else if val := reflect.ValueOf(transformedPort); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2287+
transformed["port"] = transformedPort
2288+
}
2289+
2290+
transformedPortSpecification, err := expandComputeHealthCheckGrpcTlsHealthCheckPortSpecification(original["port_specification"], d, config)
2291+
if err != nil {
2292+
return nil, err
2293+
} else if val := reflect.ValueOf(transformedPortSpecification); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2294+
transformed["portSpecification"] = transformedPortSpecification
2295+
}
2296+
2297+
transformedGrpcServiceName, err := expandComputeHealthCheckGrpcTlsHealthCheckGrpcServiceName(original["grpc_service_name"], d, config)
2298+
if err != nil {
2299+
return nil, err
2300+
} else if val := reflect.ValueOf(transformedGrpcServiceName); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2301+
transformed["grpcServiceName"] = transformedGrpcServiceName
2302+
}
2303+
2304+
return transformed, nil
2305+
}
2306+
2307+
func expandComputeHealthCheckGrpcTlsHealthCheckPort(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2308+
return v, nil
2309+
}
2310+
2311+
func expandComputeHealthCheckGrpcTlsHealthCheckPortSpecification(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2312+
return v, nil
2313+
}
2314+
2315+
func expandComputeHealthCheckGrpcTlsHealthCheckGrpcServiceName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2316+
return v, nil
2317+
}
2318+
21662319
func expandComputeHealthCheckLogConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
21672320
if v == nil {
21682321
return nil, nil
@@ -2276,5 +2429,19 @@ func resourceComputeHealthCheckEncoder(d *schema.ResourceData, meta interface{},
22762429
return obj, nil
22772430
}
22782431

2432+
if _, ok := d.GetOk("grpc_tls_health_check"); ok {
2433+
hc := d.Get("grpc_tls_health_check").([]interface{})[0]
2434+
ps := hc.(map[string]interface{})["port_specification"]
2435+
2436+
if ps == "USE_FIXED_PORT" || ps == "" {
2437+
m := obj["grpcTlsHealthCheck"].(map[string]interface{})
2438+
if m["port"] == nil {
2439+
return nil, fmt.Errorf("error in HealthCheck %s: `port` must be set for GRPC with TLS health checks`.", d.Get("name").(string))
2440+
}
2441+
}
2442+
obj["type"] = "GRPC_WITH_TLS"
2443+
return obj, nil
2444+
}
2445+
22792446
return nil, fmt.Errorf("error in HealthCheck %s: No health check block specified.", d.Get("name").(string))
22802447
}

google/services/compute/resource_compute_health_check_generated_meta.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ fields:
1414
- api_field: 'grpcHealthCheck.port'
1515
- api_field: 'grpcHealthCheck.portName'
1616
- api_field: 'grpcHealthCheck.portSpecification'
17+
- api_field: 'grpcTlsHealthCheck.grpcServiceName'
18+
- api_field: 'grpcTlsHealthCheck.port'
19+
- api_field: 'grpcTlsHealthCheck.portSpecification'
1720
- api_field: 'healthyThreshold'
1821
- api_field: 'http2HealthCheck.host'
1922
- api_field: 'http2HealthCheck.port'

google/services/compute/resource_compute_health_check_generated_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,89 @@ resource "google_compute_health_check" "grpc-health-check" {
538538
`, context)
539539
}
540540

541+
func TestAccComputeHealthCheck_healthCheckGrpcWithTlsExample(t *testing.T) {
542+
t.Parallel()
543+
544+
context := map[string]interface{}{
545+
"random_suffix": acctest.RandString(t, 10),
546+
}
547+
548+
acctest.VcrTest(t, resource.TestCase{
549+
PreCheck: func() { acctest.AccTestPreCheck(t) },
550+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
551+
CheckDestroy: testAccCheckComputeHealthCheckDestroyProducer(t),
552+
Steps: []resource.TestStep{
553+
{
554+
Config: testAccComputeHealthCheck_healthCheckGrpcWithTlsExample(context),
555+
},
556+
{
557+
ResourceName: "google_compute_health_check.grpc-with-tls-health-check",
558+
ImportState: true,
559+
ImportStateVerify: true,
560+
},
561+
},
562+
})
563+
}
564+
565+
func testAccComputeHealthCheck_healthCheckGrpcWithTlsExample(context map[string]interface{}) string {
566+
return acctest.Nprintf(`
567+
resource "google_compute_health_check" "grpc-with-tls-health-check" {
568+
name = "tf-test-grpc-with-tls-health-check%{random_suffix}"
569+
570+
timeout_sec = 1
571+
check_interval_sec = 1
572+
573+
grpc_tls_health_check {
574+
port = "443"
575+
}
576+
}
577+
`, context)
578+
}
579+
580+
func TestAccComputeHealthCheck_healthCheckGrpcWithTlsFullExample(t *testing.T) {
581+
t.Parallel()
582+
583+
context := map[string]interface{}{
584+
"random_suffix": acctest.RandString(t, 10),
585+
}
586+
587+
acctest.VcrTest(t, resource.TestCase{
588+
PreCheck: func() { acctest.AccTestPreCheck(t) },
589+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
590+
CheckDestroy: testAccCheckComputeHealthCheckDestroyProducer(t),
591+
Steps: []resource.TestStep{
592+
{
593+
Config: testAccComputeHealthCheck_healthCheckGrpcWithTlsFullExample(context),
594+
},
595+
{
596+
ResourceName: "google_compute_health_check.grpc-with-tls-health-check",
597+
ImportState: true,
598+
ImportStateVerify: true,
599+
},
600+
},
601+
})
602+
}
603+
604+
func testAccComputeHealthCheck_healthCheckGrpcWithTlsFullExample(context map[string]interface{}) string {
605+
return acctest.Nprintf(`
606+
resource "google_compute_health_check" "grpc-with-tls-health-check" {
607+
name = "tf-test-grpc-with-tls-health-check%{random_suffix}"
608+
description = "Health check via grpc with TLS"
609+
610+
timeout_sec = 1
611+
check_interval_sec = 1
612+
healthy_threshold = 4
613+
unhealthy_threshold = 5
614+
615+
grpc_tls_health_check {
616+
port_specification = "USE_FIXED_PORT"
617+
port = "443"
618+
grpc_service_name = "testservice"
619+
}
620+
}
621+
`, context)
622+
}
623+
541624
func TestAccComputeHealthCheck_computeHealthCheckHttpSourceRegionsExample(t *testing.T) {
542625
t.Parallel()
543626

0 commit comments

Comments
 (0)