diff --git a/nomad/client_endpoint.go b/nomad/client_endpoint.go index c055b02af..2cc11bd69 100644 --- a/nomad/client_endpoint.go +++ b/nomad/client_endpoint.go @@ -105,3 +105,37 @@ func (c *Client) UpdateStatus(args *structs.UpdateStatusRequest, reply *structs. reply.Index = index return nil } + +// GetNode is used to request information about a specific ndoe +func (c *Client) GetNode(args *structs.NodeSpecificRequest, + reply *structs.SingleNodeResponse) error { + if done, err := c.srv.forward("Client.GetNode", args, args, reply); done { + return err + } + defer metrics.MeasureSince([]string{"nomad", "client", "get_node"}, time.Now()) + + // Verify the arguments + if args.NodeID == "" { + return fmt.Errorf("missing node ID") + } + + // Look for the node + state := c.srv.fsm.State() + out, err := state.GetNodeByID(args.NodeID) + if err != nil { + return err + } + + // Setup the output + if out != nil { + reply.Node = out + reply.Index = out.ModifyIndex + } else { + // TODO: Fix table index + reply.Index = 0 + } + + // Set the query response + c.srv.setQueryMeta(&reply.QueryMeta) + return nil +} diff --git a/nomad/rpc.go b/nomad/rpc.go index 8b8db9f4a..373a6a634 100644 --- a/nomad/rpc.go +++ b/nomad/rpc.go @@ -254,3 +254,14 @@ func (s *Server) raftApply(t structs.MessageType, msg interface{}) (interface{}, return future.Response(), future.Index(), nil } + +// setQueryMeta is used to populate the QueryMeta data for an RPC call +func (s *Server) setQueryMeta(m *structs.QueryMeta) { + if s.IsLeader() { + m.LastContact = 0 + m.KnownLeader = true + } else { + m.LastContact = time.Now().Sub(s.raft.LastContact()) + m.KnownLeader = (s.raft.Leader() != "") + } +} diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 9dd414d38..cf911650b 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -130,12 +130,24 @@ type UpdateStatusRequest struct { WriteRequest } +// NodeSpecificRequest is used when we just need to specify a target node +type NodeSpecificRequest struct { + NodeID string + WriteRequest +} + // GenericResponse is used to respond to a request where no // specific response information is needed. type GenericResponse struct { WriteMeta } +// SingleNodeResponse is used to return a single node +type SingleNodeResponse struct { + Node *Node + QueryMeta +} + const ( NodeStatusInit = "initializing" NodeStatusReady = "ready"