mirror of https://github.com/status-im/consul.git
Merge branch 'Heuriskein-master'
This commit is contained in:
commit
ef8027ae2a
|
@ -68,6 +68,7 @@ type AgentServiceCheck struct {
|
|||
Timeout string `json:",omitempty"`
|
||||
TTL string `json:",omitempty"`
|
||||
HTTP string `json:",omitempty"`
|
||||
Status string `json:",omitempty"`
|
||||
}
|
||||
type AgentServiceChecks []*AgentServiceCheck
|
||||
|
||||
|
|
|
@ -59,6 +59,50 @@ func TestAgent_Services(t *testing.T) {
|
|||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
services, err := agent.Services()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if _, ok := services["foo"]; !ok {
|
||||
t.Fatalf("missing service: %v", services)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
// Checks should default to critical
|
||||
if chk.Status != "critical" {
|
||||
t.Fatalf("Bad: %#v", chk)
|
||||
}
|
||||
|
||||
if err := agent.ServiceDeregister("foo"); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgent_Services_CheckPassing(t *testing.T) {
|
||||
c, s := makeClient(t)
|
||||
defer s.stop()
|
||||
|
||||
agent := c.Agent()
|
||||
reg := &AgentServiceRegistration{
|
||||
Name: "foo",
|
||||
Tags: []string{"bar", "baz"},
|
||||
Port: 8000,
|
||||
Check: &AgentServiceCheck{
|
||||
TTL: "15s",
|
||||
Status: "passing",
|
||||
},
|
||||
}
|
||||
if err := agent.ServiceRegister(reg); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
services, err := agent.Services()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
|
@ -71,15 +115,38 @@ func TestAgent_Services(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if _, ok := checks["service:foo"]; !ok {
|
||||
chk, ok := checks["service:foo"]
|
||||
if !ok {
|
||||
t.Fatalf("missing check: %v", checks)
|
||||
}
|
||||
|
||||
if chk.Status != "passing" {
|
||||
t.Fatalf("Bad: %#v", chk)
|
||||
}
|
||||
if err := agent.ServiceDeregister("foo"); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgent_Services_CheckBadStatus(t *testing.T) {
|
||||
c, s := makeClient(t)
|
||||
defer s.stop()
|
||||
|
||||
agent := c.Agent()
|
||||
reg := &AgentServiceRegistration{
|
||||
Name: "foo",
|
||||
Tags: []string{"bar", "baz"},
|
||||
Port: 8000,
|
||||
Check: &AgentServiceCheck{
|
||||
TTL: "15s",
|
||||
Status: "fluffy",
|
||||
},
|
||||
}
|
||||
if err := agent.ServiceRegister(reg); err == nil {
|
||||
t.Fatalf("bad status accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgent_ServiceAddress(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, s := makeClient(t)
|
||||
|
@ -231,9 +298,47 @@ func TestAgent_Checks(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if _, ok := checks["foo"]; !ok {
|
||||
chk, ok := checks["foo"]
|
||||
if !ok {
|
||||
t.Fatalf("missing check: %v", checks)
|
||||
}
|
||||
if chk.Status != "critical" {
|
||||
t.Fatalf("check not critical: %v", chk)
|
||||
}
|
||||
|
||||
if err := agent.CheckDeregister("foo"); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgent_CheckStartPassing(t *testing.T) {
|
||||
c, s := makeClient(t)
|
||||
defer s.stop()
|
||||
|
||||
agent := c.Agent()
|
||||
|
||||
reg := &AgentCheckRegistration{
|
||||
Name: "foo",
|
||||
AgentServiceCheck: AgentServiceCheck{
|
||||
Status: "passing",
|
||||
},
|
||||
}
|
||||
reg.TTL = "15s"
|
||||
if err := agent.CheckRegister(reg); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
checks, err := agent.Checks()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
chk, ok := checks["foo"]
|
||||
if !ok {
|
||||
t.Fatalf("missing check: %v", checks)
|
||||
}
|
||||
if chk.Status != "passing" {
|
||||
t.Fatalf("check not passing: %v", chk)
|
||||
}
|
||||
|
||||
if err := agent.CheckDeregister("foo"); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
|
|
|
@ -669,6 +669,9 @@ func (a *Agent) AddService(service *structs.NodeService, chkTypes CheckTypes, pe
|
|||
ServiceID: service.ID,
|
||||
ServiceName: service.Service,
|
||||
}
|
||||
if chkType.Status != "" {
|
||||
check.Status = chkType.Status
|
||||
}
|
||||
if err := a.AddCheck(check, chkType, persist, token); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -86,6 +86,12 @@ func (s *HTTPServer) AgentRegisterCheck(resp http.ResponseWriter, req *http.Requ
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
if args.Status != "" && !structs.ValidStatus(args.Status) {
|
||||
resp.WriteHeader(400)
|
||||
resp.Write([]byte("Bad check status"))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Construct the health check
|
||||
health := args.HealthCheck(s.agent.config.NodeName)
|
||||
|
||||
|
@ -196,6 +202,11 @@ func (s *HTTPServer) AgentRegisterService(resp http.ResponseWriter, req *http.Re
|
|||
// Verify the check type
|
||||
chkTypes := args.CheckTypes()
|
||||
for _, check := range chkTypes {
|
||||
if check.Status != "" && !structs.ValidStatus(check.Status) {
|
||||
resp.WriteHeader(400)
|
||||
resp.Write([]byte("Status for checks must 'passing', 'warning', 'critical', 'unknown'"))
|
||||
return nil, nil
|
||||
}
|
||||
if !check.Valid() {
|
||||
resp.WriteHeader(400)
|
||||
resp.Write([]byte("Must provide TTL or Script and Interval!"))
|
||||
|
|
|
@ -3,14 +3,15 @@ package agent
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/testutil"
|
||||
"github.com/hashicorp/serf/serf"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/hashicorp/consul/testutil"
|
||||
"github.com/hashicorp/serf/serf"
|
||||
)
|
||||
|
||||
func TestHTTPAgentServices(t *testing.T) {
|
||||
|
@ -285,6 +286,84 @@ func TestHTTPAgentRegisterCheck(t *testing.T) {
|
|||
if token := srv.agent.state.CheckToken("test"); token == "" {
|
||||
t.Fatalf("missing token")
|
||||
}
|
||||
|
||||
// By default, checks start in critical state.
|
||||
state := srv.agent.state.Checks()["test"]
|
||||
if state.Status != structs.HealthCritical {
|
||||
t.Fatalf("bad: %v", state)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAgentRegisterCheckPassing(t *testing.T) {
|
||||
dir, srv := makeHTTPServer(t)
|
||||
defer os.RemoveAll(dir)
|
||||
defer srv.Shutdown()
|
||||
defer srv.agent.Shutdown()
|
||||
|
||||
// Register node
|
||||
req, err := http.NewRequest("GET", "/v1/agent/check/register", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
args := &CheckDefinition{
|
||||
Name: "test",
|
||||
CheckType: CheckType{
|
||||
TTL: 15 * time.Second,
|
||||
},
|
||||
Status: structs.HealthPassing,
|
||||
}
|
||||
req.Body = encodeReq(args)
|
||||
|
||||
obj, err := srv.AgentRegisterCheck(nil, req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if obj != nil {
|
||||
t.Fatalf("bad: %v", obj)
|
||||
}
|
||||
|
||||
// Ensure we have a check mapping
|
||||
if _, ok := srv.agent.state.Checks()["test"]; !ok {
|
||||
t.Fatalf("missing test check")
|
||||
}
|
||||
|
||||
if _, ok := srv.agent.checkTTLs["test"]; !ok {
|
||||
t.Fatalf("missing test check ttl")
|
||||
}
|
||||
|
||||
state := srv.agent.state.Checks()["test"]
|
||||
if state.Status != structs.HealthPassing {
|
||||
t.Fatalf("bad: %v", state)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAgentRegisterCheckBadStatus(t *testing.T) {
|
||||
dir, srv := makeHTTPServer(t)
|
||||
defer os.RemoveAll(dir)
|
||||
defer srv.Shutdown()
|
||||
defer srv.agent.Shutdown()
|
||||
|
||||
// Register node
|
||||
req, err := http.NewRequest("GET", "/v1/agent/check/register", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
args := &CheckDefinition{
|
||||
Name: "test",
|
||||
CheckType: CheckType{
|
||||
TTL: 15 * time.Second,
|
||||
},
|
||||
Status: "fluffy",
|
||||
}
|
||||
req.Body = encodeReq(args)
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
if _, err := srv.AgentRegisterCheck(resp, req); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp.Code != 400 {
|
||||
t.Fatalf("accepted bad status")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPAgentDeregisterCheck(t *testing.T) {
|
||||
|
|
|
@ -352,10 +352,53 @@ func TestAgent_AddCheck(t *testing.T) {
|
|||
}
|
||||
|
||||
// Ensure we have a check mapping
|
||||
if _, ok := agent.state.Checks()["mem"]; !ok {
|
||||
sChk, ok := agent.state.Checks()["mem"]
|
||||
if !ok {
|
||||
t.Fatalf("missing mem check")
|
||||
}
|
||||
|
||||
// Ensure our check is in the right state
|
||||
if sChk.Status != structs.HealthCritical {
|
||||
t.Fatalf("check not critical")
|
||||
}
|
||||
|
||||
// Ensure a TTL is setup
|
||||
if _, ok := agent.checkMonitors["mem"]; !ok {
|
||||
t.Fatalf("missing mem monitor")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgent_AddCheck_StartPassing(t *testing.T) {
|
||||
dir, agent := makeAgent(t, nextConfig())
|
||||
defer os.RemoveAll(dir)
|
||||
defer agent.Shutdown()
|
||||
|
||||
health := &structs.HealthCheck{
|
||||
Node: "foo",
|
||||
CheckID: "mem",
|
||||
Name: "memory util",
|
||||
Status: structs.HealthPassing,
|
||||
}
|
||||
chk := &CheckType{
|
||||
Script: "exit 0",
|
||||
Interval: 15 * time.Second,
|
||||
}
|
||||
err := agent.AddCheck(health, chk, false)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
// Ensure we have a check mapping
|
||||
sChk, ok := agent.state.Checks()["mem"]
|
||||
if !ok {
|
||||
t.Fatalf("missing mem check")
|
||||
}
|
||||
|
||||
// Ensure our check is in the right state
|
||||
if sChk.Status != structs.HealthPassing {
|
||||
t.Fatalf("check not passing")
|
||||
}
|
||||
|
||||
// Ensure a TTL is setup
|
||||
if _, ok := agent.checkMonitors["mem"]; !ok {
|
||||
t.Fatalf("missing mem monitor")
|
||||
|
|
|
@ -39,6 +39,8 @@ type CheckType struct {
|
|||
Timeout time.Duration
|
||||
TTL time.Duration
|
||||
|
||||
Status string
|
||||
|
||||
Notes string
|
||||
}
|
||||
type CheckTypes []*CheckType
|
||||
|
|
|
@ -47,6 +47,7 @@ type CheckDefinition struct {
|
|||
Notes string
|
||||
ServiceID string
|
||||
Token string
|
||||
Status string
|
||||
CheckType `mapstructure:",squash"`
|
||||
}
|
||||
|
||||
|
@ -59,6 +60,9 @@ func (c *CheckDefinition) HealthCheck(node string) *structs.HealthCheck {
|
|||
Notes: c.Notes,
|
||||
ServiceID: c.ServiceID,
|
||||
}
|
||||
if c.Status != "" {
|
||||
health.Status = c.Status
|
||||
}
|
||||
if health.CheckID == "" && health.Name != "" {
|
||||
health.CheckID = health.Name
|
||||
}
|
||||
|
|
|
@ -45,6 +45,12 @@ const (
|
|||
HealthCritical = "critical"
|
||||
)
|
||||
|
||||
func ValidStatus(s string) bool {
|
||||
return s == HealthPassing ||
|
||||
s == HealthWarning ||
|
||||
s == HealthCritical
|
||||
}
|
||||
|
||||
const (
|
||||
// Client tokens have rules applied
|
||||
ACLTypeClient = "client"
|
||||
|
|
Loading…
Reference in New Issue