diff --git a/google-beta/provider.go b/google-beta/provider.go index b47b0c153a..b1e09191fa 100644 --- a/google-beta/provider.go +++ b/google-beta/provider.go @@ -517,6 +517,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_compute_node_template": resourceComputeNodeTemplate(), "google_compute_region_autoscaler": resourceComputeRegionAutoscaler(), "google_compute_region_disk": resourceComputeRegionDisk(), + "google_compute_region_health_check": resourceComputeRegionHealthCheck(), "google_compute_resource_policy": resourceComputeResourcePolicy(), "google_compute_route": resourceComputeRoute(), "google_compute_router": resourceComputeRouter(), @@ -524,7 +525,6 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_compute_snapshot": resourceComputeSnapshot(), "google_compute_ssl_certificate": resourceComputeSslCertificate(), "google_compute_managed_ssl_certificate": resourceComputeManagedSslCertificate(), - "google_compute_reservation": resourceComputeReservation(), "google_compute_ssl_policy": resourceComputeSslPolicy(), "google_compute_subnetwork": resourceComputeSubnetwork(), "google_compute_target_http_proxy": resourceComputeTargetHttpProxy(), diff --git a/google-beta/resource_compute_health_check.go b/google-beta/resource_compute_health_check.go index 41bd1f1ac4..52435da82a 100644 --- a/google-beta/resource_compute_health_check.go +++ b/google-beta/resource_compute_health_check.go @@ -61,6 +61,9 @@ func healthCheckCustomizeDiff(diff *schema.ResourceDiff, v interface{}) error { if diff.Get("https_health_check") != nil { return validatePortSpec(diff, "https_health_check") } + if diff.Get("http2_health_check") != nil { + return validatePortSpec(diff, "http2_health_check") + } if diff.Get("tcp_health_check") != nil { return validatePortSpec(diff, "tcp_health_check") } @@ -86,6 +89,8 @@ func portDiffSuppress(k, old, new string, _ *schema.ResourceData) bool { defaultPort = 80 case "https_health_check": defaultPort = 443 + case "http2_health_check": + defaultPort = 443 case "tcp_health_check": defaultPort = 80 case "ssl_health_check": @@ -143,6 +148,49 @@ func resourceComputeHealthCheck() *schema.Resource { Optional: true, Default: 2, }, + "http2_health_check": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: portDiffSuppress, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "host": { + Type: schema.TypeString, + Optional: true, + }, + "port": { + Type: schema.TypeInt, + Optional: true, + }, + "port_name": { + Type: schema.TypeString, + Optional: true, + }, + "port_specification": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT", ""}, false), + }, + "proxy_header": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"NONE", "PROXY_V1", ""}, false), + Default: "NONE", + }, + "request_path": { + Type: schema.TypeString, + Optional: true, + Default: "/", + }, + "response": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + ConflictsWith: []string{"http_health_check", "https_health_check", "tcp_health_check", "ssl_health_check"}, + }, "http_health_check": { Type: schema.TypeList, Optional: true, @@ -184,7 +232,7 @@ func resourceComputeHealthCheck() *schema.Resource { }, }, }, - ConflictsWith: []string{"https_health_check", "tcp_health_check", "ssl_health_check"}, + ConflictsWith: []string{"https_health_check", "tcp_health_check", "ssl_health_check", "http2_health_check"}, }, "https_health_check": { Type: schema.TypeList, @@ -227,7 +275,7 @@ func resourceComputeHealthCheck() *schema.Resource { }, }, }, - ConflictsWith: []string{"http_health_check", "tcp_health_check", "ssl_health_check"}, + ConflictsWith: []string{"http_health_check", "tcp_health_check", "ssl_health_check", "http2_health_check"}, }, "ssl_health_check": { Type: schema.TypeList, @@ -265,7 +313,7 @@ func resourceComputeHealthCheck() *schema.Resource { }, }, }, - ConflictsWith: []string{"http_health_check", "https_health_check", "tcp_health_check"}, + ConflictsWith: []string{"http_health_check", "https_health_check", "tcp_health_check", "http2_health_check"}, }, "tcp_health_check": { Type: schema.TypeList, @@ -303,7 +351,7 @@ func resourceComputeHealthCheck() *schema.Resource { }, }, }, - ConflictsWith: []string{"http_health_check", "https_health_check", "ssl_health_check"}, + ConflictsWith: []string{"http_health_check", "https_health_check", "ssl_health_check", "http2_health_check"}, }, "timeout_sec": { Type: schema.TypeInt, @@ -401,6 +449,12 @@ func resourceComputeHealthCheckCreate(d *schema.ResourceData, meta interface{}) } else if v, ok := d.GetOkExists("ssl_health_check"); !isEmptyValue(reflect.ValueOf(sslHealthCheckProp)) && (ok || !reflect.DeepEqual(v, sslHealthCheckProp)) { obj["sslHealthCheck"] = sslHealthCheckProp } + http2HealthCheckProp, err := expandComputeHealthCheckHttp2HealthCheck(d.Get("http2_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("http2_health_check"); !isEmptyValue(reflect.ValueOf(http2HealthCheckProp)) && (ok || !reflect.DeepEqual(v, http2HealthCheckProp)) { + obj["http2HealthCheck"] = http2HealthCheckProp + } obj, err = resourceComputeHealthCheckEncoder(d, meta, obj) if err != nil { @@ -507,6 +561,9 @@ func resourceComputeHealthCheckRead(d *schema.ResourceData, meta interface{}) er if err := d.Set("ssl_health_check", flattenComputeHealthCheckSslHealthCheck(res["sslHealthCheck"], d)); err != nil { return fmt.Errorf("Error reading HealthCheck: %s", err) } + if err := d.Set("http2_health_check", flattenComputeHealthCheckHttp2HealthCheck(res["http2HealthCheck"], d)); err != nil { + return fmt.Errorf("Error reading HealthCheck: %s", err) + } if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { return fmt.Errorf("Error reading HealthCheck: %s", err) } @@ -583,6 +640,12 @@ func resourceComputeHealthCheckUpdate(d *schema.ResourceData, meta interface{}) } else if v, ok := d.GetOkExists("ssl_health_check"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, sslHealthCheckProp)) { obj["sslHealthCheck"] = sslHealthCheckProp } + http2HealthCheckProp, err := expandComputeHealthCheckHttp2HealthCheck(d.Get("http2_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("http2_health_check"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, http2HealthCheckProp)) { + obj["http2HealthCheck"] = http2HealthCheckProp + } obj, err = resourceComputeHealthCheckEncoder(d, meta, obj) if err != nil { @@ -957,6 +1020,65 @@ func flattenComputeHealthCheckSslHealthCheckPortSpecification(v interface{}, d * return v } +func flattenComputeHealthCheckHttp2HealthCheck(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["host"] = + flattenComputeHealthCheckHttp2HealthCheckHost(original["host"], d) + transformed["request_path"] = + flattenComputeHealthCheckHttp2HealthCheckRequestPath(original["requestPath"], d) + transformed["response"] = + flattenComputeHealthCheckHttp2HealthCheckResponse(original["response"], d) + transformed["port"] = + flattenComputeHealthCheckHttp2HealthCheckPort(original["port"], d) + transformed["port_name"] = + flattenComputeHealthCheckHttp2HealthCheckPortName(original["portName"], d) + transformed["proxy_header"] = + flattenComputeHealthCheckHttp2HealthCheckProxyHeader(original["proxyHeader"], d) + transformed["port_specification"] = + flattenComputeHealthCheckHttp2HealthCheckPortSpecification(original["portSpecification"], d) + return []interface{}{transformed} +} +func flattenComputeHealthCheckHttp2HealthCheckHost(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeHealthCheckHttp2HealthCheckRequestPath(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeHealthCheckHttp2HealthCheckResponse(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeHealthCheckHttp2HealthCheckPort(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeHealthCheckHttp2HealthCheckPortName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeHealthCheckHttp2HealthCheckProxyHeader(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeHealthCheckHttp2HealthCheckPortSpecification(v interface{}, d *schema.ResourceData) interface{} { + return v +} + func expandComputeHealthCheckCheckIntervalSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } @@ -1315,6 +1437,95 @@ func expandComputeHealthCheckSslHealthCheckPortSpecification(v interface{}, d Te return v, nil } +func expandComputeHealthCheckHttp2HealthCheck(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHost, err := expandComputeHealthCheckHttp2HealthCheckHost(original["host"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHost); val.IsValid() && !isEmptyValue(val) { + transformed["host"] = transformedHost + } + + transformedRequestPath, err := expandComputeHealthCheckHttp2HealthCheckRequestPath(original["request_path"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestPath); val.IsValid() && !isEmptyValue(val) { + transformed["requestPath"] = transformedRequestPath + } + + transformedResponse, err := expandComputeHealthCheckHttp2HealthCheckResponse(original["response"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponse); val.IsValid() && !isEmptyValue(val) { + transformed["response"] = transformedResponse + } + + transformedPort, err := expandComputeHealthCheckHttp2HealthCheckPort(original["port"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPort); val.IsValid() && !isEmptyValue(val) { + transformed["port"] = transformedPort + } + + transformedPortName, err := expandComputeHealthCheckHttp2HealthCheckPortName(original["port_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortName); val.IsValid() && !isEmptyValue(val) { + transformed["portName"] = transformedPortName + } + + transformedProxyHeader, err := expandComputeHealthCheckHttp2HealthCheckProxyHeader(original["proxy_header"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedProxyHeader); val.IsValid() && !isEmptyValue(val) { + transformed["proxyHeader"] = transformedProxyHeader + } + + transformedPortSpecification, err := expandComputeHealthCheckHttp2HealthCheckPortSpecification(original["port_specification"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortSpecification); val.IsValid() && !isEmptyValue(val) { + transformed["portSpecification"] = transformedPortSpecification + } + + return transformed, nil +} + +func expandComputeHealthCheckHttp2HealthCheckHost(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeHealthCheckHttp2HealthCheckRequestPath(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeHealthCheckHttp2HealthCheckResponse(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeHealthCheckHttp2HealthCheckPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeHealthCheckHttp2HealthCheckPortName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeHealthCheckHttp2HealthCheckProxyHeader(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeHealthCheckHttp2HealthCheckPortSpecification(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func resourceComputeHealthCheckEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { if _, ok := d.GetOk("http_health_check"); ok { @@ -1343,6 +1554,19 @@ func resourceComputeHealthCheckEncoder(d *schema.ResourceData, meta interface{}, obj["type"] = "HTTPS" return obj, nil } + if _, ok := d.GetOk("http2_health_check"); ok { + hc := d.Get("http2_health_check").([]interface{})[0] + ps := hc.(map[string]interface{})["port_specification"] + + if ps == "USE_FIXED_PORT" || ps == "" { + m := obj["http2HealthCheck"].(map[string]interface{}) + if m["port"] == nil { + m["port"] = 443 + } + } + obj["type"] = "HTTP2" + return obj, nil + } if _, ok := d.GetOk("tcp_health_check"); ok { hc := d.Get("tcp_health_check").([]interface{})[0] ps := hc.(map[string]interface{})["port_specification"] diff --git a/google-beta/resource_compute_health_check_generated_test.go b/google-beta/resource_compute_health_check_generated_test.go index d78f8a788f..d33f640ac3 100644 --- a/google-beta/resource_compute_health_check_generated_test.go +++ b/google-beta/resource_compute_health_check_generated_test.go @@ -24,7 +24,7 @@ import ( "github.com/hashicorp/terraform/terraform" ) -func TestAccComputeHealthCheck_healthCheckBasicExample(t *testing.T) { +func TestAccComputeHealthCheck_healthCheckTcpExample(t *testing.T) { t.Parallel() context := map[string]interface{}{ @@ -37,10 +37,10 @@ func TestAccComputeHealthCheck_healthCheckBasicExample(t *testing.T) { CheckDestroy: testAccCheckComputeHealthCheckDestroy, Steps: []resource.TestStep{ { - Config: testAccComputeHealthCheck_healthCheckBasicExample(context), + Config: testAccComputeHealthCheck_healthCheckTcpExample(context), }, { - ResourceName: "google_compute_health_check.internal-health-check", + ResourceName: "google_compute_health_check.tcp-health-check", ImportState: true, ImportStateVerify: true, }, @@ -48,10 +48,10 @@ func TestAccComputeHealthCheck_healthCheckBasicExample(t *testing.T) { }) } -func testAccComputeHealthCheck_healthCheckBasicExample(context map[string]interface{}) string { +func testAccComputeHealthCheck_healthCheckTcpExample(context map[string]interface{}) string { return Nprintf(` -resource "google_compute_health_check" "internal-health-check" { - name = "internal-service-health-check%{random_suffix}" +resource "google_compute_health_check" "tcp-health-check" { + name = "tcp-health-check%{random_suffix}" timeout_sec = 1 check_interval_sec = 1 @@ -63,6 +63,395 @@ resource "google_compute_health_check" "internal-health-check" { `, context) } +func TestAccComputeHealthCheck_healthCheckTcpFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeHealthCheck_healthCheckTcpFullExample(context), + }, + { + ResourceName: "google_compute_health_check.tcp-health-check", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeHealthCheck_healthCheckTcpFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_health_check" "tcp-health-check" { + name = "tcp-health-check%{random_suffix}" + description = "Health check via tcp" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + tcp_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + request = "ARE YOU HEALTHY?" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + +func TestAccComputeHealthCheck_healthCheckSslExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeHealthCheck_healthCheckSslExample(context), + }, + { + ResourceName: "google_compute_health_check.ssl-health-check", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeHealthCheck_healthCheckSslExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_health_check" "ssl-health-check" { + name = "ssl-health-check%{random_suffix}" + + timeout_sec = 1 + check_interval_sec = 1 + + ssl_health_check { + port = "443" + } +} +`, context) +} + +func TestAccComputeHealthCheck_healthCheckSslFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeHealthCheck_healthCheckSslFullExample(context), + }, + { + ResourceName: "google_compute_health_check.ssl-health-check", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeHealthCheck_healthCheckSslFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_health_check" "ssl-health-check" { + name = "ssl-health-check%{random_suffix}" + description = "Health check via ssl" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + ssl_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + request = "ARE YOU HEALTHY?" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + +func TestAccComputeHealthCheck_healthCheckHttpExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeHealthCheck_healthCheckHttpExample(context), + }, + { + ResourceName: "google_compute_health_check.http-health-check", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeHealthCheck_healthCheckHttpExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_health_check" "http-health-check" { + name = "http-health-check%{random_suffix}" + + timeout_sec = 1 + check_interval_sec = 1 + + http_health_check { + port = 80 + } +} +`, context) +} + +func TestAccComputeHealthCheck_healthCheckHttpFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeHealthCheck_healthCheckHttpFullExample(context), + }, + { + ResourceName: "google_compute_health_check.http-health-check", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeHealthCheck_healthCheckHttpFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_health_check" "http-health-check" { + name = "http-health-check%{random_suffix}" + description = "Health check via http" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + http_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + +func TestAccComputeHealthCheck_healthCheckHttpsExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeHealthCheck_healthCheckHttpsExample(context), + }, + { + ResourceName: "google_compute_health_check.https-health-check", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeHealthCheck_healthCheckHttpsExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_health_check" "https-health-check" { + name = "https-health-check%{random_suffix}" + + timeout_sec = 1 + check_interval_sec = 1 + + https_health_check { + port = "443" + } +} +`, context) +} + +func TestAccComputeHealthCheck_healthCheckHttpsFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeHealthCheck_healthCheckHttpsFullExample(context), + }, + { + ResourceName: "google_compute_health_check.https-health-check", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeHealthCheck_healthCheckHttpsFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_health_check" "https-health-check" { + name = "https-health-check%{random_suffix}" + description = "Health check via https" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + https_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + +func TestAccComputeHealthCheck_healthCheckHttp2Example(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeHealthCheck_healthCheckHttp2Example(context), + }, + { + ResourceName: "google_compute_health_check.http2-health-check", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeHealthCheck_healthCheckHttp2Example(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_health_check" "http2-health-check" { + name = "http2-health-check%{random_suffix}" + + timeout_sec = 1 + check_interval_sec = 1 + + http2_health_check { + port = "443" + } +} +`, context) +} + +func TestAccComputeHealthCheck_healthCheckHttp2FullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeHealthCheck_healthCheckHttp2FullExample(context), + }, + { + ResourceName: "google_compute_health_check.http2-health-check", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeHealthCheck_healthCheckHttp2FullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_health_check" "http2-health-check" { + name = "http2-health-check%{random_suffix}" + description = "Health check via http2" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + http2_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + func testAccCheckComputeHealthCheckDestroy(s *terraform.State) error { for name, rs := range s.RootModule().Resources { if rs.Type != "google_compute_health_check" { diff --git a/google-beta/resource_compute_health_check_test.go b/google-beta/resource_compute_health_check_test.go index 8c20280245..2099515496 100644 --- a/google-beta/resource_compute_health_check_test.go +++ b/google-beta/resource_compute_health_check_test.go @@ -7,15 +7,11 @@ import ( "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - "google.golang.org/api/compute/v1" ) -func TestAccComputeHealthCheck_tcp(t *testing.T) { +func TestAccComputeHealthCheck_tcp_update(t *testing.T) { t.Parallel() - var healthCheck compute.HealthCheck - hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) resource.Test(t, resource.TestCase{ @@ -25,82 +21,14 @@ func TestAccComputeHealthCheck_tcp(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccComputeHealthCheck_tcp(hckName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeHealthCheckExists( - "google_compute_health_check.foobar", &healthCheck), - testAccCheckComputeHealthCheckThresholds( - 3, 3, &healthCheck), - testAccCheckComputeHealthCheckTcpPort(80, &healthCheck), - testAccCheckComputeHealthCheckPortSpec( - "TCP", "", &healthCheck, - ), - ), }, { ResourceName: "google_compute_health_check.foobar", ImportState: true, ImportStateVerify: true, }, - }, - }) -} - -func TestAccComputeHealthCheck_tcp_update(t *testing.T) { - t.Parallel() - - var healthCheck compute.HealthCheck - - hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeHealthCheckDestroy, - Steps: []resource.TestStep{ - { - Config: testAccComputeHealthCheck_tcp(hckName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeHealthCheckExists( - "google_compute_health_check.foobar", &healthCheck), - testAccCheckComputeHealthCheckThresholds( - 3, 3, &healthCheck), - testAccCheckComputeHealthCheckTcpPort(80, &healthCheck), - ), - }, { Config: testAccComputeHealthCheck_tcp_update(hckName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeHealthCheckExists( - "google_compute_health_check.foobar", &healthCheck), - testAccCheckComputeHealthCheckThresholds( - 10, 10, &healthCheck), - testAccCheckComputeHealthCheckTcpPort(8080, &healthCheck), - ), - }, - }, - }) -} - -func TestAccComputeHealthCheck_ssl(t *testing.T) { - t.Parallel() - - var healthCheck compute.HealthCheck - - hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeHealthCheckDestroy, - Steps: []resource.TestStep{ - { - Config: testAccComputeHealthCheck_ssl(hckName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeHealthCheckExists( - "google_compute_health_check.foobar", &healthCheck), - testAccCheckComputeHealthCheckThresholds( - 3, 3, &healthCheck), - ), }, { ResourceName: "google_compute_health_check.foobar", @@ -114,8 +42,6 @@ func TestAccComputeHealthCheck_ssl(t *testing.T) { func TestAccComputeHealthCheck_ssl_port_spec(t *testing.T) { t.Parallel() - var healthCheck compute.HealthCheck - hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) resource.Test(t, resource.TestCase{ @@ -125,37 +51,6 @@ func TestAccComputeHealthCheck_ssl_port_spec(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccComputeHealthCheck_ssl_fixed_port(hckName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeHealthCheckExists( - "google_compute_health_check.foobar", &healthCheck), - testAccCheckComputeHealthCheckPortSpec( - "SSL", "USE_FIXED_PORT", &healthCheck), - ), - }, - }, - }) -} - -func TestAccComputeHealthCheck_http(t *testing.T) { - t.Parallel() - - var healthCheck compute.HealthCheck - - hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeHealthCheckDestroy, - Steps: []resource.TestStep{ - { - Config: testAccComputeHealthCheck_http(hckName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeHealthCheckExists( - "google_compute_health_check.foobar", &healthCheck), - testAccCheckComputeHealthCheckThresholds( - 3, 3, &healthCheck), - ), }, { ResourceName: "google_compute_health_check.foobar", @@ -169,8 +64,6 @@ func TestAccComputeHealthCheck_http(t *testing.T) { func TestAccComputeHealthCheck_http_port_spec(t *testing.T) { t.Parallel() - var healthCheck compute.HealthCheck - hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) resource.Test(t, resource.TestCase{ @@ -184,43 +77,6 @@ func TestAccComputeHealthCheck_http_port_spec(t *testing.T) { }, { Config: testAccComputeHealthCheck_http_named_port(hckName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeHealthCheckExists( - "google_compute_health_check.foobar", &healthCheck), - testAccCheckComputeHealthCheckPortSpec( - "HTTP", "USE_NAMED_PORT", &healthCheck, - ), - ), - }, - }, - }) -} - -func TestAccComputeHealthCheck_https(t *testing.T) { - t.Parallel() - - var healthCheck compute.HealthCheck - - hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeHealthCheckDestroy, - Steps: []resource.TestStep{ - { - Config: testAccComputeHealthCheck_https(hckName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeHealthCheckExists( - "google_compute_health_check.foobar", &healthCheck), - testAccCheckComputeHealthCheckThresholds( - 3, 3, &healthCheck), - ), - }, - { - ResourceName: "google_compute_health_check.foobar", - ImportState: true, - ImportStateVerify: true, }, }, }) @@ -229,8 +85,6 @@ func TestAccComputeHealthCheck_https(t *testing.T) { func TestAccComputeHealthCheck_https_serving_port(t *testing.T) { t.Parallel() - var healthCheck compute.HealthCheck - hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) resource.Test(t, resource.TestCase{ @@ -240,13 +94,6 @@ func TestAccComputeHealthCheck_https_serving_port(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccComputeHealthCheck_https_serving_port(hckName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeHealthCheckExists( - "google_compute_health_check.foobar", &healthCheck), - testAccCheckComputeHealthCheckPortSpec( - "HTTPS", "USE_SERVING_PORT", &healthCheck, - ), - ), }, { ResourceName: "google_compute_health_check.foobar", @@ -279,6 +126,9 @@ func TestAccComputeHealthCheck_typeTransition(t *testing.T) { { Config: testAccComputeHealthCheck_tcp(hckName), }, + { + Config: testAccComputeHealthCheck_http2(hckName), + }, { Config: testAccComputeHealthCheck_https(hckName), }, @@ -304,81 +154,6 @@ func TestAccComputeHealthCheck_tcpAndSsl_shouldFail(t *testing.T) { }) } -func testAccCheckComputeHealthCheckExists(n string, healthCheck *compute.HealthCheck) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - config := testAccProvider.Meta().(*Config) - - found, err := config.clientCompute.HealthChecks.Get( - config.Project, rs.Primary.ID).Do() - if err != nil { - return err - } - - if found.Name != rs.Primary.ID { - return fmt.Errorf("HealthCheck not found") - } - - *healthCheck = *found - - return nil - } -} - -func testAccCheckComputeHealthCheckThresholds(healthy, unhealthy int64, healthCheck *compute.HealthCheck) resource.TestCheckFunc { - return func(s *terraform.State) error { - if healthCheck.HealthyThreshold != healthy { - return fmt.Errorf("HealthyThreshold doesn't match: expected %d, got %d", healthy, healthCheck.HealthyThreshold) - } - - if healthCheck.UnhealthyThreshold != unhealthy { - return fmt.Errorf("UnhealthyThreshold doesn't match: expected %d, got %d", unhealthy, healthCheck.UnhealthyThreshold) - } - - return nil - } -} - -func testAccCheckComputeHealthCheckTcpPort(port int64, healthCheck *compute.HealthCheck) resource.TestCheckFunc { - return func(s *terraform.State) error { - if healthCheck.TcpHealthCheck.Port != port { - return fmt.Errorf("Port doesn't match: expected %v, got %v", port, healthCheck.TcpHealthCheck.Port) - } - return nil - } -} - -func testAccCheckComputeHealthCheckPortSpec(blockType, portSpec string, healthCheck *compute.HealthCheck) resource.TestCheckFunc { - return func(s *terraform.State) error { - var actualPortSpec string - - switch blockType { - case "SSL": - actualPortSpec = healthCheck.SslHealthCheck.PortSpecification - case "HTTP": - actualPortSpec = healthCheck.HttpHealthCheck.PortSpecification - case "HTTPS": - actualPortSpec = healthCheck.HttpsHealthCheck.PortSpecification - case "TCP": - actualPortSpec = healthCheck.TcpHealthCheck.PortSpecification - } - - if actualPortSpec != portSpec { - return fmt.Errorf("Port Specification doesn't match: expected %v, got %v", portSpec, actualPortSpec) - } - - return nil - } -} - func testAccComputeHealthCheck_tcp(hckName string) string { return fmt.Sprintf(` resource "google_compute_health_check" "foobar" { @@ -524,6 +299,22 @@ resource "google_compute_health_check" "foobar" { `, hckName) } +func testAccComputeHealthCheck_http2(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + http2_health_check { + port = "443" + } +} +`, hckName) +} + func testAccComputeHealthCheck_tcpAndSsl_shouldFail(hckName string) string { return fmt.Sprintf(` resource "google_compute_health_check" "foobar" { diff --git a/google-beta/resource_compute_region_health_check.go b/google-beta/resource_compute_region_health_check.go new file mode 100644 index 0000000000..be898bfea2 --- /dev/null +++ b/google-beta/resource_compute_region_health_check.go @@ -0,0 +1,1553 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "log" + "reflect" + "strconv" + "time" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + "google.golang.org/api/compute/v1" +) + +func resourceComputeRegionHealthCheck() *schema.Resource { + return &schema.Resource{ + Create: resourceComputeRegionHealthCheckCreate, + Read: resourceComputeRegionHealthCheckRead, + Update: resourceComputeRegionHealthCheckUpdate, + Delete: resourceComputeRegionHealthCheckDelete, + + Importer: &schema.ResourceImporter{ + State: resourceComputeRegionHealthCheckImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(4 * time.Minute), + Update: schema.DefaultTimeout(4 * time.Minute), + Delete: schema.DefaultTimeout(4 * time.Minute), + }, + + CustomizeDiff: healthCheckCustomizeDiff, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "check_interval_sec": { + Type: schema.TypeInt, + Optional: true, + Default: 5, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "healthy_threshold": { + Type: schema.TypeInt, + Optional: true, + Default: 2, + }, + "http2_health_check": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: portDiffSuppress, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "host": { + Type: schema.TypeString, + Optional: true, + }, + "port": { + Type: schema.TypeInt, + Optional: true, + }, + "port_name": { + Type: schema.TypeString, + Optional: true, + }, + "port_specification": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT", ""}, false), + }, + "proxy_header": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"NONE", "PROXY_V1", ""}, false), + Default: "NONE", + }, + "request_path": { + Type: schema.TypeString, + Optional: true, + Default: "/", + }, + "response": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + ConflictsWith: []string{"http_health_check", "https_health_check", "tcp_health_check", "ssl_health_check"}, + }, + "http_health_check": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: portDiffSuppress, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "host": { + Type: schema.TypeString, + Optional: true, + }, + "port": { + Type: schema.TypeInt, + Optional: true, + }, + "port_name": { + Type: schema.TypeString, + Optional: true, + }, + "port_specification": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT", ""}, false), + }, + "proxy_header": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"NONE", "PROXY_V1", ""}, false), + Default: "NONE", + }, + "request_path": { + Type: schema.TypeString, + Optional: true, + Default: "/", + }, + "response": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + ConflictsWith: []string{"https_health_check", "tcp_health_check", "ssl_health_check", "http2_health_check"}, + }, + "https_health_check": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: portDiffSuppress, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "host": { + Type: schema.TypeString, + Optional: true, + }, + "port": { + Type: schema.TypeInt, + Optional: true, + }, + "port_name": { + Type: schema.TypeString, + Optional: true, + }, + "port_specification": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT", ""}, false), + }, + "proxy_header": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"NONE", "PROXY_V1", ""}, false), + Default: "NONE", + }, + "request_path": { + Type: schema.TypeString, + Optional: true, + Default: "/", + }, + "response": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + ConflictsWith: []string{"http_health_check", "tcp_health_check", "ssl_health_check", "http2_health_check"}, + }, + "region": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + }, + "ssl_health_check": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: portDiffSuppress, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Optional: true, + }, + "port_name": { + Type: schema.TypeString, + Optional: true, + }, + "port_specification": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT", ""}, false), + }, + "proxy_header": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"NONE", "PROXY_V1", ""}, false), + Default: "NONE", + }, + "request": { + Type: schema.TypeString, + Optional: true, + }, + "response": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + ConflictsWith: []string{"http_health_check", "https_health_check", "tcp_health_check", "http2_health_check"}, + }, + "tcp_health_check": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: portDiffSuppress, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Optional: true, + }, + "port_name": { + Type: schema.TypeString, + Optional: true, + }, + "port_specification": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"USE_FIXED_PORT", "USE_NAMED_PORT", "USE_SERVING_PORT", ""}, false), + }, + "proxy_header": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"NONE", "PROXY_V1", ""}, false), + Default: "NONE", + }, + "request": { + Type: schema.TypeString, + Optional: true, + }, + "response": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + ConflictsWith: []string{"http_health_check", "https_health_check", "ssl_health_check", "http2_health_check"}, + }, + "timeout_sec": { + Type: schema.TypeInt, + Optional: true, + Default: 5, + }, + "unhealthy_threshold": { + Type: schema.TypeInt, + Optional: true, + Default: 2, + }, + "creation_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceComputeRegionHealthCheckCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + obj := make(map[string]interface{}) + checkIntervalSecProp, err := expandComputeRegionHealthCheckCheckIntervalSec(d.Get("check_interval_sec"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("check_interval_sec"); !isEmptyValue(reflect.ValueOf(checkIntervalSecProp)) && (ok || !reflect.DeepEqual(v, checkIntervalSecProp)) { + obj["checkIntervalSec"] = checkIntervalSecProp + } + descriptionProp, err := expandComputeRegionHealthCheckDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + healthyThresholdProp, err := expandComputeRegionHealthCheckHealthyThreshold(d.Get("healthy_threshold"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("healthy_threshold"); !isEmptyValue(reflect.ValueOf(healthyThresholdProp)) && (ok || !reflect.DeepEqual(v, healthyThresholdProp)) { + obj["healthyThreshold"] = healthyThresholdProp + } + nameProp, err := expandComputeRegionHealthCheckName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + unhealthyThresholdProp, err := expandComputeRegionHealthCheckUnhealthyThreshold(d.Get("unhealthy_threshold"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("unhealthy_threshold"); !isEmptyValue(reflect.ValueOf(unhealthyThresholdProp)) && (ok || !reflect.DeepEqual(v, unhealthyThresholdProp)) { + obj["unhealthyThreshold"] = unhealthyThresholdProp + } + timeoutSecProp, err := expandComputeRegionHealthCheckTimeoutSec(d.Get("timeout_sec"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("timeout_sec"); !isEmptyValue(reflect.ValueOf(timeoutSecProp)) && (ok || !reflect.DeepEqual(v, timeoutSecProp)) { + obj["timeoutSec"] = timeoutSecProp + } + httpHealthCheckProp, err := expandComputeRegionHealthCheckHttpHealthCheck(d.Get("http_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("http_health_check"); !isEmptyValue(reflect.ValueOf(httpHealthCheckProp)) && (ok || !reflect.DeepEqual(v, httpHealthCheckProp)) { + obj["httpHealthCheck"] = httpHealthCheckProp + } + httpsHealthCheckProp, err := expandComputeRegionHealthCheckHttpsHealthCheck(d.Get("https_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("https_health_check"); !isEmptyValue(reflect.ValueOf(httpsHealthCheckProp)) && (ok || !reflect.DeepEqual(v, httpsHealthCheckProp)) { + obj["httpsHealthCheck"] = httpsHealthCheckProp + } + tcpHealthCheckProp, err := expandComputeRegionHealthCheckTcpHealthCheck(d.Get("tcp_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("tcp_health_check"); !isEmptyValue(reflect.ValueOf(tcpHealthCheckProp)) && (ok || !reflect.DeepEqual(v, tcpHealthCheckProp)) { + obj["tcpHealthCheck"] = tcpHealthCheckProp + } + sslHealthCheckProp, err := expandComputeRegionHealthCheckSslHealthCheck(d.Get("ssl_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("ssl_health_check"); !isEmptyValue(reflect.ValueOf(sslHealthCheckProp)) && (ok || !reflect.DeepEqual(v, sslHealthCheckProp)) { + obj["sslHealthCheck"] = sslHealthCheckProp + } + http2HealthCheckProp, err := expandComputeRegionHealthCheckHttp2HealthCheck(d.Get("http2_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("http2_health_check"); !isEmptyValue(reflect.ValueOf(http2HealthCheckProp)) && (ok || !reflect.DeepEqual(v, http2HealthCheckProp)) { + obj["http2HealthCheck"] = http2HealthCheckProp + } + regionProp, err := expandComputeRegionHealthCheckRegion(d.Get("region"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) { + obj["region"] = regionProp + } + + obj, err = resourceComputeRegionHealthCheckEncoder(d, meta, obj) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/healthChecks") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new RegionHealthCheck: %#v", obj) + project, err := getProject(d, config) + if err != nil { + return err + } + res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return fmt.Errorf("Error creating RegionHealthCheck: %s", err) + } + + // Store the ID now + id, err := replaceVars(d, config, "{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + waitErr := computeOperationWaitTime( + config.clientCompute, op, project, "Creating RegionHealthCheck", + int(d.Timeout(schema.TimeoutCreate).Minutes())) + + if waitErr != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create RegionHealthCheck: %s", waitErr) + } + + log.Printf("[DEBUG] Finished creating RegionHealthCheck %q: %#v", d.Id(), res) + + return resourceComputeRegionHealthCheckRead(d, meta) +} + +func resourceComputeRegionHealthCheckRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/healthChecks/{{name}}") + if err != nil { + return err + } + + project, err := getProject(d, config) + if err != nil { + return err + } + res, err := sendRequest(config, "GET", project, url, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("ComputeRegionHealthCheck %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + + if err := d.Set("check_interval_sec", flattenComputeRegionHealthCheckCheckIntervalSec(res["checkIntervalSec"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("creation_timestamp", flattenComputeRegionHealthCheckCreationTimestamp(res["creationTimestamp"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("description", flattenComputeRegionHealthCheckDescription(res["description"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("healthy_threshold", flattenComputeRegionHealthCheckHealthyThreshold(res["healthyThreshold"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("name", flattenComputeRegionHealthCheckName(res["name"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("unhealthy_threshold", flattenComputeRegionHealthCheckUnhealthyThreshold(res["unhealthyThreshold"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("timeout_sec", flattenComputeRegionHealthCheckTimeoutSec(res["timeoutSec"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("type", flattenComputeRegionHealthCheckType(res["type"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("http_health_check", flattenComputeRegionHealthCheckHttpHealthCheck(res["httpHealthCheck"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("https_health_check", flattenComputeRegionHealthCheckHttpsHealthCheck(res["httpsHealthCheck"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("tcp_health_check", flattenComputeRegionHealthCheckTcpHealthCheck(res["tcpHealthCheck"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("ssl_health_check", flattenComputeRegionHealthCheckSslHealthCheck(res["sslHealthCheck"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("http2_health_check", flattenComputeRegionHealthCheckHttp2HealthCheck(res["http2HealthCheck"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("region", flattenComputeRegionHealthCheckRegion(res["region"], d)); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { + return fmt.Errorf("Error reading RegionHealthCheck: %s", err) + } + + return nil +} + +func resourceComputeRegionHealthCheckUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + checkIntervalSecProp, err := expandComputeRegionHealthCheckCheckIntervalSec(d.Get("check_interval_sec"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("check_interval_sec"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, checkIntervalSecProp)) { + obj["checkIntervalSec"] = checkIntervalSecProp + } + descriptionProp, err := expandComputeRegionHealthCheckDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + healthyThresholdProp, err := expandComputeRegionHealthCheckHealthyThreshold(d.Get("healthy_threshold"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("healthy_threshold"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, healthyThresholdProp)) { + obj["healthyThreshold"] = healthyThresholdProp + } + nameProp, err := expandComputeRegionHealthCheckName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + unhealthyThresholdProp, err := expandComputeRegionHealthCheckUnhealthyThreshold(d.Get("unhealthy_threshold"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("unhealthy_threshold"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, unhealthyThresholdProp)) { + obj["unhealthyThreshold"] = unhealthyThresholdProp + } + timeoutSecProp, err := expandComputeRegionHealthCheckTimeoutSec(d.Get("timeout_sec"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("timeout_sec"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, timeoutSecProp)) { + obj["timeoutSec"] = timeoutSecProp + } + httpHealthCheckProp, err := expandComputeRegionHealthCheckHttpHealthCheck(d.Get("http_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("http_health_check"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, httpHealthCheckProp)) { + obj["httpHealthCheck"] = httpHealthCheckProp + } + httpsHealthCheckProp, err := expandComputeRegionHealthCheckHttpsHealthCheck(d.Get("https_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("https_health_check"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, httpsHealthCheckProp)) { + obj["httpsHealthCheck"] = httpsHealthCheckProp + } + tcpHealthCheckProp, err := expandComputeRegionHealthCheckTcpHealthCheck(d.Get("tcp_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("tcp_health_check"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, tcpHealthCheckProp)) { + obj["tcpHealthCheck"] = tcpHealthCheckProp + } + sslHealthCheckProp, err := expandComputeRegionHealthCheckSslHealthCheck(d.Get("ssl_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("ssl_health_check"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, sslHealthCheckProp)) { + obj["sslHealthCheck"] = sslHealthCheckProp + } + http2HealthCheckProp, err := expandComputeRegionHealthCheckHttp2HealthCheck(d.Get("http2_health_check"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("http2_health_check"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, http2HealthCheckProp)) { + obj["http2HealthCheck"] = http2HealthCheckProp + } + regionProp, err := expandComputeRegionHealthCheckRegion(d.Get("region"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, regionProp)) { + obj["region"] = regionProp + } + + obj, err = resourceComputeRegionHealthCheckEncoder(d, meta, obj) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/healthChecks/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating RegionHealthCheck %q: %#v", d.Id(), obj) + res, err := sendRequestWithTimeout(config, "PUT", project, url, obj, d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return fmt.Errorf("Error updating RegionHealthCheck %q: %s", d.Id(), err) + } + + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + err = computeOperationWaitTime( + config.clientCompute, op, project, "Updating RegionHealthCheck", + int(d.Timeout(schema.TimeoutUpdate).Minutes())) + + if err != nil { + return err + } + + return resourceComputeRegionHealthCheckRead(d, meta) +} + +func resourceComputeRegionHealthCheckDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + project, err := getProject(d, config) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/healthChecks/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting RegionHealthCheck %q", d.Id()) + + res, err := sendRequestWithTimeout(config, "DELETE", project, url, obj, d.Timeout(schema.TimeoutDelete)) + if err != nil { + return handleNotFoundError(err, d, "RegionHealthCheck") + } + + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + err = computeOperationWaitTime( + config.clientCompute, op, project, "Deleting RegionHealthCheck", + int(d.Timeout(schema.TimeoutDelete).Minutes())) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting RegionHealthCheck %q: %#v", d.Id(), res) + return nil +} + +func resourceComputeRegionHealthCheckImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + if err := parseImportId([]string{ + "projects/(?P[^/]+)/regions/(?P[^/]+)/healthChecks/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVars(d, config, "{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenComputeRegionHealthCheckCheckIntervalSec(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionHealthCheckCreationTimestamp(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckDescription(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHealthyThreshold(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionHealthCheckName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckUnhealthyThreshold(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionHealthCheckTimeoutSec(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionHealthCheckType(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpHealthCheck(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["host"] = + flattenComputeRegionHealthCheckHttpHealthCheckHost(original["host"], d) + transformed["request_path"] = + flattenComputeRegionHealthCheckHttpHealthCheckRequestPath(original["requestPath"], d) + transformed["response"] = + flattenComputeRegionHealthCheckHttpHealthCheckResponse(original["response"], d) + transformed["port"] = + flattenComputeRegionHealthCheckHttpHealthCheckPort(original["port"], d) + transformed["port_name"] = + flattenComputeRegionHealthCheckHttpHealthCheckPortName(original["portName"], d) + transformed["proxy_header"] = + flattenComputeRegionHealthCheckHttpHealthCheckProxyHeader(original["proxyHeader"], d) + transformed["port_specification"] = + flattenComputeRegionHealthCheckHttpHealthCheckPortSpecification(original["portSpecification"], d) + return []interface{}{transformed} +} +func flattenComputeRegionHealthCheckHttpHealthCheckHost(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpHealthCheckRequestPath(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpHealthCheckResponse(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpHealthCheckPort(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionHealthCheckHttpHealthCheckPortName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpHealthCheckProxyHeader(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpHealthCheckPortSpecification(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpsHealthCheck(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["host"] = + flattenComputeRegionHealthCheckHttpsHealthCheckHost(original["host"], d) + transformed["request_path"] = + flattenComputeRegionHealthCheckHttpsHealthCheckRequestPath(original["requestPath"], d) + transformed["response"] = + flattenComputeRegionHealthCheckHttpsHealthCheckResponse(original["response"], d) + transformed["port"] = + flattenComputeRegionHealthCheckHttpsHealthCheckPort(original["port"], d) + transformed["port_name"] = + flattenComputeRegionHealthCheckHttpsHealthCheckPortName(original["portName"], d) + transformed["proxy_header"] = + flattenComputeRegionHealthCheckHttpsHealthCheckProxyHeader(original["proxyHeader"], d) + transformed["port_specification"] = + flattenComputeRegionHealthCheckHttpsHealthCheckPortSpecification(original["portSpecification"], d) + return []interface{}{transformed} +} +func flattenComputeRegionHealthCheckHttpsHealthCheckHost(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpsHealthCheckRequestPath(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpsHealthCheckResponse(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpsHealthCheckPort(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionHealthCheckHttpsHealthCheckPortName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpsHealthCheckProxyHeader(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttpsHealthCheckPortSpecification(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckTcpHealthCheck(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["request"] = + flattenComputeRegionHealthCheckTcpHealthCheckRequest(original["request"], d) + transformed["response"] = + flattenComputeRegionHealthCheckTcpHealthCheckResponse(original["response"], d) + transformed["port"] = + flattenComputeRegionHealthCheckTcpHealthCheckPort(original["port"], d) + transformed["port_name"] = + flattenComputeRegionHealthCheckTcpHealthCheckPortName(original["portName"], d) + transformed["proxy_header"] = + flattenComputeRegionHealthCheckTcpHealthCheckProxyHeader(original["proxyHeader"], d) + transformed["port_specification"] = + flattenComputeRegionHealthCheckTcpHealthCheckPortSpecification(original["portSpecification"], d) + return []interface{}{transformed} +} +func flattenComputeRegionHealthCheckTcpHealthCheckRequest(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckTcpHealthCheckResponse(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckTcpHealthCheckPort(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionHealthCheckTcpHealthCheckPortName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckTcpHealthCheckProxyHeader(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckTcpHealthCheckPortSpecification(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckSslHealthCheck(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["request"] = + flattenComputeRegionHealthCheckSslHealthCheckRequest(original["request"], d) + transformed["response"] = + flattenComputeRegionHealthCheckSslHealthCheckResponse(original["response"], d) + transformed["port"] = + flattenComputeRegionHealthCheckSslHealthCheckPort(original["port"], d) + transformed["port_name"] = + flattenComputeRegionHealthCheckSslHealthCheckPortName(original["portName"], d) + transformed["proxy_header"] = + flattenComputeRegionHealthCheckSslHealthCheckProxyHeader(original["proxyHeader"], d) + transformed["port_specification"] = + flattenComputeRegionHealthCheckSslHealthCheckPortSpecification(original["portSpecification"], d) + return []interface{}{transformed} +} +func flattenComputeRegionHealthCheckSslHealthCheckRequest(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckSslHealthCheckResponse(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckSslHealthCheckPort(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionHealthCheckSslHealthCheckPortName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckSslHealthCheckProxyHeader(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckSslHealthCheckPortSpecification(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttp2HealthCheck(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["host"] = + flattenComputeRegionHealthCheckHttp2HealthCheckHost(original["host"], d) + transformed["request_path"] = + flattenComputeRegionHealthCheckHttp2HealthCheckRequestPath(original["requestPath"], d) + transformed["response"] = + flattenComputeRegionHealthCheckHttp2HealthCheckResponse(original["response"], d) + transformed["port"] = + flattenComputeRegionHealthCheckHttp2HealthCheckPort(original["port"], d) + transformed["port_name"] = + flattenComputeRegionHealthCheckHttp2HealthCheckPortName(original["portName"], d) + transformed["proxy_header"] = + flattenComputeRegionHealthCheckHttp2HealthCheckProxyHeader(original["proxyHeader"], d) + transformed["port_specification"] = + flattenComputeRegionHealthCheckHttp2HealthCheckPortSpecification(original["portSpecification"], d) + return []interface{}{transformed} +} +func flattenComputeRegionHealthCheckHttp2HealthCheckHost(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttp2HealthCheckRequestPath(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttp2HealthCheckResponse(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttp2HealthCheckPort(v interface{}, d *schema.ResourceData) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} + +func flattenComputeRegionHealthCheckHttp2HealthCheckPortName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttp2HealthCheckProxyHeader(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckHttp2HealthCheckPortSpecification(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionHealthCheckRegion(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return v + } + return NameFromSelfLinkStateFunc(v) +} + +func expandComputeRegionHealthCheckCheckIntervalSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHealthyThreshold(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckUnhealthyThreshold(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpHealthCheck(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHost, err := expandComputeRegionHealthCheckHttpHealthCheckHost(original["host"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHost); val.IsValid() && !isEmptyValue(val) { + transformed["host"] = transformedHost + } + + transformedRequestPath, err := expandComputeRegionHealthCheckHttpHealthCheckRequestPath(original["request_path"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestPath); val.IsValid() && !isEmptyValue(val) { + transformed["requestPath"] = transformedRequestPath + } + + transformedResponse, err := expandComputeRegionHealthCheckHttpHealthCheckResponse(original["response"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponse); val.IsValid() && !isEmptyValue(val) { + transformed["response"] = transformedResponse + } + + transformedPort, err := expandComputeRegionHealthCheckHttpHealthCheckPort(original["port"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPort); val.IsValid() && !isEmptyValue(val) { + transformed["port"] = transformedPort + } + + transformedPortName, err := expandComputeRegionHealthCheckHttpHealthCheckPortName(original["port_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortName); val.IsValid() && !isEmptyValue(val) { + transformed["portName"] = transformedPortName + } + + transformedProxyHeader, err := expandComputeRegionHealthCheckHttpHealthCheckProxyHeader(original["proxy_header"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedProxyHeader); val.IsValid() && !isEmptyValue(val) { + transformed["proxyHeader"] = transformedProxyHeader + } + + transformedPortSpecification, err := expandComputeRegionHealthCheckHttpHealthCheckPortSpecification(original["port_specification"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortSpecification); val.IsValid() && !isEmptyValue(val) { + transformed["portSpecification"] = transformedPortSpecification + } + + return transformed, nil +} + +func expandComputeRegionHealthCheckHttpHealthCheckHost(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpHealthCheckRequestPath(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpHealthCheckResponse(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpHealthCheckPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpHealthCheckPortName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpHealthCheckProxyHeader(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpHealthCheckPortSpecification(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpsHealthCheck(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHost, err := expandComputeRegionHealthCheckHttpsHealthCheckHost(original["host"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHost); val.IsValid() && !isEmptyValue(val) { + transformed["host"] = transformedHost + } + + transformedRequestPath, err := expandComputeRegionHealthCheckHttpsHealthCheckRequestPath(original["request_path"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestPath); val.IsValid() && !isEmptyValue(val) { + transformed["requestPath"] = transformedRequestPath + } + + transformedResponse, err := expandComputeRegionHealthCheckHttpsHealthCheckResponse(original["response"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponse); val.IsValid() && !isEmptyValue(val) { + transformed["response"] = transformedResponse + } + + transformedPort, err := expandComputeRegionHealthCheckHttpsHealthCheckPort(original["port"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPort); val.IsValid() && !isEmptyValue(val) { + transformed["port"] = transformedPort + } + + transformedPortName, err := expandComputeRegionHealthCheckHttpsHealthCheckPortName(original["port_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortName); val.IsValid() && !isEmptyValue(val) { + transformed["portName"] = transformedPortName + } + + transformedProxyHeader, err := expandComputeRegionHealthCheckHttpsHealthCheckProxyHeader(original["proxy_header"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedProxyHeader); val.IsValid() && !isEmptyValue(val) { + transformed["proxyHeader"] = transformedProxyHeader + } + + transformedPortSpecification, err := expandComputeRegionHealthCheckHttpsHealthCheckPortSpecification(original["port_specification"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortSpecification); val.IsValid() && !isEmptyValue(val) { + transformed["portSpecification"] = transformedPortSpecification + } + + return transformed, nil +} + +func expandComputeRegionHealthCheckHttpsHealthCheckHost(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpsHealthCheckRequestPath(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpsHealthCheckResponse(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpsHealthCheckPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpsHealthCheckPortName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpsHealthCheckProxyHeader(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttpsHealthCheckPortSpecification(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckTcpHealthCheck(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedRequest, err := expandComputeRegionHealthCheckTcpHealthCheckRequest(original["request"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequest); val.IsValid() && !isEmptyValue(val) { + transformed["request"] = transformedRequest + } + + transformedResponse, err := expandComputeRegionHealthCheckTcpHealthCheckResponse(original["response"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponse); val.IsValid() && !isEmptyValue(val) { + transformed["response"] = transformedResponse + } + + transformedPort, err := expandComputeRegionHealthCheckTcpHealthCheckPort(original["port"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPort); val.IsValid() && !isEmptyValue(val) { + transformed["port"] = transformedPort + } + + transformedPortName, err := expandComputeRegionHealthCheckTcpHealthCheckPortName(original["port_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortName); val.IsValid() && !isEmptyValue(val) { + transformed["portName"] = transformedPortName + } + + transformedProxyHeader, err := expandComputeRegionHealthCheckTcpHealthCheckProxyHeader(original["proxy_header"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedProxyHeader); val.IsValid() && !isEmptyValue(val) { + transformed["proxyHeader"] = transformedProxyHeader + } + + transformedPortSpecification, err := expandComputeRegionHealthCheckTcpHealthCheckPortSpecification(original["port_specification"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortSpecification); val.IsValid() && !isEmptyValue(val) { + transformed["portSpecification"] = transformedPortSpecification + } + + return transformed, nil +} + +func expandComputeRegionHealthCheckTcpHealthCheckRequest(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckTcpHealthCheckResponse(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckTcpHealthCheckPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckTcpHealthCheckPortName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckTcpHealthCheckProxyHeader(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckTcpHealthCheckPortSpecification(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckSslHealthCheck(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedRequest, err := expandComputeRegionHealthCheckSslHealthCheckRequest(original["request"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequest); val.IsValid() && !isEmptyValue(val) { + transformed["request"] = transformedRequest + } + + transformedResponse, err := expandComputeRegionHealthCheckSslHealthCheckResponse(original["response"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponse); val.IsValid() && !isEmptyValue(val) { + transformed["response"] = transformedResponse + } + + transformedPort, err := expandComputeRegionHealthCheckSslHealthCheckPort(original["port"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPort); val.IsValid() && !isEmptyValue(val) { + transformed["port"] = transformedPort + } + + transformedPortName, err := expandComputeRegionHealthCheckSslHealthCheckPortName(original["port_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortName); val.IsValid() && !isEmptyValue(val) { + transformed["portName"] = transformedPortName + } + + transformedProxyHeader, err := expandComputeRegionHealthCheckSslHealthCheckProxyHeader(original["proxy_header"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedProxyHeader); val.IsValid() && !isEmptyValue(val) { + transformed["proxyHeader"] = transformedProxyHeader + } + + transformedPortSpecification, err := expandComputeRegionHealthCheckSslHealthCheckPortSpecification(original["port_specification"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortSpecification); val.IsValid() && !isEmptyValue(val) { + transformed["portSpecification"] = transformedPortSpecification + } + + return transformed, nil +} + +func expandComputeRegionHealthCheckSslHealthCheckRequest(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckSslHealthCheckResponse(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckSslHealthCheckPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckSslHealthCheckPortName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckSslHealthCheckProxyHeader(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckSslHealthCheckPortSpecification(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttp2HealthCheck(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHost, err := expandComputeRegionHealthCheckHttp2HealthCheckHost(original["host"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHost); val.IsValid() && !isEmptyValue(val) { + transformed["host"] = transformedHost + } + + transformedRequestPath, err := expandComputeRegionHealthCheckHttp2HealthCheckRequestPath(original["request_path"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestPath); val.IsValid() && !isEmptyValue(val) { + transformed["requestPath"] = transformedRequestPath + } + + transformedResponse, err := expandComputeRegionHealthCheckHttp2HealthCheckResponse(original["response"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponse); val.IsValid() && !isEmptyValue(val) { + transformed["response"] = transformedResponse + } + + transformedPort, err := expandComputeRegionHealthCheckHttp2HealthCheckPort(original["port"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPort); val.IsValid() && !isEmptyValue(val) { + transformed["port"] = transformedPort + } + + transformedPortName, err := expandComputeRegionHealthCheckHttp2HealthCheckPortName(original["port_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortName); val.IsValid() && !isEmptyValue(val) { + transformed["portName"] = transformedPortName + } + + transformedProxyHeader, err := expandComputeRegionHealthCheckHttp2HealthCheckProxyHeader(original["proxy_header"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedProxyHeader); val.IsValid() && !isEmptyValue(val) { + transformed["proxyHeader"] = transformedProxyHeader + } + + transformedPortSpecification, err := expandComputeRegionHealthCheckHttp2HealthCheckPortSpecification(original["port_specification"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPortSpecification); val.IsValid() && !isEmptyValue(val) { + transformed["portSpecification"] = transformedPortSpecification + } + + return transformed, nil +} + +func expandComputeRegionHealthCheckHttp2HealthCheckHost(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttp2HealthCheckRequestPath(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttp2HealthCheckResponse(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttp2HealthCheckPort(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttp2HealthCheckPortName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttp2HealthCheckProxyHeader(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckHttp2HealthCheckPortSpecification(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionHealthCheckRegion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for region: %s", err) + } + return f.RelativeLink(), nil +} + +func resourceComputeRegionHealthCheckEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + + if _, ok := d.GetOk("http_health_check"); ok { + hc := d.Get("http_health_check").([]interface{})[0] + ps := hc.(map[string]interface{})["port_specification"] + + if ps == "USE_FIXED_PORT" || ps == "" { + m := obj["httpHealthCheck"].(map[string]interface{}) + if m["port"] == nil { + m["port"] = 80 + } + } + obj["type"] = "HTTP" + return obj, nil + } + if _, ok := d.GetOk("https_health_check"); ok { + hc := d.Get("https_health_check").([]interface{})[0] + ps := hc.(map[string]interface{})["port_specification"] + + if ps == "USE_FIXED_PORT" || ps == "" { + m := obj["httpsHealthCheck"].(map[string]interface{}) + if m["port"] == nil { + m["port"] = 443 + } + } + obj["type"] = "HTTPS" + return obj, nil + } + if _, ok := d.GetOk("http2_health_check"); ok { + hc := d.Get("http2_health_check").([]interface{})[0] + ps := hc.(map[string]interface{})["port_specification"] + + if ps == "USE_FIXED_PORT" || ps == "" { + m := obj["http2HealthCheck"].(map[string]interface{}) + if m["port"] == nil { + m["port"] = 443 + } + } + obj["type"] = "HTTP2" + return obj, nil + } + if _, ok := d.GetOk("tcp_health_check"); ok { + hc := d.Get("tcp_health_check").([]interface{})[0] + ps := hc.(map[string]interface{})["port_specification"] + + if ps == "USE_FIXED_PORT" || ps == "" { + m := obj["tcpHealthCheck"].(map[string]interface{}) + if m["port"] == nil { + m["port"] = 80 + } + } + obj["type"] = "TCP" + return obj, nil + } + if _, ok := d.GetOk("ssl_health_check"); ok { + hc := d.Get("ssl_health_check").([]interface{})[0] + ps := hc.(map[string]interface{})["port_specification"] + + if ps == "USE_FIXED_PORT" || ps == "" { + m := obj["sslHealthCheck"].(map[string]interface{}) + if m["port"] == nil { + m["port"] = 443 + } + } + obj["type"] = "SSL" + return obj, nil + } + + return nil, fmt.Errorf("error in HealthCheck %s: No health check block specified.", d.Get("name").(string)) +} diff --git a/google-beta/resource_compute_region_health_check_generated_test.go b/google-beta/resource_compute_region_health_check_generated_test.go new file mode 100644 index 0000000000..688d25706c --- /dev/null +++ b/google-beta/resource_compute_region_health_check_generated_test.go @@ -0,0 +1,438 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccComputeRegionHealthCheck_regionHealthCheckTcpExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckTcpExample(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckTcpExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "tcp-region-health-check" { + provider = "google-beta" + name = "tcp-region-health-check%{random_suffix}" + + timeout_sec = 1 + check_interval_sec = 1 + + tcp_health_check { + port = "80" + } +} +`, context) +} + +func TestAccComputeRegionHealthCheck_regionHealthCheckTcpFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckTcpFullExample(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckTcpFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "tcp-region-health-check" { + provider = "google-beta" + name = "tcp-region-health-check%{random_suffix}" + description = "Health check via tcp" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + tcp_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + request = "ARE YOU HEALTHY?" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + +func TestAccComputeRegionHealthCheck_regionHealthCheckSslExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckSslExample(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckSslExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "ssl-region-health-check" { + provider = "google-beta" + name = "ssl-region-health-check%{random_suffix}" + + timeout_sec = 1 + check_interval_sec = 1 + + ssl_health_check { + port = "443" + } +} +`, context) +} + +func TestAccComputeRegionHealthCheck_regionHealthCheckSslFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckSslFullExample(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckSslFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "ssl-region-health-check" { + provider = "google-beta" + name = "ssl-region-health-check%{random_suffix}" + description = "Health check via ssl" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + ssl_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + request = "ARE YOU HEALTHY?" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + +func TestAccComputeRegionHealthCheck_regionHealthCheckHttpExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckHttpExample(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckHttpExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "http-region-health-check" { + provider = "google-beta" + name = "http-region-health-check%{random_suffix}" + + timeout_sec = 1 + check_interval_sec = 1 + + http_health_check { + port = "80" + } +} +`, context) +} + +func TestAccComputeRegionHealthCheck_regionHealthCheckHttpFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckHttpFullExample(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckHttpFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "http-region-health-check" { + provider = "google-beta" + name = "http-region-health-check%{random_suffix}" + description = "Health check via http" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + http_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + +func TestAccComputeRegionHealthCheck_regionHealthCheckHttpsExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckHttpsExample(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckHttpsExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "https-region-health-check" { + provider = "google-beta" + name = "https-region-health-check%{random_suffix}" + + timeout_sec = 1 + check_interval_sec = 1 + + https_health_check { + port = "443" + } +} +`, context) +} + +func TestAccComputeRegionHealthCheck_regionHealthCheckHttpsFullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckHttpsFullExample(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckHttpsFullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "https-region-health-check" { + provider = "google-beta" + name = "https-region-health-check%{random_suffix}" + description = "Health check via https" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + https_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + +func TestAccComputeRegionHealthCheck_regionHealthCheckHttp2Example(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckHttp2Example(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckHttp2Example(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "http2-region-health-check" { + provider = "google-beta" + name = "http2-region-health-check%{random_suffix}" + + timeout_sec = 1 + check_interval_sec = 1 + + http2_health_check { + port = "443" + } +} +`, context) +} + +func TestAccComputeRegionHealthCheck_regionHealthCheckHttp2FullExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(10), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_regionHealthCheckHttp2FullExample(context), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_regionHealthCheckHttp2FullExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_region_health_check" "http2-region-health-check" { + provider = "google-beta" + name = "http2-region-health-check%{random_suffix}" + description = "Health check via http2" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + http2_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +`, context) +} + +func testAccCheckComputeRegionHealthCheckDestroy(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_region_health_check" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := testAccProvider.Meta().(*Config) + + url, err := replaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/healthChecks/{{name}}") + if err != nil { + return err + } + + _, err = sendRequest(config, "GET", "", url, nil) + if err == nil { + return fmt.Errorf("ComputeRegionHealthCheck still exists at %s", url) + } + } + + return nil +} diff --git a/google-beta/resource_compute_region_health_check_test.go b/google-beta/resource_compute_region_health_check_test.go new file mode 100644 index 0000000000..03e8388a0e --- /dev/null +++ b/google-beta/resource_compute_region_health_check_test.go @@ -0,0 +1,339 @@ +package google + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccComputeRegionHealthCheck_tcp_update(t *testing.T) { + t.Parallel() + + hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_tcp(hckName), + }, + { + ResourceName: "google_compute_region_health_check.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeRegionHealthCheck_tcp_update(hckName), + }, + { + ResourceName: "google_compute_region_health_check.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeRegionHealthCheck_ssl_port_spec(t *testing.T) { + t.Parallel() + + hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_ssl_fixed_port(hckName), + }, + { + ResourceName: "google_compute_region_health_check.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeRegionHealthCheck_http_port_spec(t *testing.T) { + t.Parallel() + + hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_http_port_spec(hckName), + ExpectError: regexp.MustCompile("Error in http_health_check: Must specify port_name when using USE_NAMED_PORT as port_specification."), + }, + { + Config: testAccComputeRegionHealthCheck_http_named_port(hckName), + }, + { + ResourceName: "google_compute_region_health_check.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeRegionHealthCheck_https_serving_port(t *testing.T) { + t.Parallel() + + hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_https_serving_port(hckName), + }, + { + ResourceName: "google_compute_region_health_check.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeRegionHealthCheck_typeTransition(t *testing.T) { + t.Parallel() + + hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_https(hckName), + }, + { + Config: testAccComputeRegionHealthCheck_http(hckName), + }, + { + Config: testAccComputeRegionHealthCheck_ssl(hckName), + }, + { + Config: testAccComputeRegionHealthCheck_tcp(hckName), + }, + { + Config: testAccComputeRegionHealthCheck_http2(hckName), + }, + { + Config: testAccComputeRegionHealthCheck_https(hckName), + }, + }, + }) +} + +func TestAccComputeRegionHealthCheck_tcpAndSsl_shouldFail(t *testing.T) { + t.Parallel() + + hckName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeRegionHealthCheckDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionHealthCheck_tcpAndSsl_shouldFail(hckName), + ExpectError: regexp.MustCompile("conflicts with tcp_health_check"), + }, + }, + }) +} + +func testAccComputeRegionHealthCheck_tcp(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + tcp_health_check { + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_tcp_update(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource updated for Terraform acceptance testing" + healthy_threshold = 10 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 10 + tcp_health_check { + port = "8080" + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_ssl(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + ssl_health_check { + port = "443" + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_ssl_fixed_port(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + ssl_health_check { + port = "443" + port_specification = "USE_FIXED_PORT" + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_http(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + http_health_check { + port = "80" + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_http_port_spec(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + http_health_check { + port_specification = "USE_NAMED_PORT" + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_http_named_port(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + http_health_check { + port_name = "http" + port_specification = "USE_NAMED_PORT" + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_https(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + https_health_check { + port = "443" + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_https_serving_port(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + https_health_check { + port_specification = "USE_SERVING_PORT" + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_http2(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + http2_health_check { + port = "443" + } +} +`, hckName) +} + +func testAccComputeRegionHealthCheck_tcpAndSsl_shouldFail(hckName string) string { + return fmt.Sprintf(` +resource "google_compute_region_health_check" "foobar" { + check_interval_sec = 3 + description = "Resource created for Terraform acceptance testing" + healthy_threshold = 3 + name = "health-test-%s" + timeout_sec = 2 + unhealthy_threshold = 3 + + tcp_health_check { + } + ssl_health_check { + } +} +`, hckName) +} diff --git a/google-beta/resource_compute_reservation.go b/google-beta/resource_compute_reservation.go deleted file mode 100644 index 16118f75ad..0000000000 --- a/google-beta/resource_compute_reservation.go +++ /dev/null @@ -1,705 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** -// -// ---------------------------------------------------------------------------- -// -// This file is automatically generated by Magic Modules and manual -// changes will be clobbered when the file is regenerated. -// -// Please read more about how to change this file in -// .github/CONTRIBUTING.md. -// -// ---------------------------------------------------------------------------- - -package google - -import ( - "fmt" - "log" - "reflect" - "strconv" - "time" - - "github.com/hashicorp/terraform/helper/schema" - "github.com/hashicorp/terraform/helper/validation" - "google.golang.org/api/compute/v1" -) - -func resourceComputeReservation() *schema.Resource { - return &schema.Resource{ - Create: resourceComputeReservationCreate, - Read: resourceComputeReservationRead, - Delete: resourceComputeReservationDelete, - - Importer: &schema.ResourceImporter{ - State: resourceComputeReservationImport, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(4 * time.Minute), - Delete: schema.DefaultTimeout(4 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "specific_reservation": { - Type: schema.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "count": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - }, - "instance_properties": { - Type: schema.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "machine_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "guest_accelerators": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "accelerator_count": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - }, - "accelerator_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - }, - }, - }, - "local_ssds": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "disk_size_gb": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - }, - "interface": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"SCSI", "NVME", ""}, false), - Default: "SCSI", - }, - }, - }, - }, - "min_cpu_platform": { - Type: schema.TypeString, - Computed: true, - Optional: true, - ForceNew: true, - }, - }, - }, - }, - "in_use_count": { - Type: schema.TypeInt, - Computed: true, - }, - }, - }, - }, - "zone": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - DiffSuppressFunc: compareSelfLinkOrResourceName, - }, - "description": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - "specific_reservation_required": { - Type: schema.TypeBool, - Optional: true, - ForceNew: true, - Default: false, - }, - "commitment": { - Type: schema.TypeString, - Computed: true, - }, - "creation_timestamp": { - Type: schema.TypeString, - Computed: true, - }, - "status": { - Type: schema.TypeString, - Computed: true, - }, - "project": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - }, - "self_link": { - Type: schema.TypeString, - Computed: true, - }, - }, - } -} - -func resourceComputeReservationCreate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - - obj := make(map[string]interface{}) - descriptionProp, err := expandComputeReservationDescription(d.Get("description"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { - obj["description"] = descriptionProp - } - nameProp, err := expandComputeReservationName(d.Get("name"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { - obj["name"] = nameProp - } - specificReservationRequiredProp, err := expandComputeReservationSpecificReservationRequired(d.Get("specific_reservation_required"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("specific_reservation_required"); !isEmptyValue(reflect.ValueOf(specificReservationRequiredProp)) && (ok || !reflect.DeepEqual(v, specificReservationRequiredProp)) { - obj["specificReservationRequired"] = specificReservationRequiredProp - } - specificReservationProp, err := expandComputeReservationSpecificReservation(d.Get("specific_reservation"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("specific_reservation"); !isEmptyValue(reflect.ValueOf(specificReservationProp)) && (ok || !reflect.DeepEqual(v, specificReservationProp)) { - obj["specificReservation"] = specificReservationProp - } - zoneProp, err := expandComputeReservationZone(d.Get("zone"), d, config) - if err != nil { - return err - } else if v, ok := d.GetOkExists("zone"); !isEmptyValue(reflect.ValueOf(zoneProp)) && (ok || !reflect.DeepEqual(v, zoneProp)) { - obj["zone"] = zoneProp - } - - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/reservations") - if err != nil { - return err - } - - log.Printf("[DEBUG] Creating new Reservation: %#v", obj) - project, err := getProject(d, config) - if err != nil { - return err - } - res, err := sendRequestWithTimeout(config, "POST", project, url, obj, d.Timeout(schema.TimeoutCreate)) - if err != nil { - return fmt.Errorf("Error creating Reservation: %s", err) - } - - // Store the ID now - id, err := replaceVars(d, config, "{{name}}") - if err != nil { - return fmt.Errorf("Error constructing id: %s", err) - } - d.SetId(id) - - op := &compute.Operation{} - err = Convert(res, op) - if err != nil { - return err - } - - waitErr := computeOperationWaitTime( - config.clientCompute, op, project, "Creating Reservation", - int(d.Timeout(schema.TimeoutCreate).Minutes())) - - if waitErr != nil { - // The resource didn't actually create - d.SetId("") - return fmt.Errorf("Error waiting to create Reservation: %s", waitErr) - } - - log.Printf("[DEBUG] Finished creating Reservation %q: %#v", d.Id(), res) - - return resourceComputeReservationRead(d, meta) -} - -func resourceComputeReservationRead(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/reservations/{{name}}") - if err != nil { - return err - } - - project, err := getProject(d, config) - if err != nil { - return err - } - res, err := sendRequest(config, "GET", project, url, nil) - if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("ComputeReservation %q", d.Id())) - } - - if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - - if err := d.Set("creation_timestamp", flattenComputeReservationCreationTimestamp(res["creationTimestamp"], d)); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - if err := d.Set("description", flattenComputeReservationDescription(res["description"], d)); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - if err := d.Set("name", flattenComputeReservationName(res["name"], d)); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - if err := d.Set("commitment", flattenComputeReservationCommitment(res["commitment"], d)); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - if err := d.Set("specific_reservation_required", flattenComputeReservationSpecificReservationRequired(res["specificReservationRequired"], d)); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - if err := d.Set("status", flattenComputeReservationStatus(res["status"], d)); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - if err := d.Set("specific_reservation", flattenComputeReservationSpecificReservation(res["specificReservation"], d)); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - if err := d.Set("zone", flattenComputeReservationZone(res["zone"], d)); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { - return fmt.Errorf("Error reading Reservation: %s", err) - } - - return nil -} - -func resourceComputeReservationDelete(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - - project, err := getProject(d, config) - if err != nil { - return err - } - - url, err := replaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/reservations/{{name}}") - if err != nil { - return err - } - - var obj map[string]interface{} - log.Printf("[DEBUG] Deleting Reservation %q", d.Id()) - - res, err := sendRequestWithTimeout(config, "DELETE", project, url, obj, d.Timeout(schema.TimeoutDelete)) - if err != nil { - return handleNotFoundError(err, d, "Reservation") - } - - op := &compute.Operation{} - err = Convert(res, op) - if err != nil { - return err - } - - err = computeOperationWaitTime( - config.clientCompute, op, project, "Deleting Reservation", - int(d.Timeout(schema.TimeoutDelete).Minutes())) - - if err != nil { - return err - } - - log.Printf("[DEBUG] Finished deleting Reservation %q: %#v", d.Id(), res) - return nil -} - -func resourceComputeReservationImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - config := meta.(*Config) - if err := parseImportId([]string{ - "projects/(?P[^/]+)/zones/(?P[^/]+)/reservations/(?P[^/]+)", - "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", - "(?P[^/]+)/(?P[^/]+)", - "(?P[^/]+)", - }, d, config); err != nil { - return nil, err - } - - // Replace import id for the resource id - id, err := replaceVars(d, config, "{{name}}") - if err != nil { - return nil, fmt.Errorf("Error constructing id: %s", err) - } - d.SetId(id) - - return []*schema.ResourceData{d}, nil -} - -func flattenComputeReservationCreationTimestamp(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationDescription(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationName(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationCommitment(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationSpecificReservationRequired(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationStatus(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationSpecificReservation(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["count"] = - flattenComputeReservationSpecificReservationCount(original["count"], d) - transformed["in_use_count"] = - flattenComputeReservationSpecificReservationInUseCount(original["inUseCount"], d) - transformed["instance_properties"] = - flattenComputeReservationSpecificReservationInstanceProperties(original["instanceProperties"], d) - return []interface{}{transformed} -} -func flattenComputeReservationSpecificReservationCount(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. - } - return v -} - -func flattenComputeReservationSpecificReservationInUseCount(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. - } - return v -} - -func flattenComputeReservationSpecificReservationInstanceProperties(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - if len(original) == 0 { - return nil - } - transformed := make(map[string]interface{}) - transformed["machine_type"] = - flattenComputeReservationSpecificReservationInstancePropertiesMachineType(original["machineType"], d) - transformed["min_cpu_platform"] = - flattenComputeReservationSpecificReservationInstancePropertiesMinCpuPlatform(original["minCpuPlatform"], d) - transformed["guest_accelerators"] = - flattenComputeReservationSpecificReservationInstancePropertiesGuestAccelerators(original["guestAccelerators"], d) - transformed["local_ssds"] = - flattenComputeReservationSpecificReservationInstancePropertiesLocalSsds(original["localSsds"], d) - return []interface{}{transformed} -} -func flattenComputeReservationSpecificReservationInstancePropertiesMachineType(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationSpecificReservationInstancePropertiesMinCpuPlatform(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationSpecificReservationInstancePropertiesGuestAccelerators(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } - l := v.([]interface{}) - transformed := make([]interface{}, 0, len(l)) - for _, raw := range l { - original := raw.(map[string]interface{}) - if len(original) < 1 { - // Do not include empty json objects coming back from the api - continue - } - transformed = append(transformed, map[string]interface{}{ - "accelerator_type": flattenComputeReservationSpecificReservationInstancePropertiesGuestAcceleratorsAcceleratorType(original["acceleratorType"], d), - "accelerator_count": flattenComputeReservationSpecificReservationInstancePropertiesGuestAcceleratorsAcceleratorCount(original["acceleratorCount"], d), - }) - } - return transformed -} -func flattenComputeReservationSpecificReservationInstancePropertiesGuestAcceleratorsAcceleratorType(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationSpecificReservationInstancePropertiesGuestAcceleratorsAcceleratorCount(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. - } - return v -} - -func flattenComputeReservationSpecificReservationInstancePropertiesLocalSsds(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } - l := v.([]interface{}) - transformed := make([]interface{}, 0, len(l)) - for _, raw := range l { - original := raw.(map[string]interface{}) - if len(original) < 1 { - // Do not include empty json objects coming back from the api - continue - } - transformed = append(transformed, map[string]interface{}{ - "interface": flattenComputeReservationSpecificReservationInstancePropertiesLocalSsdsInterface(original["interface"], d), - "disk_size_gb": flattenComputeReservationSpecificReservationInstancePropertiesLocalSsdsDiskSizeGb(original["diskSizeGb"], d), - }) - } - return transformed -} -func flattenComputeReservationSpecificReservationInstancePropertiesLocalSsdsInterface(v interface{}, d *schema.ResourceData) interface{} { - return v -} - -func flattenComputeReservationSpecificReservationInstancePropertiesLocalSsdsDiskSizeGb(v interface{}, d *schema.ResourceData) interface{} { - // Handles the string fixed64 format - if strVal, ok := v.(string); ok { - if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { - return intVal - } // let terraform core handle it if we can't convert the string to an int. - } - return v -} - -func flattenComputeReservationZone(v interface{}, d *schema.ResourceData) interface{} { - if v == nil { - return v - } - return ConvertSelfLinkToV1(v.(string)) -} - -func expandComputeReservationDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationSpecificReservationRequired(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationSpecificReservation(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedCount, err := expandComputeReservationSpecificReservationCount(original["count"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedCount); val.IsValid() && !isEmptyValue(val) { - transformed["count"] = transformedCount - } - - transformedInUseCount, err := expandComputeReservationSpecificReservationInUseCount(original["in_use_count"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedInUseCount); val.IsValid() && !isEmptyValue(val) { - transformed["inUseCount"] = transformedInUseCount - } - - transformedInstanceProperties, err := expandComputeReservationSpecificReservationInstanceProperties(original["instance_properties"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedInstanceProperties); val.IsValid() && !isEmptyValue(val) { - transformed["instanceProperties"] = transformedInstanceProperties - } - - return transformed, nil -} - -func expandComputeReservationSpecificReservationCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationSpecificReservationInUseCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationSpecificReservationInstanceProperties(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedMachineType, err := expandComputeReservationSpecificReservationInstancePropertiesMachineType(original["machine_type"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedMachineType); val.IsValid() && !isEmptyValue(val) { - transformed["machineType"] = transformedMachineType - } - - transformedMinCpuPlatform, err := expandComputeReservationSpecificReservationInstancePropertiesMinCpuPlatform(original["min_cpu_platform"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedMinCpuPlatform); val.IsValid() && !isEmptyValue(val) { - transformed["minCpuPlatform"] = transformedMinCpuPlatform - } - - transformedGuestAccelerators, err := expandComputeReservationSpecificReservationInstancePropertiesGuestAccelerators(original["guest_accelerators"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedGuestAccelerators); val.IsValid() && !isEmptyValue(val) { - transformed["guestAccelerators"] = transformedGuestAccelerators - } - - transformedLocalSsds, err := expandComputeReservationSpecificReservationInstancePropertiesLocalSsds(original["local_ssds"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedLocalSsds); val.IsValid() && !isEmptyValue(val) { - transformed["localSsds"] = transformedLocalSsds - } - - return transformed, nil -} - -func expandComputeReservationSpecificReservationInstancePropertiesMachineType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationSpecificReservationInstancePropertiesMinCpuPlatform(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationSpecificReservationInstancePropertiesGuestAccelerators(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedAcceleratorType, err := expandComputeReservationSpecificReservationInstancePropertiesGuestAcceleratorsAcceleratorType(original["accelerator_type"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedAcceleratorType); val.IsValid() && !isEmptyValue(val) { - transformed["acceleratorType"] = transformedAcceleratorType - } - - transformedAcceleratorCount, err := expandComputeReservationSpecificReservationInstancePropertiesGuestAcceleratorsAcceleratorCount(original["accelerator_count"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedAcceleratorCount); val.IsValid() && !isEmptyValue(val) { - transformed["acceleratorCount"] = transformedAcceleratorCount - } - - req = append(req, transformed) - } - return req, nil -} - -func expandComputeReservationSpecificReservationInstancePropertiesGuestAcceleratorsAcceleratorType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationSpecificReservationInstancePropertiesGuestAcceleratorsAcceleratorCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationSpecificReservationInstancePropertiesLocalSsds(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedInterface, err := expandComputeReservationSpecificReservationInstancePropertiesLocalSsdsInterface(original["interface"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedInterface); val.IsValid() && !isEmptyValue(val) { - transformed["interface"] = transformedInterface - } - - transformedDiskSizeGb, err := expandComputeReservationSpecificReservationInstancePropertiesLocalSsdsDiskSizeGb(original["disk_size_gb"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedDiskSizeGb); val.IsValid() && !isEmptyValue(val) { - transformed["diskSizeGb"] = transformedDiskSizeGb - } - - req = append(req, transformed) - } - return req, nil -} - -func expandComputeReservationSpecificReservationInstancePropertiesLocalSsdsInterface(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationSpecificReservationInstancePropertiesLocalSsdsDiskSizeGb(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - return v, nil -} - -func expandComputeReservationZone(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { - f, err := parseGlobalFieldValue("zones", v.(string), "project", d, config, true) - if err != nil { - return nil, fmt.Errorf("Invalid value for zone: %s", err) - } - return f.RelativeLink(), nil -} diff --git a/google-beta/resource_compute_reservation_generated_test.go b/google-beta/resource_compute_reservation_generated_test.go deleted file mode 100644 index 10fcb6f692..0000000000 --- a/google-beta/resource_compute_reservation_generated_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// ---------------------------------------------------------------------------- -// -// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** -// -// ---------------------------------------------------------------------------- -// -// This file is automatically generated by Magic Modules and manual -// changes will be clobbered when the file is regenerated. -// -// Please read more about how to change this file in -// .github/CONTRIBUTING.md. -// -// ---------------------------------------------------------------------------- - -package google - -import ( - "fmt" - "strings" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" -) - -func TestAccComputeReservation_reservationBasicExample(t *testing.T) { - t.Parallel() - - context := map[string]interface{}{ - "random_suffix": acctest.RandString(10), - } - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeReservationDestroy, - Steps: []resource.TestStep{ - { - Config: testAccComputeReservation_reservationBasicExample(context), - }, - { - ResourceName: "google_compute_reservation.gce_reservation", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccComputeReservation_reservationBasicExample(context map[string]interface{}) string { - return Nprintf(` -resource "google_compute_reservation" "gce_reservation" { - name = "gce-reservation%{random_suffix}" - zone = "us-central1-a" - - specific_reservation { - count = 1 - instance_properties { - min_cpu_platform = "Intel Cascade Lake" - machine_type = "n2-standard-2" - } - } -} -`, context) -} - -func testAccCheckComputeReservationDestroy(s *terraform.State) error { - for name, rs := range s.RootModule().Resources { - if rs.Type != "google_compute_reservation" { - continue - } - if strings.HasPrefix(name, "data.") { - continue - } - - config := testAccProvider.Meta().(*Config) - - url, err := replaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/reservations/{{name}}") - if err != nil { - return err - } - - _, err = sendRequest(config, "GET", "", url, nil) - if err == nil { - return fmt.Errorf("ComputeReservation still exists at %s", url) - } - } - - return nil -} diff --git a/website/docs/r/compute_health_check.html.markdown b/website/docs/r/compute_health_check.html.markdown index 724acf8c80..d4f1290b14 100644 --- a/website/docs/r/compute_health_check.html.markdown +++ b/website/docs/r/compute_health_check.html.markdown @@ -41,16 +41,16 @@ To get more information about HealthCheck, see: * [Official Documentation](https://cloud.google.com/load-balancing/docs/health-checks) -## Example Usage - Health Check Basic +## Example Usage - Health Check Tcp ```hcl -resource "google_compute_health_check" "internal-health-check" { - name = "internal-service-health-check" +resource "google_compute_health_check" "tcp-health-check" { + name = "tcp-health-check" timeout_sec = 1 check_interval_sec = 1 @@ -60,6 +60,224 @@ resource "google_compute_health_check" "internal-health-check" { } } ``` + +## Example Usage - Health Check Tcp Full + + +```hcl +resource "google_compute_health_check" "tcp-health-check" { + name = "tcp-health-check" + description = "Health check via tcp" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + tcp_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + request = "ARE YOU HEALTHY?" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` + +## Example Usage - Health Check Ssl + + +```hcl +resource "google_compute_health_check" "ssl-health-check" { + name = "ssl-health-check" + + timeout_sec = 1 + check_interval_sec = 1 + + ssl_health_check { + port = "443" + } +} +``` + +## Example Usage - Health Check Ssl Full + + +```hcl +resource "google_compute_health_check" "ssl-health-check" { + name = "ssl-health-check" + description = "Health check via ssl" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + ssl_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + request = "ARE YOU HEALTHY?" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` + +## Example Usage - Health Check Http + + +```hcl +resource "google_compute_health_check" "http-health-check" { + name = "http-health-check" + + timeout_sec = 1 + check_interval_sec = 1 + + http_health_check { + port = 80 + } +} +``` + +## Example Usage - Health Check Http Full + + +```hcl +resource "google_compute_health_check" "http-health-check" { + name = "http-health-check" + description = "Health check via http" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + http_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` + +## Example Usage - Health Check Https + + +```hcl +resource "google_compute_health_check" "https-health-check" { + name = "https-health-check" + + timeout_sec = 1 + check_interval_sec = 1 + + https_health_check { + port = "443" + } +} +``` + +## Example Usage - Health Check Https Full + + +```hcl +resource "google_compute_health_check" "https-health-check" { + name = "https-health-check" + description = "Health check via https" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + https_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` + +## Example Usage - Health Check Http2 + + +```hcl +resource "google_compute_health_check" "http2-health-check" { + name = "http2-health-check" + + timeout_sec = 1 + check_interval_sec = 1 + + http2_health_check { + port = "443" + } +} +``` + +## Example Usage - Health Check Http2 Full + + +```hcl +resource "google_compute_health_check" "http2-health-check" { + name = "http2-health-check" + description = "Health check via http2" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + http2_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` ## Argument Reference @@ -122,6 +340,10 @@ The following arguments are supported: (Optional) A nested object resource Structure is documented below. +* `http2_health_check` - + (Optional) + A nested object resource Structure is documented below. + * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. @@ -306,6 +528,53 @@ The `ssl_health_check` block supports: If not specified, SSL health check follows behavior specified in `port` and `portName` fields. +The `http2_health_check` block supports: + +* `host` - + (Optional) + The value of the host header in the HTTP2 health check request. + If left empty (default value), the public IP on behalf of which this health + check is performed will be used. + +* `request_path` - + (Optional) + The request path of the HTTP2 health check request. + The default value is /. + +* `response` - + (Optional) + The bytes to match against the beginning of the response data. If left empty + (the default value), any response will indicate health. The response data + can only be ASCII. + +* `port` - + (Optional) + The TCP port number for the HTTP2 health check request. + The default value is 443. + +* `port_name` - + (Optional) + Port name as defined in InstanceGroup#NamedPort#name. If both port and + port_name are defined, port takes precedence. + +* `proxy_header` - + (Optional) + Specifies the type of proxy header to append before sending data to the + backend, either NONE or PROXY_V1. The default is NONE. + +* `port_specification` - + (Optional) + Specifies how port is selected for health checking, can be one of the + following values: + * `USE_FIXED_PORT`: The port number in `port` is used for health checking. + * `USE_NAMED_PORT`: The `portName` is used for health checking. + * `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each + network endpoint is used for health checking. For other backends, the + port or named port specified in the Backend Service is used for health + checking. + If not specified, HTTP2 health check follows behavior specified in `port` and + `portName` fields. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: diff --git a/website/docs/r/compute_region_health_check.html.markdown b/website/docs/r/compute_region_health_check.html.markdown new file mode 100644 index 0000000000..33da2c34f7 --- /dev/null +++ b/website/docs/r/compute_region_health_check.html.markdown @@ -0,0 +1,633 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- +layout: "google" +page_title: "Google: google_compute_region_health_check" +sidebar_current: "docs-google-compute-region-health-check" +description: |- + Health Checks determine whether instances are responsive and able to do work. +--- + +# google\_compute\_region\_health\_check + +Health Checks determine whether instances are responsive and able to do work. +They are an important part of a comprehensive load balancing configuration, +as they enable monitoring instances behind load balancers. + +Health Checks poll instances at a specified interval. Instances that +do not respond successfully to some number of probes in a row are marked +as unhealthy. No new connections are sent to unhealthy instances, +though existing connections will continue. The health check will +continue to poll unhealthy instances. If an instance later responds +successfully to some number of consecutive probes, it is marked +healthy again and can receive new connections. + +~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](https://terraform.io/docs/providers/google/provider_versions.html) for more details on beta resources. + +To get more information about RegionHealthCheck, see: + +* [API documentation](https://cloud.google.com/compute/docs/reference/rest/beta/regionHealthChecks) +* How-to Guides + * [Official Documentation](https://cloud.google.com/load-balancing/docs/health-checks) + + +## Example Usage - Region Health Check Tcp + + +```hcl +resource "google_compute_region_health_check" "tcp-region-health-check" { + provider = "google-beta" + name = "tcp-region-health-check" + + timeout_sec = 1 + check_interval_sec = 1 + + tcp_health_check { + port = "80" + } +} +``` + +## Example Usage - Region Health Check Tcp Full + + +```hcl +resource "google_compute_region_health_check" "tcp-region-health-check" { + provider = "google-beta" + name = "tcp-region-health-check" + description = "Health check via tcp" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + tcp_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + request = "ARE YOU HEALTHY?" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` + +## Example Usage - Region Health Check Ssl + + +```hcl +resource "google_compute_region_health_check" "ssl-region-health-check" { + provider = "google-beta" + name = "ssl-region-health-check" + + timeout_sec = 1 + check_interval_sec = 1 + + ssl_health_check { + port = "443" + } +} +``` + +## Example Usage - Region Health Check Ssl Full + + +```hcl +resource "google_compute_region_health_check" "ssl-region-health-check" { + provider = "google-beta" + name = "ssl-region-health-check" + description = "Health check via ssl" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + ssl_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + request = "ARE YOU HEALTHY?" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` + +## Example Usage - Region Health Check Http + + +```hcl +resource "google_compute_region_health_check" "http-region-health-check" { + provider = "google-beta" + name = "http-region-health-check" + + timeout_sec = 1 + check_interval_sec = 1 + + http_health_check { + port = "80" + } +} +``` + +## Example Usage - Region Health Check Http Full + + +```hcl +resource "google_compute_region_health_check" "http-region-health-check" { + provider = "google-beta" + name = "http-region-health-check" + description = "Health check via http" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + http_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` + +## Example Usage - Region Health Check Https + + +```hcl +resource "google_compute_region_health_check" "https-region-health-check" { + provider = "google-beta" + name = "https-region-health-check" + + timeout_sec = 1 + check_interval_sec = 1 + + https_health_check { + port = "443" + } +} +``` + +## Example Usage - Region Health Check Https Full + + +```hcl +resource "google_compute_region_health_check" "https-region-health-check" { + provider = "google-beta" + name = "https-region-health-check" + description = "Health check via https" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + https_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` + +## Example Usage - Region Health Check Http2 + + +```hcl +resource "google_compute_region_health_check" "http2-region-health-check" { + provider = "google-beta" + name = "http2-region-health-check" + + timeout_sec = 1 + check_interval_sec = 1 + + http2_health_check { + port = "443" + } +} +``` + +## Example Usage - Region Health Check Http2 Full + + +```hcl +resource "google_compute_region_health_check" "http2-region-health-check" { + provider = "google-beta" + name = "http2-region-health-check" + description = "Health check via http2" + + timeout_sec = 1 + check_interval_sec = 1 + healthy_threshold = 4 + unhealthy_threshold = 5 + + http2_health_check { + port_name = "health-check-port" + port_specification = "USE_NAMED_PORT" + host = "1.2.3.4" + request_path = "/mypath" + proxy_header = "NONE" + response = "I AM HEALTHY" + } +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `name` - + (Required) + Name of the resource. Provided by the client when the resource is + created. The name must be 1-63 characters long, and comply with + RFC1035. Specifically, the name must be 1-63 characters long and + match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means + the first character must be a lowercase letter, and all following + characters must be a dash, lowercase letter, or digit, except the + last character, which cannot be a dash. + + +- - - + + +* `check_interval_sec` - + (Optional) + How often (in seconds) to send a health check. The default value is 5 + seconds. + +* `description` - + (Optional) + An optional description of this resource. Provide this property when + you create the resource. + +* `healthy_threshold` - + (Optional) + A so-far unhealthy instance will be marked healthy after this many + consecutive successes. The default value is 2. + +* `unhealthy_threshold` - + (Optional) + A so-far healthy instance will be marked unhealthy after this many + consecutive failures. The default value is 2. + +* `timeout_sec` - + (Optional) + How long (in seconds) to wait before claiming failure. + The default value is 5 seconds. It is invalid for timeoutSec to have + greater value than checkIntervalSec. + +* `http_health_check` - + (Optional) + A nested object resource Structure is documented below. + +* `https_health_check` - + (Optional) + A nested object resource Structure is documented below. + +* `tcp_health_check` - + (Optional) + A nested object resource Structure is documented below. + +* `ssl_health_check` - + (Optional) + A nested object resource Structure is documented below. + +* `http2_health_check` - + (Optional) + A nested object resource Structure is documented below. + +* `region` - + (Optional) + The Region in which the created health check should reside. + If it is not provided, the provider region is used. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +The `http_health_check` block supports: + +* `host` - + (Optional) + The value of the host header in the HTTP health check request. + If left empty (default value), the public IP on behalf of which this health + check is performed will be used. + +* `request_path` - + (Optional) + The request path of the HTTP health check request. + The default value is /. + +* `response` - + (Optional) + The bytes to match against the beginning of the response data. If left empty + (the default value), any response will indicate health. The response data + can only be ASCII. + +* `port` - + (Optional) + The TCP port number for the HTTP health check request. + The default value is 80. + +* `port_name` - + (Optional) + Port name as defined in InstanceGroup#NamedPort#name. If both port and + port_name are defined, port takes precedence. + +* `proxy_header` - + (Optional) + Specifies the type of proxy header to append before sending data to the + backend, either NONE or PROXY_V1. The default is NONE. + +* `port_specification` - + (Optional) + Specifies how port is selected for health checking, can be one of the + following values: + * `USE_FIXED_PORT`: The port number in `port` is used for health checking. + * `USE_NAMED_PORT`: The `portName` is used for health checking. + * `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each + network endpoint is used for health checking. For other backends, the + port or named port specified in the Backend Service is used for health + checking. + If not specified, HTTP health check follows behavior specified in `port` and + `portName` fields. + +The `https_health_check` block supports: + +* `host` - + (Optional) + The value of the host header in the HTTPS health check request. + If left empty (default value), the public IP on behalf of which this health + check is performed will be used. + +* `request_path` - + (Optional) + The request path of the HTTPS health check request. + The default value is /. + +* `response` - + (Optional) + The bytes to match against the beginning of the response data. If left empty + (the default value), any response will indicate health. The response data + can only be ASCII. + +* `port` - + (Optional) + The TCP port number for the HTTPS health check request. + The default value is 443. + +* `port_name` - + (Optional) + Port name as defined in InstanceGroup#NamedPort#name. If both port and + port_name are defined, port takes precedence. + +* `proxy_header` - + (Optional) + Specifies the type of proxy header to append before sending data to the + backend, either NONE or PROXY_V1. The default is NONE. + +* `port_specification` - + (Optional) + Specifies how port is selected for health checking, can be one of the + following values: + * `USE_FIXED_PORT`: The port number in `port` is used for health checking. + * `USE_NAMED_PORT`: The `portName` is used for health checking. + * `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each + network endpoint is used for health checking. For other backends, the + port or named port specified in the Backend Service is used for health + checking. + If not specified, HTTPS health check follows behavior specified in `port` and + `portName` fields. + +The `tcp_health_check` block supports: + +* `request` - + (Optional) + The application data to send once the TCP connection has been + established (default value is empty). If both request and response are + empty, the connection establishment alone will indicate health. The request + data can only be ASCII. + +* `response` - + (Optional) + The bytes to match against the beginning of the response data. If left empty + (the default value), any response will indicate health. The response data + can only be ASCII. + +* `port` - + (Optional) + The TCP port number for the TCP health check request. + The default value is 80. + +* `port_name` - + (Optional) + Port name as defined in InstanceGroup#NamedPort#name. If both port and + port_name are defined, port takes precedence. + +* `proxy_header` - + (Optional) + Specifies the type of proxy header to append before sending data to the + backend, either NONE or PROXY_V1. The default is NONE. + +* `port_specification` - + (Optional) + Specifies how port is selected for health checking, can be one of the + following values: + * `USE_FIXED_PORT`: The port number in `port` is used for health checking. + * `USE_NAMED_PORT`: The `portName` is used for health checking. + * `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each + network endpoint is used for health checking. For other backends, the + port or named port specified in the Backend Service is used for health + checking. + If not specified, TCP health check follows behavior specified in `port` and + `portName` fields. + +The `ssl_health_check` block supports: + +* `request` - + (Optional) + The application data to send once the SSL connection has been + established (default value is empty). If both request and response are + empty, the connection establishment alone will indicate health. The request + data can only be ASCII. + +* `response` - + (Optional) + The bytes to match against the beginning of the response data. If left empty + (the default value), any response will indicate health. The response data + can only be ASCII. + +* `port` - + (Optional) + The TCP port number for the SSL health check request. + The default value is 443. + +* `port_name` - + (Optional) + Port name as defined in InstanceGroup#NamedPort#name. If both port and + port_name are defined, port takes precedence. + +* `proxy_header` - + (Optional) + Specifies the type of proxy header to append before sending data to the + backend, either NONE or PROXY_V1. The default is NONE. + +* `port_specification` - + (Optional) + Specifies how port is selected for health checking, can be one of the + following values: + * `USE_FIXED_PORT`: The port number in `port` is used for health checking. + * `USE_NAMED_PORT`: The `portName` is used for health checking. + * `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each + network endpoint is used for health checking. For other backends, the + port or named port specified in the Backend Service is used for health + checking. + If not specified, SSL health check follows behavior specified in `port` and + `portName` fields. + +The `http2_health_check` block supports: + +* `host` - + (Optional) + The value of the host header in the HTTP2 health check request. + If left empty (default value), the public IP on behalf of which this health + check is performed will be used. + +* `request_path` - + (Optional) + The request path of the HTTP2 health check request. + The default value is /. + +* `response` - + (Optional) + The bytes to match against the beginning of the response data. If left empty + (the default value), any response will indicate health. The response data + can only be ASCII. + +* `port` - + (Optional) + The TCP port number for the HTTP2 health check request. + The default value is 443. + +* `port_name` - + (Optional) + Port name as defined in InstanceGroup#NamedPort#name. If both port and + port_name are defined, port takes precedence. + +* `proxy_header` - + (Optional) + Specifies the type of proxy header to append before sending data to the + backend, either NONE or PROXY_V1. The default is NONE. + +* `port_specification` - + (Optional) + Specifies how port is selected for health checking, can be one of the + following values: + * `USE_FIXED_PORT`: The port number in `port` is used for health checking. + * `USE_NAMED_PORT`: The `portName` is used for health checking. + * `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each + network endpoint is used for health checking. For other backends, the + port or named port specified in the Backend Service is used for health + checking. + If not specified, HTTP2 health check follows behavior specified in `port` and + `portName` fields. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + + +* `creation_timestamp` - + Creation timestamp in RFC3339 text format. + +* `type` - + The type of the health check. One of HTTP, HTTP2, HTTPS, TCP, or SSL. +* `self_link` - The URI of the created resource. + + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 4 minutes. +- `update` - Default is 4 minutes. +- `delete` - Default is 4 minutes. + +## Import + +RegionHealthCheck can be imported using any of these accepted formats: + +``` +$ terraform import -provider=google-beta google_compute_region_health_check.default projects/{{project}}/regions/{{region}}/healthChecks/{{name}} +$ terraform import -provider=google-beta google_compute_region_health_check.default {{project}}/{{region}}/{{name}} +$ terraform import -provider=google-beta google_compute_region_health_check.default {{region}}/{{name}} +$ terraform import -provider=google-beta google_compute_region_health_check.default {{name}} +``` + +-> If you're importing a resource with beta features, make sure to include `-provider=google-beta` +as an argument so that Terraform uses the correct provider to import your resource. + +## User Project Overrides + +This resource supports [User Project Overrides](https://www.terraform.io/docs/providers/google/provider_reference.html#user_project_override). diff --git a/website/docs/r/compute_reservation.html.markdown b/website/docs/r/compute_reservation.html.markdown deleted file mode 100644 index 49d0354037..0000000000 --- a/website/docs/r/compute_reservation.html.markdown +++ /dev/null @@ -1,207 +0,0 @@ ---- -# ---------------------------------------------------------------------------- -# -# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** -# -# ---------------------------------------------------------------------------- -# -# This file is automatically generated by Magic Modules and manual -# changes will be clobbered when the file is regenerated. -# -# Please read more about how to change this file in -# .github/CONTRIBUTING.md. -# -# ---------------------------------------------------------------------------- -layout: "google" -page_title: "Google: google_compute_reservation" -sidebar_current: "docs-google-compute-reservation" -description: |- - Represents a reservation resource. ---- - -# google\_compute\_reservation - -Represents a reservation resource. A reservation ensures that capacity is -held in a specific zone even if the reserved VMs are not running. - -Reservations apply only to Compute Engine, Cloud Dataproc, and Google -Kubernetes Engine VM usage.Reservations do not apply to `f1-micro` or -`g1-small` machine types, preemptible VMs, sole tenant nodes, or other -services not listed above -like Cloud SQL and Dataflow. - - -To get more information about Reservation, see: - -* [API documentation](https://cloud.google.com/compute/docs/reference/rest/v1/reservations) -* How-to Guides - * [Reserving zonal resources](https://cloud.google.com/compute/docs/instances/reserving-zonal-resources) - - -## Example Usage - Reservation Basic - - -```hcl -resource "google_compute_reservation" "gce_reservation" { - name = "gce-reservation" - zone = "us-central1-a" - - specific_reservation { - count = 1 - instance_properties { - min_cpu_platform = "Intel Cascade Lake" - machine_type = "n2-standard-2" - } - } -} -``` - -## Argument Reference - -The following arguments are supported: - - -* `name` - - (Required) - Name of the resource. Provided by the client when the resource is - created. The name must be 1-63 characters long, and comply with - RFC1035. Specifically, the name must be 1-63 characters long and match - the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the - first character must be a lowercase letter, and all following - characters must be a dash, lowercase letter, or digit, except the last - character, which cannot be a dash. - -* `specific_reservation` - - (Required) - Reservation for instances with specific machine shapes. Structure is documented below. - -* `zone` - - (Required) - The zone where the reservation is made. - - -The `specific_reservation` block supports: - -* `count` - - (Required) - The number of resources that are allocated. - -* `in_use_count` - - How many instances are in use. - -* `instance_properties` - - (Required) - The instance properties for the reservation. Structure is documented below. - - -The `instance_properties` block supports: - -* `machine_type` - - (Required) - The name of the machine type to reserve. - -* `min_cpu_platform` - - (Optional) - The minimum CPU platform for the reservation. For example, - `"Intel Skylake"`. See - the CPU platform availability reference](https://cloud.google.com/compute/docs/instances/specify-min-cpu-platform#availablezones) - for information on available CPU platforms. - -* `guest_accelerators` - - (Optional) - Guest accelerator type and count. Structure is documented below. - -* `local_ssds` - - (Optional) - The amount of local ssd to reserve with each instance. This - reserves disks of type `local-ssd`. Structure is documented below. - - -The `guest_accelerators` block supports: - -* `accelerator_type` - - (Required) - The full or partial URL of the accelerator type to - attach to this instance. For example: - `projects/my-project/zones/us-central1-c/acceleratorTypes/nvidia-tesla-p100` - If you are creating an instance template, specify only the accelerator name. - -* `accelerator_count` - - (Required) - The number of the guest accelerator cards exposed to - this instance. - -The `local_ssds` block supports: - -* `interface` - - (Optional) - The disk interface to use for attaching this disk, one - of `SCSI` or `NVME`. The default is `SCSI`. - -* `disk_size_gb` - - (Required) - The size of the disk in base-2 GB. - -- - - - - -* `description` - - (Optional) - An optional description of this resource. - -* `specific_reservation_required` - - (Optional) - When set to true, only VMs that target this reservation by name can - consume this reservation. Otherwise, it can be consumed by VMs with - affinity for any reservation. Defaults to false. - -* `project` - (Optional) The ID of the project in which the resource belongs. - If it is not provided, the provider project is used. - - -## Attributes Reference - -In addition to the arguments listed above, the following computed attributes are exported: - - -* `creation_timestamp` - - Creation timestamp in RFC3339 text format. - -* `commitment` - - Full or partial URL to a parent commitment. This field displays for - reservations that are tied to a commitment. - -* `status` - - The status of the reservation. -* `self_link` - The URI of the created resource. - - -## Timeouts - -This resource provides the following -[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: - -- `create` - Default is 4 minutes. -- `delete` - Default is 4 minutes. - -## Import - -Reservation can be imported using any of these accepted formats: - -``` -$ terraform import google_compute_reservation.default projects/{{project}}/zones/{{zone}}/reservations/{{name}} -$ terraform import google_compute_reservation.default {{project}}/{{zone}}/{{name}} -$ terraform import google_compute_reservation.default {{zone}}/{{name}} -$ terraform import google_compute_reservation.default {{name}} -``` - --> If you're importing a resource with beta features, make sure to include `-provider=google-beta` -as an argument so that Terraform uses the correct provider to import your resource. - -## User Project Overrides - -This resource supports [User Project Overrides](https://www.terraform.io/docs/providers/google/provider_reference.html#user_project_override).