github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/helper_test.go (about) 1 package consul 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "testing" 8 9 "github.com/hashicorp/consul/testutil/retry" 10 "github.com/hashicorp/raft" 11 "github.com/hashicorp/serf/serf" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func waitForLeader(servers ...*Server) error { 16 if len(servers) == 0 { 17 return errors.New("no servers") 18 } 19 dc := servers[0].config.Datacenter 20 for _, s := range servers { 21 if s.config.Datacenter != dc { 22 return fmt.Errorf("servers are in different datacenters %s and %s", s.config.Datacenter, dc) 23 } 24 } 25 for _, s := range servers { 26 if s.IsLeader() { 27 return nil 28 } 29 } 30 return errors.New("no leader") 31 } 32 33 // wantPeers determines whether the server has the given 34 // number of voting raft peers. 35 func wantPeers(s *Server, peers int) error { 36 n, err := s.numPeers() 37 if err != nil { 38 return err 39 } 40 if got, want := n, peers; got != want { 41 return fmt.Errorf("got %d peers want %d", got, want) 42 } 43 return nil 44 } 45 46 // wantRaft determines if the servers have all of each other in their 47 // Raft configurations, 48 func wantRaft(servers []*Server) error { 49 // Make sure all the servers are represented in the Raft config, 50 // and that there are no extras. 51 verifyRaft := func(c raft.Configuration) error { 52 want := make(map[raft.ServerID]bool) 53 for _, s := range servers { 54 want[s.config.RaftConfig.LocalID] = true 55 } 56 57 for _, s := range c.Servers { 58 if !want[s.ID] { 59 return fmt.Errorf("don't want %q", s.ID) 60 } 61 delete(want, s.ID) 62 } 63 64 if len(want) > 0 { 65 return fmt.Errorf("didn't find %v", want) 66 } 67 return nil 68 } 69 70 for _, s := range servers { 71 future := s.raft.GetConfiguration() 72 if err := future.Error(); err != nil { 73 return err 74 } 75 if err := verifyRaft(future.Configuration()); err != nil { 76 return err 77 } 78 } 79 return nil 80 } 81 82 // joinAddrLAN returns the address other servers can 83 // use to join the cluster on the LAN interface. 84 func joinAddrLAN(s *Server) string { 85 if s == nil { 86 panic("no server") 87 } 88 port := s.config.SerfLANConfig.MemberlistConfig.BindPort 89 return fmt.Sprintf("127.0.0.1:%d", port) 90 } 91 92 // joinAddrWAN returns the address other servers can 93 // use to join the cluster on the WAN interface. 94 func joinAddrWAN(s *Server) string { 95 if s == nil { 96 panic("no server") 97 } 98 port := s.config.SerfWANConfig.MemberlistConfig.BindPort 99 return fmt.Sprintf("127.0.0.1:%d", port) 100 } 101 102 type clientOrServer interface { 103 JoinLAN(addrs []string) (int, error) 104 LANMembers() []serf.Member 105 } 106 107 // joinLAN is a convenience function for 108 // 109 // member.JoinLAN("127.0.0.1:"+leader.config.SerfLANConfig.MemberlistConfig.BindPort) 110 func joinLAN(t *testing.T, member clientOrServer, leader *Server) { 111 if member == nil || leader == nil { 112 panic("no server") 113 } 114 var memberAddr string 115 switch x := member.(type) { 116 case *Server: 117 memberAddr = joinAddrLAN(x) 118 case *Client: 119 memberAddr = fmt.Sprintf("127.0.0.1:%d", x.config.SerfLANConfig.MemberlistConfig.BindPort) 120 } 121 leaderAddr := joinAddrLAN(leader) 122 if _, err := member.JoinLAN([]string{leaderAddr}); err != nil { 123 t.Fatal(err) 124 } 125 retry.Run(t, func(r *retry.R) { 126 if !seeEachOther(leader.LANMembers(), member.LANMembers(), leaderAddr, memberAddr) { 127 r.Fatalf("leader and member cannot see each other on LAN") 128 } 129 }) 130 if !seeEachOther(leader.LANMembers(), member.LANMembers(), leaderAddr, memberAddr) { 131 t.Fatalf("leader and member cannot see each other on LAN") 132 } 133 } 134 135 // joinWAN is a convenience function for 136 // 137 // member.JoinWAN("127.0.0.1:"+leader.config.SerfWANConfig.MemberlistConfig.BindPort) 138 func joinWAN(t *testing.T, member, leader *Server) { 139 if member == nil || leader == nil { 140 panic("no server") 141 } 142 leaderAddr, memberAddr := joinAddrWAN(leader), joinAddrWAN(member) 143 if _, err := member.JoinWAN([]string{leaderAddr}); err != nil { 144 t.Fatal(err) 145 } 146 retry.Run(t, func(r *retry.R) { 147 if !seeEachOther(leader.WANMembers(), member.WANMembers(), leaderAddr, memberAddr) { 148 r.Fatalf("leader and member cannot see each other on WAN") 149 } 150 }) 151 if !seeEachOther(leader.WANMembers(), member.WANMembers(), leaderAddr, memberAddr) { 152 t.Fatalf("leader and member cannot see each other on WAN") 153 } 154 } 155 156 func waitForNewACLs(t *testing.T, server *Server) { 157 retry.Run(t, func(r *retry.R) { 158 require.False(r, server.UseLegacyACLs(), "Server cannot use new ACLs") 159 }) 160 161 require.False(t, server.UseLegacyACLs(), "Server cannot use new ACLs") 162 } 163 164 func seeEachOther(a, b []serf.Member, addra, addrb string) bool { 165 return serfMembersContains(a, addrb) && serfMembersContains(b, addra) 166 } 167 168 func serfMembersContains(members []serf.Member, addr string) bool { 169 // There are tests that manipulate the advertise address, so we just 170 // compare port numbers here, since that uniquely identifies a member 171 // as we use the loopback interface for everything. 172 _, want, err := net.SplitHostPort(addr) 173 if err != nil { 174 panic(err) 175 } 176 for _, m := range members { 177 if got := fmt.Sprintf("%d", m.Port); got == want { 178 return true 179 } 180 } 181 return false 182 }