-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
status_endpoint.go
149 lines (129 loc) · 3.89 KB
/
status_endpoint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package nomad
import (
"errors"
"fmt"
"strconv"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/consul/agent/consul/autopilot"
"github.com/hashicorp/nomad/nomad/structs"
)
// Status endpoint is used to check on server status
type Status struct {
srv *Server
logger log.Logger
}
// Version is used to allow clients to determine the capabilities
// of the server
func (s *Status) Version(args *structs.GenericRequest, reply *structs.VersionResponse) error {
if done, err := s.srv.forward("Status.Version", args, args, reply); done {
return err
}
conf := s.srv.config
reply.Build = conf.Build
reply.Versions = map[string]int{
structs.ProtocolVersion: int(conf.ProtocolVersion),
structs.APIMajorVersion: structs.ApiMajorVersion,
structs.APIMinorVersion: structs.ApiMinorVersion,
}
return nil
}
// Ping is used to just check for connectivity
func (s *Status) Ping(args struct{}, reply *struct{}) error {
return nil
}
// Leader is used to get the address of the leader
func (s *Status) Leader(args *structs.GenericRequest, reply *string) error {
if args.Region == "" {
args.Region = s.srv.config.Region
}
if done, err := s.srv.forward("Status.Leader", args, args, reply); done {
return err
}
leader := string(s.srv.raft.Leader())
if leader != "" {
*reply = leader
} else {
*reply = ""
}
return nil
}
// Peers is used to get all the Raft peers
func (s *Status) Peers(args *structs.GenericRequest, reply *[]string) error {
if args.Region == "" {
args.Region = s.srv.config.Region
}
if done, err := s.srv.forward("Status.Peers", args, args, reply); done {
return err
}
future := s.srv.raft.GetConfiguration()
if err := future.Error(); err != nil {
return err
}
for _, server := range future.Configuration().Servers {
*reply = append(*reply, string(server.Address))
}
return nil
}
// Members return the list of servers in a cluster that a particular server is
// aware of
func (s *Status) Members(args *structs.GenericRequest, reply *structs.ServerMembersResponse) error {
// Check node read permissions
if aclObj, err := s.srv.ResolveToken(args.AuthToken); err != nil {
return err
} else if aclObj != nil && !aclObj.AllowNodeRead() {
return structs.ErrPermissionDenied
}
serfMembers := s.srv.Members()
members := make([]*structs.ServerMember, len(serfMembers))
for i, mem := range serfMembers {
members[i] = &structs.ServerMember{
Name: mem.Name,
Addr: mem.Addr,
Port: mem.Port,
Tags: mem.Tags,
Status: mem.Status.String(),
ProtocolMin: mem.ProtocolMin,
ProtocolMax: mem.ProtocolMax,
ProtocolCur: mem.ProtocolCur,
DelegateMin: mem.DelegateMin,
DelegateMax: mem.DelegateMax,
DelegateCur: mem.DelegateCur,
}
}
*reply = structs.ServerMembersResponse{
ServerName: s.srv.config.NodeName,
ServerRegion: s.srv.config.Region,
ServerDC: s.srv.config.Datacenter,
Members: members,
}
return nil
}
// Used by Autopilot to query the raft stats of the local server.
func (s *Status) RaftStats(args struct{}, reply *autopilot.ServerStats) error {
stats := s.srv.raft.Stats()
var err error
reply.LastContact = stats["last_contact"]
reply.LastIndex, err = strconv.ParseUint(stats["last_log_index"], 10, 64)
if err != nil {
return fmt.Errorf("error parsing server's last_log_index value: %s", err)
}
reply.LastTerm, err = strconv.ParseUint(stats["last_log_term"], 10, 64)
if err != nil {
return fmt.Errorf("error parsing server's last_log_term value: %s", err)
}
return nil
}
// HasNodeConn returns whether the server has a connection to the requested
// Node.
func (s *Status) HasNodeConn(args *structs.NodeSpecificRequest, reply *structs.NodeConnQueryResponse) error {
// Validate the args
if args.NodeID == "" {
return errors.New("Must provide the NodeID")
}
state, ok := s.srv.getNodeConn(args.NodeID)
if ok {
reply.Connected = true
reply.Established = state.Established
}
return nil
}