From a126240a128991d1c001f6d31d43fa3e3e40b373 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Fri, 4 Mar 2016 15:18:25 -0800 Subject: [PATCH] Adds support for new PUT API for checks. --- api/agent.go | 59 ++++++++++++++++++++++++++++++++++++++---- api/agent_test.go | 65 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 108 insertions(+), 16 deletions(-) diff --git a/api/agent.go b/api/agent.go index 183ae6efd..54d30cac0 100644 --- a/api/agent.go +++ b/api/agent.go @@ -200,21 +200,26 @@ func (a *Agent) ServiceDeregister(serviceID string) error { // PassTTL is used to set a TTL check to the passing state func (a *Agent) PassTTL(checkID, note string) error { - return a.UpdateTTL(checkID, note, "pass") + return a.updateTTL(checkID, note, "pass") } // WarnTTL is used to set a TTL check to the warning state func (a *Agent) WarnTTL(checkID, note string) error { - return a.UpdateTTL(checkID, note, "warn") + return a.updateTTL(checkID, note, "warn") } // FailTTL is used to set a TTL check to the failing state func (a *Agent) FailTTL(checkID, note string) error { - return a.UpdateTTL(checkID, note, "fail") + return a.updateTTL(checkID, note, "fail") } -// UpdateTTL is used to update the TTL of a check -func (a *Agent) UpdateTTL(checkID, note, status string) error { +// updateTTL is used to update the TTL of a check. This is the internal +// method that uses the old API that's present in Consul versions prior +// to 0.6.4. Since Consul didn't have an analogous "update" API before it +// seemed ok to break this (former) UpdateTTL in favor of the new UpdateTTL +// below, but keep the old Pass/Warn/Fail methods using the old API under the +// hood. +func (a *Agent) updateTTL(checkID, note, status string) error { switch status { case "pass": case "warn": @@ -233,6 +238,50 @@ func (a *Agent) UpdateTTL(checkID, note, status string) error { return nil } +// checkUpdate is the payload for a PUT for a check update. +type checkUpdate struct { + // Status us one of the structs.Health* states, "passing", "warning", or + // "critical". + Status string + + // Output is the information to post to the UI for operators as the + // output of the process that decided to hit the TTL check. This is + // different from the note field that's associated with the check + // itself. + Output string +} + +// UpdateTTL is used to update the TTL of a check. This uses the newer API +// that was introduced in Consul 0.6.4 and later. We translate the old status +// strings for compatibility (though a newer version of Consul will still be +// required to use this API). +func (a *Agent) UpdateTTL(checkID, output, status string) error { + switch status { + case "pass", "passing": + status = "passing" + case "warn", "warning": + status = "warning" + case "fail", "critical": + status = "critical" + default: + return fmt.Errorf("Invalid status: %s", status) + } + + endpoint := fmt.Sprintf("/v1/agent/check/update/%s", checkID) + r := a.c.newRequest("PUT", endpoint) + r.obj = &checkUpdate{ + Status: status, + Output: output, + } + + _, resp, err := requireOK(a.c.doRequest(r)) + if err != nil { + return err + } + resp.Body.Close() + return nil +} + // CheckRegister is used to register a new check with // the local agent func (a *Agent) CheckRegister(check *AgentCheckRegistration) error { diff --git a/api/agent_test.go b/api/agent_test.go index c5e1854dd..a61245149 100644 --- a/api/agent_test.go +++ b/api/agent_test.go @@ -300,24 +300,67 @@ func TestAgent_SetTTLStatus(t *testing.T) { t.Fatalf("err: %v", err) } - if err := agent.WarnTTL("service:foo", "test"); err != nil { - t.Fatalf("err: %v", err) + verify := func(status, output string) { + checks, err := agent.Checks() + if err != nil { + t.Fatalf("err: %v", err) + } + chk, ok := checks["service:foo"] + if !ok { + t.Fatalf("missing check: %v", checks) + } + if chk.Status != status { + t.Fatalf("Bad: %#v", chk) + } + if chk.Output != output { + t.Fatalf("Bad: %#v", chk) + } } - checks, err := agent.Checks() - if err != nil { + if err := agent.WarnTTL("service:foo", "foo"); err != nil { t.Fatalf("err: %v", err) } - chk, ok := checks["service:foo"] - if !ok { - t.Fatalf("missing check: %v", checks) + verify("warning", "foo") + + if err := agent.PassTTL("service:foo", "bar"); err != nil { + t.Fatalf("err: %v", err) } - if chk.Status != "warning" { - t.Fatalf("Bad: %#v", chk) + verify("passing", "bar") + + if err := agent.FailTTL("service:foo", "baz"); err != nil { + t.Fatalf("err: %v", err) } - if chk.Output != "test" { - t.Fatalf("Bad: %#v", chk) + verify("critical", "baz") + + if err := agent.UpdateTTL("service:foo", "foo", "warn"); err != nil { + t.Fatalf("err: %v", err) } + verify("warning", "foo") + + if err := agent.UpdateTTL("service:foo", "bar", "pass"); err != nil { + t.Fatalf("err: %v", err) + } + verify("passing", "bar") + + if err := agent.UpdateTTL("service:foo", "baz", "fail"); err != nil { + t.Fatalf("err: %v", err) + } + verify("critical", "baz") + + if err := agent.UpdateTTL("service:foo", "foo", "warning"); err != nil { + t.Fatalf("err: %v", err) + } + verify("warning", "foo") + + if err := agent.UpdateTTL("service:foo", "bar", "passing"); err != nil { + t.Fatalf("err: %v", err) + } + verify("passing", "bar") + + if err := agent.UpdateTTL("service:foo", "baz", "critical"); err != nil { + t.Fatalf("err: %v", err) + } + verify("critical", "baz") if err := agent.ServiceDeregister("foo"); err != nil { t.Fatalf("err: %v", err)