From d5207e17ed8b3cfad288ea858e3613883ad9b403 Mon Sep 17 00:00:00 2001 From: Jon Oden Date: Thu, 20 Apr 2017 16:24:19 -0400 Subject: [PATCH] Add ability to associate healthcheck to a backend (#13539) --- .../fastly/resource_fastly_service_v1.go | 274 +++++++++--------- .../fastly/resource_fastly_service_v1_test.go | 2 + 2 files changed, 143 insertions(+), 133 deletions(-) diff --git a/builtin/providers/fastly/resource_fastly_service_v1.go b/builtin/providers/fastly/resource_fastly_service_v1.go index e9408902f..196948141 100644 --- a/builtin/providers/fastly/resource_fastly_service_v1.go +++ b/builtin/providers/fastly/resource_fastly_service_v1.go @@ -107,6 +107,80 @@ func resourceServiceV1() *schema.Resource { Description: "The default hostname for the version", }, + "healthcheck": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + // required fields + "name": { + Type: schema.TypeString, + Required: true, + Description: "A name to refer to this healthcheck", + }, + "host": { + Type: schema.TypeString, + Required: true, + Description: "Which host to check", + }, + "path": { + Type: schema.TypeString, + Required: true, + Description: "The path to check", + }, + // optional fields + "check_interval": { + Type: schema.TypeInt, + Optional: true, + Default: 5000, + Description: "How often to run the healthcheck in milliseconds", + }, + "expected_response": { + Type: schema.TypeInt, + Optional: true, + Default: 200, + Description: "The status code expected from the host", + }, + "http_version": { + Type: schema.TypeString, + Optional: true, + Default: "1.1", + Description: "Whether to use version 1.0 or 1.1 HTTP", + }, + "initial": { + Type: schema.TypeInt, + Optional: true, + Default: 2, + Description: "When loading a config, the initial number of probes to be seen as OK", + }, + "method": { + Type: schema.TypeString, + Optional: true, + Default: "HEAD", + Description: "Which HTTP method to use", + }, + "threshold": { + Type: schema.TypeInt, + Optional: true, + Default: 3, + Description: "How many healthchecks must succeed to be considered healthy", + }, + "timeout": { + Type: schema.TypeInt, + Optional: true, + Default: 500, + Description: "Timeout in milliseconds", + }, + "window": { + Type: schema.TypeInt, + Optional: true, + Default: 5, + Description: "The number of most recent healthcheck queries to keep for this healthcheck", + }, + }, + }, + }, + "backend": { Type: schema.TypeSet, Optional: true, @@ -154,6 +228,12 @@ func resourceServiceV1() *schema.Resource { Default: 15000, Description: "How long to wait for the first bytes in milliseconds", }, + "healthcheck": { + Type: schema.TypeString, + Optional: true, + Default: "", + Description: "The healthcheck name that should be used for this Backend", + }, "max_conn": { Type: schema.TypeInt, Optional: true, @@ -403,80 +483,6 @@ func resourceServiceV1() *schema.Resource { }, }, - "healthcheck": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - // required fields - "name": { - Type: schema.TypeString, - Required: true, - Description: "A name to refer to this healthcheck", - }, - "host": { - Type: schema.TypeString, - Required: true, - Description: "Which host to check", - }, - "path": { - Type: schema.TypeString, - Required: true, - Description: "The path to check", - }, - // optional fields - "check_interval": { - Type: schema.TypeInt, - Optional: true, - Default: 5000, - Description: "How often to run the healthcheck in milliseconds", - }, - "expected_response": { - Type: schema.TypeInt, - Optional: true, - Default: 200, - Description: "The status code expected from the host", - }, - "http_version": { - Type: schema.TypeString, - Optional: true, - Default: "1.1", - Description: "Whether to use version 1.0 or 1.1 HTTP", - }, - "initial": { - Type: schema.TypeInt, - Optional: true, - Default: 2, - Description: "When loading a config, the initial number of probes to be seen as OK", - }, - "method": { - Type: schema.TypeString, - Optional: true, - Default: "HEAD", - Description: "Which HTTP method to use", - }, - "threshold": { - Type: schema.TypeInt, - Optional: true, - Default: 3, - Description: "How many healthchecks must succeed to be considered healthy", - }, - "timeout": { - Type: schema.TypeInt, - Optional: true, - Default: 500, - Description: "Timeout in milliseconds", - }, - "window": { - Type: schema.TypeInt, - Optional: true, - Default: 5, - Description: "The number of most recent healthcheck queries to keep for this healthcheck", - }, - }, - }, - }, - "s3logging": { Type: schema.TypeSet, Optional: true, @@ -1028,6 +1034,65 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error { } } + // Healthchecks need to be updated BEFORE backends + if d.HasChange("healthcheck") { + oh, nh := d.GetChange("healthcheck") + if oh == nil { + oh = new(schema.Set) + } + if nh == nil { + nh = new(schema.Set) + } + + ohs := oh.(*schema.Set) + nhs := nh.(*schema.Set) + removeHealthCheck := ohs.Difference(nhs).List() + addHealthCheck := nhs.Difference(ohs).List() + + // DELETE old healthcheck configurations + for _, hRaw := range removeHealthCheck { + hf := hRaw.(map[string]interface{}) + opts := gofastly.DeleteHealthCheckInput{ + Service: d.Id(), + Version: latestVersion, + Name: hf["name"].(string), + } + + log.Printf("[DEBUG] Fastly Healthcheck removal opts: %#v", opts) + err := conn.DeleteHealthCheck(&opts) + if err != nil { + return err + } + } + + // POST new/updated Healthcheck + for _, hRaw := range addHealthCheck { + hf := hRaw.(map[string]interface{}) + + opts := gofastly.CreateHealthCheckInput{ + Service: d.Id(), + Version: latestVersion, + Name: hf["name"].(string), + Host: hf["host"].(string), + Path: hf["path"].(string), + CheckInterval: uint(hf["check_interval"].(int)), + ExpectedResponse: uint(hf["expected_response"].(int)), + HTTPVersion: hf["http_version"].(string), + Initial: uint(hf["initial"].(int)), + Method: hf["method"].(string), + Threshold: uint(hf["threshold"].(int)), + Timeout: uint(hf["timeout"].(int)), + Window: uint(hf["window"].(int)), + } + + log.Printf("[DEBUG] Create Healthcheck Opts: %#v", opts) + _, err := conn.CreateHealthCheck(&opts) + if err != nil { + return err + } + } + } + // find difference in backends if d.HasChange("backend") { ob, nb := d.GetChange("backend") @@ -1081,6 +1146,7 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error { MaxConn: uint(df["max_conn"].(int)), Weight: uint(df["weight"].(int)), RequestCondition: df["request_condition"].(string), + HealthCheck: df["healthcheck"].(string), } log.Printf("[DEBUG] Create Backend Opts: %#v", opts) @@ -1210,65 +1276,6 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error { } } - // find difference in Healthcheck - if d.HasChange("healthcheck") { - oh, nh := d.GetChange("healthcheck") - if oh == nil { - oh = new(schema.Set) - } - if nh == nil { - nh = new(schema.Set) - } - - ohs := oh.(*schema.Set) - nhs := nh.(*schema.Set) - removeHealthCheck := ohs.Difference(nhs).List() - addHealthCheck := nhs.Difference(ohs).List() - - // DELETE old healthcheck configurations - for _, hRaw := range removeHealthCheck { - hf := hRaw.(map[string]interface{}) - opts := gofastly.DeleteHealthCheckInput{ - Service: d.Id(), - Version: latestVersion, - Name: hf["name"].(string), - } - - log.Printf("[DEBUG] Fastly Healthcheck removal opts: %#v", opts) - err := conn.DeleteHealthCheck(&opts) - if err != nil { - return err - } - } - - // POST new/updated Healthcheck - for _, hRaw := range addHealthCheck { - hf := hRaw.(map[string]interface{}) - - opts := gofastly.CreateHealthCheckInput{ - Service: d.Id(), - Version: latestVersion, - Name: hf["name"].(string), - Host: hf["host"].(string), - Path: hf["path"].(string), - CheckInterval: uint(hf["check_interval"].(int)), - ExpectedResponse: uint(hf["expected_response"].(int)), - HTTPVersion: hf["http_version"].(string), - Initial: uint(hf["initial"].(int)), - Method: hf["method"].(string), - Threshold: uint(hf["threshold"].(int)), - Timeout: uint(hf["timeout"].(int)), - Window: uint(hf["window"].(int)), - } - - log.Printf("[DEBUG] Create Healthcheck Opts: %#v", opts) - _, err := conn.CreateHealthCheck(&opts) - if err != nil { - return err - } - } - } - // find difference in s3logging if d.HasChange("s3logging") { os, ns := d.GetChange("s3logging") @@ -2051,6 +2058,7 @@ func flattenBackends(backendList []*gofastly.Backend) []map[string]interface{} { "ssl_sni_hostname": b.SSLSNIHostname, "weight": int(b.Weight), "request_condition": b.RequestCondition, + "healthcheck": b.HealthCheck, } bl = append(bl, nb) diff --git a/builtin/providers/fastly/resource_fastly_service_v1_test.go b/builtin/providers/fastly/resource_fastly_service_v1_test.go index 93c03799a..9b6f0defb 100644 --- a/builtin/providers/fastly/resource_fastly_service_v1_test.go +++ b/builtin/providers/fastly/resource_fastly_service_v1_test.go @@ -71,6 +71,7 @@ func TestResourceFastlyFlattenBackend(t *testing.T) { FirstByteTimeout: uint(15000), MaxConn: uint(200), RequestCondition: "", + HealthCheck: "", SSLCheckCert: true, SSLHostname: "", SSLCertHostname: "", @@ -91,6 +92,7 @@ func TestResourceFastlyFlattenBackend(t *testing.T) { "first_byte_timeout": 15000, "max_conn": 200, "request_condition": "", + "healthcheck": "", "ssl_check_cert": true, "ssl_hostname": "", "ssl_cert_hostname": "",