github.com/clly/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  }