Add ability to associate healthcheck to a backend (#13539)

This commit is contained in:
Jon Oden 2017-04-20 16:24:19 -04:00 committed by Paul Stack
parent fa5cc7eb34
commit d5207e17ed
2 changed files with 143 additions and 133 deletions

View File

@ -107,6 +107,80 @@ func resourceServiceV1() *schema.Resource {
Description: "The default hostname for the version", 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": { "backend": {
Type: schema.TypeSet, Type: schema.TypeSet,
Optional: true, Optional: true,
@ -154,6 +228,12 @@ func resourceServiceV1() *schema.Resource {
Default: 15000, Default: 15000,
Description: "How long to wait for the first bytes in milliseconds", 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": { "max_conn": {
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, 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": { "s3logging": {
Type: schema.TypeSet, Type: schema.TypeSet,
Optional: true, 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 // find difference in backends
if d.HasChange("backend") { if d.HasChange("backend") {
ob, nb := d.GetChange("backend") ob, nb := d.GetChange("backend")
@ -1081,6 +1146,7 @@ func resourceServiceV1Update(d *schema.ResourceData, meta interface{}) error {
MaxConn: uint(df["max_conn"].(int)), MaxConn: uint(df["max_conn"].(int)),
Weight: uint(df["weight"].(int)), Weight: uint(df["weight"].(int)),
RequestCondition: df["request_condition"].(string), RequestCondition: df["request_condition"].(string),
HealthCheck: df["healthcheck"].(string),
} }
log.Printf("[DEBUG] Create Backend Opts: %#v", opts) 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 // find difference in s3logging
if d.HasChange("s3logging") { if d.HasChange("s3logging") {
os, ns := d.GetChange("s3logging") os, ns := d.GetChange("s3logging")
@ -2051,6 +2058,7 @@ func flattenBackends(backendList []*gofastly.Backend) []map[string]interface{} {
"ssl_sni_hostname": b.SSLSNIHostname, "ssl_sni_hostname": b.SSLSNIHostname,
"weight": int(b.Weight), "weight": int(b.Weight),
"request_condition": b.RequestCondition, "request_condition": b.RequestCondition,
"healthcheck": b.HealthCheck,
} }
bl = append(bl, nb) bl = append(bl, nb)

View File

@ -71,6 +71,7 @@ func TestResourceFastlyFlattenBackend(t *testing.T) {
FirstByteTimeout: uint(15000), FirstByteTimeout: uint(15000),
MaxConn: uint(200), MaxConn: uint(200),
RequestCondition: "", RequestCondition: "",
HealthCheck: "",
SSLCheckCert: true, SSLCheckCert: true,
SSLHostname: "", SSLHostname: "",
SSLCertHostname: "", SSLCertHostname: "",
@ -91,6 +92,7 @@ func TestResourceFastlyFlattenBackend(t *testing.T) {
"first_byte_timeout": 15000, "first_byte_timeout": 15000,
"max_conn": 200, "max_conn": 200,
"request_condition": "", "request_condition": "",
"healthcheck": "",
"ssl_check_cert": true, "ssl_check_cert": true,
"ssl_hostname": "", "ssl_hostname": "",
"ssl_cert_hostname": "", "ssl_cert_hostname": "",