consul/agent/metadata/server.go

169 lines
3.4 KiB
Go
Raw Normal View History

package metadata
import (
"fmt"
"net"
2017-03-21 23:36:44 +00:00
"regexp"
"strconv"
"strings"
2017-03-21 23:36:44 +00:00
"github.com/hashicorp/go-version"
"github.com/hashicorp/serf/serf"
)
// Key is used in maps and for equality tests. A key is based on endpoints.
type Key struct {
name string
}
// Equal compares two Key objects
func (k *Key) Equal(x *Key) bool {
return k.name == x.name
}
2016-03-30 00:39:19 +00:00
// Server is used to return details of a consul server
type Server struct {
Name string
ID string
Datacenter string
Segment string
Port int
SegmentAddrs map[string]string
SegmentPorts map[string]int
WanJoinPort int
Bootstrap bool
Expect int
Build version.Version
Version int
RaftVersion int
Addr net.Addr
Status serf.MemberStatus
2018-09-20 00:41:36 +00:00
NonVoter bool
// If true, use TLS when connecting to this server
UseTLS bool
}
// Key returns the corresponding Key
2016-03-30 00:39:19 +00:00
func (s *Server) Key() *Key {
return &Key{
name: s.Name,
}
}
2016-03-30 00:39:19 +00:00
// String returns a string representation of Server
func (s *Server) String() string {
var addrStr, networkStr string
if s.Addr != nil {
addrStr = s.Addr.String()
networkStr = s.Addr.Network()
}
return fmt.Sprintf("%s (Addr: %s/%s) (DC: %s)", s.Name, networkStr, addrStr, s.Datacenter)
}
2017-03-21 23:36:44 +00:00
var versionFormat = regexp.MustCompile(`\d+\.\d+\.\d+`)
2016-03-30 00:39:19 +00:00
// IsConsulServer returns true if a serf member is a consul server
// agent. Returns a bool and a pointer to the Server.
func IsConsulServer(m serf.Member) (bool, *Server) {
if m.Tags["role"] != "consul" {
return false, nil
}
datacenter := m.Tags["dc"]
segment := m.Tags["segment"]
_, bootstrap := m.Tags["bootstrap"]
_, useTLS := m.Tags["use_tls"]
expect := 0
2018-01-28 18:40:13 +00:00
expectStr, ok := m.Tags["expect"]
var err error
if ok {
2018-01-28 18:40:13 +00:00
expect, err = strconv.Atoi(expectStr)
if err != nil {
return false, nil
}
}
2018-01-28 18:40:13 +00:00
portStr := m.Tags["port"]
port, err := strconv.Atoi(portStr)
if err != nil {
return false, nil
}
2018-01-28 18:40:13 +00:00
segmentAddrs := make(map[string]string)
segmentPorts := make(map[string]int)
for name, value := range m.Tags {
if strings.HasPrefix(name, "sl_") {
addr, port, err := net.SplitHostPort(value)
if err != nil {
return false, nil
}
2018-01-28 18:40:13 +00:00
segmentPort, err := strconv.Atoi(port)
if err != nil {
return false, nil
}
2018-01-28 18:40:13 +00:00
segmentName := strings.TrimPrefix(name, "sl_")
segmentAddrs[segmentName] = addr
segmentPorts[segmentName] = segmentPort
}
}
2018-01-28 18:40:13 +00:00
buildVersion, err := Build(&m)
2017-03-21 23:36:44 +00:00
if err != nil {
return false, nil
}
2018-01-28 18:40:13 +00:00
wanJoinPort := 0
wanJoinPortStr, ok := m.Tags["wan_join_port"]
2017-03-15 19:26:54 +00:00
if ok {
2018-01-28 18:40:13 +00:00
wanJoinPort, err = strconv.Atoi(wanJoinPortStr)
2017-03-15 19:26:54 +00:00
if err != nil {
return false, nil
}
}
2018-01-28 18:40:13 +00:00
vsnStr := m.Tags["vsn"]
vsn, err := strconv.Atoi(vsnStr)
if err != nil {
return false, nil
}
2018-01-28 18:40:13 +00:00
raftVsn := 0
2018-01-28 18:48:21 +00:00
raftVsnStr, ok := m.Tags["raft_vsn"]
if ok {
2018-01-28 18:48:21 +00:00
raftVsn, err = strconv.Atoi(raftVsnStr)
if err != nil {
return false, nil
}
2017-02-22 20:53:32 +00:00
}
2018-09-20 00:41:36 +00:00
// Check if the server is a non voter
_, nonVoter := m.Tags["nonvoter"]
addr := &net.TCPAddr{IP: m.Addr, Port: port}
2016-03-30 00:39:19 +00:00
parts := &Server{
Name: m.Name,
ID: m.Tags["id"],
Datacenter: datacenter,
Segment: segment,
Port: port,
2018-01-28 18:40:13 +00:00
SegmentAddrs: segmentAddrs,
SegmentPorts: segmentPorts,
2018-01-28 18:48:21 +00:00
WanJoinPort: wanJoinPort,
Bootstrap: bootstrap,
Expect: expect,
Addr: addr,
2018-01-28 18:40:13 +00:00
Build: *buildVersion,
Version: vsn,
2018-01-28 18:40:13 +00:00
RaftVersion: raftVsn,
Status: m.Status,
UseTLS: useTLS,
2018-09-20 00:41:36 +00:00
NonVoter: nonVoter,
}
return true, parts
}