mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00

This standardizes the flags to use a list of URLs everywhere. The next step is to enforce the scheme based on TLS settings and support compat flags.
129 lines
2.7 KiB
Go
129 lines
2.7 KiB
Go
package etcdserver
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"net/url"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// Cluster is a list of Members that belong to the same raft cluster
|
|
type Cluster map[int64]*Member
|
|
|
|
func (c Cluster) FindID(id int64) *Member {
|
|
return c[id]
|
|
}
|
|
|
|
func (c Cluster) FindName(name string) *Member {
|
|
for _, m := range c {
|
|
if m.Name == name {
|
|
return m
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c Cluster) Add(m Member) error {
|
|
if c.FindID(m.ID) != nil {
|
|
return fmt.Errorf("Member exists with identical ID %v", m)
|
|
}
|
|
c[m.ID] = &m
|
|
return nil
|
|
}
|
|
|
|
func (c *Cluster) AddSlice(mems []Member) error {
|
|
for _, m := range mems {
|
|
err := c.Add(m)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Pick chooses a random address from a given Member's addresses, and returns it as
|
|
// an addressible URI. If the given member does not exist, an empty string is returned.
|
|
func (c Cluster) Pick(id int64) string {
|
|
if m := c.FindID(id); m != nil {
|
|
addrs := m.PeerURLs
|
|
if len(addrs) == 0 {
|
|
return ""
|
|
}
|
|
return addrs[rand.Intn(len(addrs))]
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// Set parses command line sets of names to IPs formatted like:
|
|
// mach0=http://1.1.1.1,mach0=http://2.2.2.2,mach0=http://1.1.1.1,mach1=http://2.2.2.2,mach1=http://3.3.3.3
|
|
func (c *Cluster) Set(s string) error {
|
|
*c = Cluster{}
|
|
v, err := url.ParseQuery(strings.Replace(s, ",", "&", -1))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for name, urls := range v {
|
|
if len(urls) == 0 || urls[0] == "" {
|
|
return fmt.Errorf("Empty URL given for %q", name)
|
|
}
|
|
m := newMember(name, urls, nil)
|
|
err := c.Add(*m)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c Cluster) String() string {
|
|
sl := []string{}
|
|
for _, m := range c {
|
|
for _, u := range m.PeerURLs {
|
|
sl = append(sl, fmt.Sprintf("%s=%s", m.Name, u))
|
|
}
|
|
}
|
|
sort.Strings(sl)
|
|
return strings.Join(sl, ",")
|
|
}
|
|
|
|
func (c Cluster) IDs() []int64 {
|
|
var ids []int64
|
|
for _, m := range c {
|
|
ids = append(ids, m.ID)
|
|
}
|
|
return ids
|
|
}
|
|
|
|
// PeerURLs returns a list of all peer addresses. Each address is prefixed
|
|
// with the scheme (currently "http://"). The returned list is sorted in
|
|
// ascending lexicographical order.
|
|
func (c Cluster) PeerURLs() []string {
|
|
endpoints := make([]string, 0)
|
|
for _, p := range c {
|
|
for _, addr := range p.PeerURLs {
|
|
endpoints = append(endpoints, addr)
|
|
}
|
|
}
|
|
sort.Strings(endpoints)
|
|
return endpoints
|
|
}
|
|
|
|
// ClientURLs returns a list of all client addresses. Each address is prefixed
|
|
// with the scheme (currently "http://"). The returned list is sorted in
|
|
// ascending lexicographical order.
|
|
func (c Cluster) ClientURLs() []string {
|
|
urls := make([]string, 0)
|
|
for _, p := range c {
|
|
for _, url := range p.ClientURLs {
|
|
urls = append(urls, url)
|
|
}
|
|
}
|
|
sort.Strings(urls)
|
|
return urls
|
|
}
|