github.imxd.top/hashicorp/consul@v1.4.5/agent/metadata/server.go (about) 1 package metadata 2 3 import ( 4 "fmt" 5 "net" 6 "regexp" 7 "strconv" 8 "strings" 9 10 "github.com/hashicorp/consul/agent/structs" 11 "github.com/hashicorp/go-version" 12 "github.com/hashicorp/serf/serf" 13 ) 14 15 // Key is used in maps and for equality tests. A key is based on endpoints. 16 type Key struct { 17 name string 18 } 19 20 // Equal compares two Key objects 21 func (k *Key) Equal(x *Key) bool { 22 return k.name == x.name 23 } 24 25 // Server is used to return details of a consul server 26 type Server struct { 27 Name string 28 ID string 29 Datacenter string 30 Segment string 31 Port int 32 SegmentAddrs map[string]string 33 SegmentPorts map[string]int 34 WanJoinPort int 35 Bootstrap bool 36 Expect int 37 Build version.Version 38 Version int 39 RaftVersion int 40 Addr net.Addr 41 Status serf.MemberStatus 42 NonVoter bool 43 ACLs structs.ACLMode 44 45 // If true, use TLS when connecting to this server 46 UseTLS bool 47 } 48 49 // Key returns the corresponding Key 50 func (s *Server) Key() *Key { 51 return &Key{ 52 name: s.Name, 53 } 54 } 55 56 // String returns a string representation of Server 57 func (s *Server) String() string { 58 var addrStr, networkStr string 59 if s.Addr != nil { 60 addrStr = s.Addr.String() 61 networkStr = s.Addr.Network() 62 } 63 64 return fmt.Sprintf("%s (Addr: %s/%s) (DC: %s)", s.Name, networkStr, addrStr, s.Datacenter) 65 } 66 67 var versionFormat = regexp.MustCompile(`\d+\.\d+\.\d+`) 68 69 // IsConsulServer returns true if a serf member is a consul server 70 // agent. Returns a bool and a pointer to the Server. 71 func IsConsulServer(m serf.Member) (bool, *Server) { 72 if m.Tags["role"] != "consul" { 73 return false, nil 74 } 75 76 datacenter := m.Tags["dc"] 77 segment := m.Tags["segment"] 78 _, bootstrap := m.Tags["bootstrap"] 79 _, useTLS := m.Tags["use_tls"] 80 81 expect := 0 82 expectStr, ok := m.Tags["expect"] 83 var err error 84 if ok { 85 expect, err = strconv.Atoi(expectStr) 86 if err != nil { 87 return false, nil 88 } 89 } 90 91 portStr := m.Tags["port"] 92 port, err := strconv.Atoi(portStr) 93 if err != nil { 94 return false, nil 95 } 96 97 var acls structs.ACLMode 98 if aclMode, ok := m.Tags["acls"]; ok { 99 acls = structs.ACLMode(aclMode) 100 } else { 101 acls = structs.ACLModeUnknown 102 } 103 104 segmentAddrs := make(map[string]string) 105 segmentPorts := make(map[string]int) 106 for name, value := range m.Tags { 107 if strings.HasPrefix(name, "sl_") { 108 addr, port, err := net.SplitHostPort(value) 109 if err != nil { 110 return false, nil 111 } 112 segmentPort, err := strconv.Atoi(port) 113 if err != nil { 114 return false, nil 115 } 116 117 segmentName := strings.TrimPrefix(name, "sl_") 118 segmentAddrs[segmentName] = addr 119 segmentPorts[segmentName] = segmentPort 120 } 121 } 122 123 buildVersion, err := Build(&m) 124 if err != nil { 125 return false, nil 126 } 127 128 wanJoinPort := 0 129 wanJoinPortStr, ok := m.Tags["wan_join_port"] 130 if ok { 131 wanJoinPort, err = strconv.Atoi(wanJoinPortStr) 132 if err != nil { 133 return false, nil 134 } 135 } 136 137 vsnStr := m.Tags["vsn"] 138 vsn, err := strconv.Atoi(vsnStr) 139 if err != nil { 140 return false, nil 141 } 142 143 raftVsn := 0 144 raftVsnStr, ok := m.Tags["raft_vsn"] 145 if ok { 146 raftVsn, err = strconv.Atoi(raftVsnStr) 147 if err != nil { 148 return false, nil 149 } 150 } 151 152 // Check if the server is a non voter 153 _, nonVoter := m.Tags["nonvoter"] 154 155 addr := &net.TCPAddr{IP: m.Addr, Port: port} 156 157 parts := &Server{ 158 Name: m.Name, 159 ID: m.Tags["id"], 160 Datacenter: datacenter, 161 Segment: segment, 162 Port: port, 163 SegmentAddrs: segmentAddrs, 164 SegmentPorts: segmentPorts, 165 WanJoinPort: wanJoinPort, 166 Bootstrap: bootstrap, 167 Expect: expect, 168 Addr: addr, 169 Build: *buildVersion, 170 Version: vsn, 171 RaftVersion: raftVsn, 172 Status: m.Status, 173 UseTLS: useTLS, 174 NonVoter: nonVoter, 175 ACLs: acls, 176 } 177 return true, parts 178 }