agent: Support server-side filtering of passing checks. Fixes #57.
This commit is contained in:
parent
cb33d73ffe
commit
d6b7dd5b62
|
@ -106,5 +106,26 @@ func (s *HTTPServer) HealthServiceNodes(resp http.ResponseWriter, req *http.Requ
|
||||||
if err := s.agent.RPC("Health.ServiceNodes", &args, &out); err != nil {
|
if err := s.agent.RPC("Health.ServiceNodes", &args, &out); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter to only passing if specified
|
||||||
|
if _, ok := params["passing"]; ok {
|
||||||
|
out.Nodes = filterNonPassing(out.Nodes)
|
||||||
|
}
|
||||||
return out.Nodes, nil
|
return out.Nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filterNonPassing is used to filter out any nodes that have check that are not passing
|
||||||
|
func filterNonPassing(nodes structs.CheckServiceNodes) structs.CheckServiceNodes {
|
||||||
|
n := len(nodes)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
node := nodes[i]
|
||||||
|
for _, check := range node.Checks {
|
||||||
|
if check.Status != structs.HealthPassing {
|
||||||
|
nodes[i], nodes[n-1] = nodes[n-1], structs.CheckServiceNode{}
|
||||||
|
n--
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes[:n]
|
||||||
|
}
|
||||||
|
|
|
@ -138,3 +138,48 @@ func TestHealthServiceNodes(t *testing.T) {
|
||||||
t.Fatalf("bad: %v", obj)
|
t.Fatalf("bad: %v", obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHealthServiceNodes_PassingFilter(t *testing.T) {
|
||||||
|
dir, srv := makeHTTPServer(t)
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
defer srv.Shutdown()
|
||||||
|
defer srv.agent.Shutdown()
|
||||||
|
|
||||||
|
// Wait for a leader
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
// Create a failing service check
|
||||||
|
args := &structs.RegisterRequest{
|
||||||
|
Datacenter: "dc1",
|
||||||
|
Node: srv.agent.config.NodeName,
|
||||||
|
Address: "127.0.0.1",
|
||||||
|
Check: &structs.HealthCheck{
|
||||||
|
Node: srv.agent.config.NodeName,
|
||||||
|
Name: "consul check",
|
||||||
|
ServiceID: "consul",
|
||||||
|
Status: structs.HealthCritical,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var out struct{}
|
||||||
|
if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", "/v1/health/service/consul?passing", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := httptest.NewRecorder()
|
||||||
|
obj, err := srv.HealthServiceNodes(resp, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
assertIndex(t, resp)
|
||||||
|
|
||||||
|
// Should be 0 health check for consul
|
||||||
|
nodes := obj.(structs.CheckServiceNodes)
|
||||||
|
if len(nodes) != 0 {
|
||||||
|
t.Fatalf("bad: %v", obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -681,6 +681,10 @@ endpoint automatically returns the status of the associated health check,
|
||||||
as well as any system level health checks. This allows a client to avoid
|
as well as any system level health checks. This allows a client to avoid
|
||||||
sending traffic to nodes failing health tests, or who are reporting warnings.
|
sending traffic to nodes failing health tests, or who are reporting warnings.
|
||||||
|
|
||||||
|
Providing the "?passing" query parameter will filter results to only nodes
|
||||||
|
with all checks in the passing state. This can be used to avoid some filtering
|
||||||
|
logic on the client side. (Added in Consul 0.2)
|
||||||
|
|
||||||
Users can also built in support for dynamic load balancing and other features
|
Users can also built in support for dynamic load balancing and other features
|
||||||
by incorporating the use of health checks.
|
by incorporating the use of health checks.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue