From deebe64de0290f842f712e69f1fedfcfae3a7bb2 Mon Sep 17 00:00:00 2001 From: Ty Larrabee Date: Fri, 31 May 2019 21:04:08 +0000 Subject: [PATCH] Add failover to region_backend_service Signed-off-by: Modular Magician --- ...resource_compute_region_backend_service.go | 130 ++++++++++++++++++ ...rce_compute_region_backend_service_test.go | 7 + ...mpute_region_backend_service.html.markdown | 40 ++++++ 3 files changed, 177 insertions(+) diff --git a/google-beta/resource_compute_region_backend_service.go b/google-beta/resource_compute_region_backend_service.go index 3eed1d11ea..634bd2be91 100644 --- a/google-beta/resource_compute_region_backend_service.go +++ b/google-beta/resource_compute_region_backend_service.go @@ -83,6 +83,27 @@ func resourceComputeRegionBackendService() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "failover_policy": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disable_connection_drain_on_failover": { + Type: schema.TypeBool, + Optional: true, + }, + "drop_traffic_if_unhealthy": { + Type: schema.TypeBool, + Optional: true, + }, + "failover_ratio": { + Type: schema.TypeFloat, + Optional: true, + }, + }, + }, + }, "load_balancing_scheme": { Type: schema.TypeString, Optional: true, @@ -138,6 +159,10 @@ func computeRegionBackendServiceBackendSchema() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "failover": { + Type: schema.TypeBool, + Optional: true, + }, "group": { Type: schema.TypeString, Optional: true, @@ -175,6 +200,12 @@ func resourceComputeRegionBackendServiceCreate(d *schema.ResourceData, meta inte } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { obj["description"] = descriptionProp } + failoverPolicyProp, err := expandComputeRegionBackendServiceFailoverPolicy(d.Get("failover_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("failover_policy"); !isEmptyValue(reflect.ValueOf(failoverPolicyProp)) && (ok || !reflect.DeepEqual(v, failoverPolicyProp)) { + obj["failoverPolicy"] = failoverPolicyProp + } fingerprintProp, err := expandComputeRegionBackendServiceFingerprint(d.Get("fingerprint"), d, config) if err != nil { return err @@ -294,6 +325,9 @@ func resourceComputeRegionBackendServiceRead(d *schema.ResourceData, meta interf if err := d.Set("description", flattenComputeRegionBackendServiceDescription(res["description"], d)); err != nil { return fmt.Errorf("Error reading RegionBackendService: %s", err) } + if err := d.Set("failover_policy", flattenComputeRegionBackendServiceFailoverPolicy(res["failoverPolicy"], d)); err != nil { + return fmt.Errorf("Error reading RegionBackendService: %s", err) + } if err := d.Set("fingerprint", flattenComputeRegionBackendServiceFingerprint(res["fingerprint"], d)); err != nil { return fmt.Errorf("Error reading RegionBackendService: %s", err) } @@ -357,6 +391,12 @@ func resourceComputeRegionBackendServiceUpdate(d *schema.ResourceData, meta inte } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { obj["description"] = descriptionProp } + failoverPolicyProp, err := expandComputeRegionBackendServiceFailoverPolicy(d.Get("failover_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("failover_policy"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, failoverPolicyProp)) { + obj["failoverPolicy"] = failoverPolicyProp + } fingerprintProp, err := expandComputeRegionBackendServiceFingerprint(d.Get("fingerprint"), d, config) if err != nil { return err @@ -512,6 +552,7 @@ func flattenComputeRegionBackendServiceBackend(v interface{}, d *schema.Resource transformed.Add(map[string]interface{}{ "description": flattenComputeRegionBackendServiceBackendDescription(original["description"], d), "group": flattenComputeRegionBackendServiceBackendGroup(original["group"], d), + "failover": flattenComputeRegionBackendServiceBackendFailover(original["failover"], d), }) } return transformed @@ -527,10 +568,43 @@ func flattenComputeRegionBackendServiceBackendGroup(v interface{}, d *schema.Res return ConvertSelfLinkToV1(v.(string)) } +func flattenComputeRegionBackendServiceBackendFailover(v interface{}, d *schema.ResourceData) interface{} { + return v +} + func flattenComputeRegionBackendServiceDescription(v interface{}, d *schema.ResourceData) interface{} { return v } +func flattenComputeRegionBackendServiceFailoverPolicy(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["disable_connection_drain_on_failover"] = + flattenComputeRegionBackendServiceFailoverPolicyDisableConnectionDrainOnFailover(original["disableConnectionDrainOnFailover"], d) + transformed["drop_traffic_if_unhealthy"] = + flattenComputeRegionBackendServiceFailoverPolicyDropTrafficIfUnhealthy(original["dropTrafficIfUnhealthy"], d) + transformed["failover_ratio"] = + flattenComputeRegionBackendServiceFailoverPolicyFailoverRatio(original["failoverRatio"], d) + return []interface{}{transformed} +} +func flattenComputeRegionBackendServiceFailoverPolicyDisableConnectionDrainOnFailover(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionBackendServiceFailoverPolicyDropTrafficIfUnhealthy(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenComputeRegionBackendServiceFailoverPolicyFailoverRatio(v interface{}, d *schema.ResourceData) interface{} { + return v +} + func flattenComputeRegionBackendServiceFingerprint(v interface{}, d *schema.ResourceData) interface{} { return v } @@ -621,6 +695,13 @@ func expandComputeRegionBackendServiceBackend(v interface{}, d TerraformResource transformed["group"] = transformedGroup } + transformedFailover, err := expandComputeRegionBackendServiceBackendFailover(original["failover"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFailover); val.IsValid() && !isEmptyValue(val) { + transformed["failover"] = transformedFailover + } + req = append(req, transformed) } return req, nil @@ -634,10 +715,59 @@ func expandComputeRegionBackendServiceBackendGroup(v interface{}, d TerraformRes return v, nil } +func expandComputeRegionBackendServiceBackendFailover(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeRegionBackendServiceDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } +func expandComputeRegionBackendServiceFailoverPolicy(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{}) + + transformedDisableConnectionDrainOnFailover, err := expandComputeRegionBackendServiceFailoverPolicyDisableConnectionDrainOnFailover(original["disable_connection_drain_on_failover"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDisableConnectionDrainOnFailover); val.IsValid() && !isEmptyValue(val) { + transformed["disableConnectionDrainOnFailover"] = transformedDisableConnectionDrainOnFailover + } + + transformedDropTrafficIfUnhealthy, err := expandComputeRegionBackendServiceFailoverPolicyDropTrafficIfUnhealthy(original["drop_traffic_if_unhealthy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDropTrafficIfUnhealthy); val.IsValid() && !isEmptyValue(val) { + transformed["dropTrafficIfUnhealthy"] = transformedDropTrafficIfUnhealthy + } + + transformedFailoverRatio, err := expandComputeRegionBackendServiceFailoverPolicyFailoverRatio(original["failover_ratio"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFailoverRatio); val.IsValid() && !isEmptyValue(val) { + transformed["failoverRatio"] = transformedFailoverRatio + } + + return transformed, nil +} + +func expandComputeRegionBackendServiceFailoverPolicyDisableConnectionDrainOnFailover(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionBackendServiceFailoverPolicyDropTrafficIfUnhealthy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionBackendServiceFailoverPolicyFailoverRatio(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeRegionBackendServiceFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google-beta/resource_compute_region_backend_service_test.go b/google-beta/resource_compute_region_backend_service_test.go index 8d5f23b41f..cd3d19eee0 100644 --- a/google-beta/resource_compute_region_backend_service_test.go +++ b/google-beta/resource_compute_region_backend_service_test.go @@ -248,6 +248,13 @@ resource "google_compute_region_backend_service" "lipsum" { backend { group = "${google_compute_instance_group_manager.foobar.instance_group}" + failover = true + } + + failover_policy { + disable_connection_drain_on_failover = true + drop_traffic_if_unhealthy = true + failover_ratio = 0.4 } health_checks = ["${google_compute_health_check.default.self_link}"] diff --git a/website/docs/r/compute_region_backend_service.html.markdown b/website/docs/r/compute_region_backend_service.html.markdown index aeece9e83d..5aff494771 100644 --- a/website/docs/r/compute_region_backend_service.html.markdown +++ b/website/docs/r/compute_region_backend_service.html.markdown @@ -96,6 +96,10 @@ The following arguments are supported: (Optional) An optional description of this resource. +* `failover_policy` - + (Optional, [Beta](https://terraform.io/docs/providers/google/provider_versions.html)) + Policy for failovers. Structure is documented below. + * `protocol` - (Optional) The protocol this BackendService uses to communicate with backends. @@ -150,6 +154,42 @@ The `backend` block supports: partial URL. The instance group must be within the same region as the BackendService. +* `failover` - + (Optional, [Beta](https://terraform.io/docs/providers/google/provider_versions.html)) + This field designates whether this is a failover backend. More + than one failover backend can be configured for a given BackendService. + +The `failover_policy` block supports: + +* `disable_connection_drain_on_failover` - + (Optional) + On failover or failback, this field indicates whether connection drain + will be honored. Setting this to true has the following effect: connections + to the old active pool are not drained. Connections to the new active pool + use the timeout of 10 min (currently fixed). Setting to false has the + following effect: both old and new connections will have a drain timeout + of 10 min. + This can be set to true only if the protocol is TCP. + The default is false. + +* `drop_traffic_if_unhealthy` - + (Optional) + This option is used only when no healthy VMs are detected in the primary + and backup instance groups. When set to true, traffic is dropped. When + set to false, new connections are sent across all VMs in the primary group. + The default is false. + +* `failover_ratio` - + (Optional) + The value of the field must be in [0, 1]. If the ratio of the healthy + VMs in the primary backend is at or below this number, traffic arriving + at the load-balanced IP will be directed to the failover backend. + In case where 'failoverRatio' is not set or all the VMs in the backup + backend are unhealthy, the traffic will be directed back to the primary + backend in the "force" mode, where traffic will be spread to the healthy + VMs with the best effort, or to all VMs when no VM is healthy. + This field is only used with l4 load balancing. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: