Browse Source

Adding CheckServiceNodes to get health info with service nodes

pull/19/head
Armon Dadgar 11 years ago
parent
commit
0de92171ee
  1. 59
      consul/state_store.go
  2. 61
      consul/state_store_test.go
  3. 7
      consul/structs/structs.go

59
consul/state_store.go

@ -484,6 +484,65 @@ func parseHealthChecks(res []interface{}, err error) structs.HealthChecks {
return results
}
// CheckServiceNodes returns the nodes associated with a given service, along
// with any associated check
func (s *StateStore) CheckServiceNodes(service string) structs.CheckServiceNodes {
tx, err := s.tables.StartTxn(true)
if err != nil {
panic(fmt.Errorf("Failed to start txn: %v", err))
}
defer tx.Abort()
res, err := s.serviceTable.Get("service", service)
return s.parseCheckServiceNodes(tx, res, err)
}
// CheckServiceNodes returns the nodes associated with a given service, along
// with any associated checks
func (s *StateStore) CheckServiceTagNodes(service, tag string) structs.CheckServiceNodes {
tx, err := s.tables.StartTxn(true)
if err != nil {
panic(fmt.Errorf("Failed to start txn: %v", err))
}
defer tx.Abort()
res, err := s.serviceTable.Get("service", service, tag)
return s.parseCheckServiceNodes(tx, res, err)
}
// parseCheckServiceNodes parses results CheckServiceNodes and CheckServiceTagNodes
func (s *StateStore) parseCheckServiceNodes(tx *MDBTxn, res []interface{}, err error) structs.CheckServiceNodes {
if err != nil {
panic(fmt.Errorf("Failed to get node services: %v", err))
}
nodes := make(structs.CheckServiceNodes, len(res))
for i, r := range res {
srv := r.(*structs.ServiceNode)
// Get the node
nodeRes, err := s.nodeTable.GetTxn(tx, "id", srv.Node)
if err != nil || len(nodeRes) != 1 {
panic(fmt.Errorf("Failed to join node: %v", err))
}
// Get any associated checks
checks := parseHealthChecks(s.checkTable.GetTxn(tx, "node", srv.Node, srv.ServiceID))
// Setup the node
nodes[i].Node = *nodeRes[0].(*structs.Node)
nodes[i].Service = structs.NodeService{
ID: srv.ServiceID,
Service: srv.ServiceName,
Tag: srv.ServiceTag,
Port: srv.ServicePort,
}
nodes[i].Checks = checks
}
return nodes
}
// Snapshot is used to create a point in time snapshot
func (s *StateStore) Snapshot() (*StateSnapshot, error) {
// Begin a new txn on all tables

61
consul/state_store_test.go

@ -692,3 +692,64 @@ func TestDeleteNodeCheck(t *testing.T) {
t.Fatalf("bad: %v", checks[0])
}
}
func TestCheckServiceNodes(t *testing.T) {
store, err := NewStateStore()
if err != nil {
t.Fatalf("err: %v", err)
}
defer store.Close()
if err := store.EnsureNode(structs.Node{"foo", "127.0.0.1"}); err != nil {
t.Fatalf("err: %v", err)
}
if err := store.EnsureService("foo", "db1", "db", "master", 8000); err != nil {
t.Fatalf("err: %v")
}
check := &structs.HealthCheck{
Node: "foo",
CheckID: "db",
Name: "Can connect",
Status: structs.HealthPassing,
ServiceID: "db1",
}
if err := store.EnsureCheck(check); err != nil {
t.Fatalf("err: %v")
}
nodes := store.CheckServiceNodes("db")
if len(nodes) != 1 {
t.Fatalf("Bad: %v", nodes)
}
if nodes[0].Node.Node != "foo" {
t.Fatalf("Bad: %v", nodes[0])
}
if nodes[0].Service.ID != "db1" {
t.Fatalf("Bad: %v", nodes[0])
}
if len(nodes[0].Checks) != 1 {
t.Fatalf("Bad: %v", nodes[0])
}
if nodes[0].Checks[0].Status != structs.HealthPassing {
t.Fatalf("Bad: %v", nodes[0])
}
nodes = store.CheckServiceTagNodes("db", "master")
if len(nodes) != 1 {
t.Fatalf("Bad: %v", nodes)
}
if nodes[0].Node.Node != "foo" {
t.Fatalf("Bad: %v", nodes[0])
}
if nodes[0].Service.ID != "db1" {
t.Fatalf("Bad: %v", nodes[0])
}
if len(nodes[0].Checks) != 1 {
t.Fatalf("Bad: %v", nodes[0])
}
if nodes[0].Checks[0].Status != structs.HealthPassing {
t.Fatalf("Bad: %v", nodes[0])
}
}

7
consul/structs/structs.go

@ -113,13 +113,14 @@ type HealthCheck struct {
}
type HealthChecks []*HealthCheck
// NodeServiceStatus is used to provide the node, it's service
// CheckServiceNode is used to provide the node, it's service
// definition, as well as a HealthCheck that is associated
type NodeServiceStatus struct {
type CheckServiceNode struct {
Node Node
Service NodeService
Check HealthCheck
Checks HealthChecks
}
type CheckServiceNodes []CheckServiceNode
// Decode is used to decode a MsgPack encoded object
func Decode(buf []byte, out interface{}) error {

Loading…
Cancel
Save