package consul import ( "fmt" "io/ioutil" "net" "os" "testing" "time" ) var nextPort = 15000 func getPort() int { p := nextPort nextPort++ return p } func tmpDir(t *testing.T) string { dir, err := ioutil.TempDir("", "consul") if err != nil { t.Fatalf("err: %v", err) } return dir } func configureTLS(config *Config) { config.CAFile = "../test/ca/root.cer" config.CertFile = "../test/key/ourdomain.cer" config.KeyFile = "../test/key/ourdomain.key" } func testServerConfig(t *testing.T) (string, *Config) { dir := tmpDir(t) config := DefaultConfig() config.Bootstrap = true config.Datacenter = "dc1" config.DataDir = dir // Adjust the ports p := getPort() config.NodeName = fmt.Sprintf("Node %d", p) config.RPCAddr = &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: p, } config.SerfLANConfig.MemberlistConfig.BindAddr = "127.0.0.1" config.SerfLANConfig.MemberlistConfig.BindPort = getPort() config.SerfLANConfig.MemberlistConfig.SuspicionMult = 2 config.SerfLANConfig.MemberlistConfig.ProbeTimeout = 50 * time.Millisecond config.SerfLANConfig.MemberlistConfig.ProbeInterval = 100 * time.Millisecond config.SerfLANConfig.MemberlistConfig.GossipInterval = 100 * time.Millisecond config.SerfWANConfig.MemberlistConfig.BindAddr = "127.0.0.1" config.SerfWANConfig.MemberlistConfig.BindPort = getPort() config.SerfWANConfig.MemberlistConfig.SuspicionMult = 2 config.SerfWANConfig.MemberlistConfig.ProbeTimeout = 50 * time.Millisecond config.SerfWANConfig.MemberlistConfig.ProbeInterval = 100 * time.Millisecond config.SerfWANConfig.MemberlistConfig.GossipInterval = 100 * time.Millisecond config.RaftConfig.HeartbeatTimeout = 40 * time.Millisecond config.RaftConfig.ElectionTimeout = 40 * time.Millisecond config.ReconcileInterval = 100 * time.Millisecond return dir, config } func testServer(t *testing.T) (string, *Server) { return testServerDC(t, "dc1") } func testServerDC(t *testing.T, dc string) (string, *Server) { return testServerDCBootstrap(t, dc, true) } func testServerDCBootstrap(t *testing.T, dc string, bootstrap bool) (string, *Server) { dir, config := testServerConfig(t) config.Datacenter = dc config.Bootstrap = bootstrap server, err := NewServer(config) if err != nil { t.Fatalf("err: %v", err) } return dir, server } func TestServer_StartStop(t *testing.T) { dir := tmpDir(t) defer os.RemoveAll(dir) config := DefaultConfig() config.DataDir = dir private, err := GetPrivateIP() if err != nil { t.Fatalf("err: %v", err) } config.RPCAdvertise = &net.TCPAddr{ IP: private.IP, Port: 8300, } server, err := NewServer(config) if err != nil { t.Fatalf("err: %v", err) } if err := server.Shutdown(); err != nil { t.Fatalf("err: %v", err) } // Idempotent if err := server.Shutdown(); err != nil { t.Fatalf("err: %v", err) } } func TestServer_JoinLAN(t *testing.T) { dir1, s1 := testServer(t) defer os.RemoveAll(dir1) defer s1.Shutdown() dir2, s2 := testServer(t) defer os.RemoveAll(dir2) defer s2.Shutdown() // Try to join addr := fmt.Sprintf("127.0.0.1:%d", s1.config.SerfLANConfig.MemberlistConfig.BindPort) if _, err := s2.JoinLAN([]string{addr}); err != nil { t.Fatalf("err: %v", err) } // Check the members if len(s1.LANMembers()) != 2 { t.Fatalf("bad len") } if len(s2.LANMembers()) != 2 { t.Fatalf("bad len") } } func TestServer_JoinWAN(t *testing.T) { dir1, s1 := testServer(t) defer os.RemoveAll(dir1) defer s1.Shutdown() dir2, s2 := testServerDC(t, "dc2") defer os.RemoveAll(dir2) defer s2.Shutdown() // Try to join addr := fmt.Sprintf("127.0.0.1:%d", s1.config.SerfWANConfig.MemberlistConfig.BindPort) if _, err := s2.JoinWAN([]string{addr}); err != nil { t.Fatalf("err: %v", err) } // Check the members if len(s1.WANMembers()) != 2 { t.Fatalf("bad len") } if len(s2.WANMembers()) != 2 { t.Fatalf("bad len") } time.Sleep(10 * time.Millisecond) // Check the remoteConsuls has both if len(s1.remoteConsuls) != 2 { t.Fatalf("remote consul missing") } if len(s2.remoteConsuls) != 2 { t.Fatalf("remote consul missing") } } func TestServer_Leave(t *testing.T) { dir1, s1 := testServer(t) defer os.RemoveAll(dir1) defer s1.Shutdown() // Second server not in bootstrap mode dir2, s2 := testServerDCBootstrap(t, "dc1", false) defer os.RemoveAll(dir2) defer s2.Shutdown() // Try to join addr := fmt.Sprintf("127.0.0.1:%d", s1.config.SerfLANConfig.MemberlistConfig.BindPort) if _, err := s2.JoinLAN([]string{addr}); err != nil { t.Fatalf("err: %v", err) } time.Sleep(time.Second) p1, _ := s1.raftPeers.Peers() if len(p1) != 2 { t.Fatalf("should have 2 peers: %v", p1) } p2, _ := s2.raftPeers.Peers() if len(p2) != 2 { t.Fatalf("should have 2 peers: %v", p2) } // Issue a leave if err := s2.Leave(); err != nil { t.Fatalf("err: %v", err) } // Should lose a peer p1, _ = s1.raftPeers.Peers() if len(p1) != 1 { t.Fatalf("should have 1 peer: %v", p1) } } func TestServer_RPC(t *testing.T) { dir1, s1 := testServer(t) defer os.RemoveAll(dir1) defer s1.Shutdown() var out struct{} if err := s1.RPC("Status.Ping", struct{}{}, &out); err != nil { t.Fatalf("err: %v", err) } } func TestServer_JoinLAN_TLS(t *testing.T) { dir1, conf1 := testServerConfig(t) conf1.VerifyIncoming = true conf1.VerifyOutgoing = true configureTLS(conf1) s1, err := NewServer(conf1) if err != nil { t.Fatalf("err: %v", err) } defer os.RemoveAll(dir1) defer s1.Shutdown() dir2, conf2 := testServerConfig(t) conf2.Bootstrap = false conf2.VerifyIncoming = true conf2.VerifyOutgoing = true configureTLS(conf2) s2, err := NewServer(conf2) if err != nil { t.Fatalf("err: %v", err) } defer os.RemoveAll(dir2) defer s2.Shutdown() // Try to join addr := fmt.Sprintf("127.0.0.1:%d", s1.config.SerfLANConfig.MemberlistConfig.BindPort) if _, err := s2.JoinLAN([]string{addr}); err != nil { t.Fatalf("err: %v", err) } // Check the members if len(s1.LANMembers()) != 2 { t.Fatalf("bad len") } if len(s2.LANMembers()) != 2 { t.Fatalf("bad len") } // Wait a while time.Sleep(100 * time.Millisecond) // Verify Raft has established a peer if s1.Stats()["raft"]["num_peers"] != "1" { t.Fatalf("bad: %v", s1.Stats()["raft"]) } if s2.Stats()["raft"]["num_peers"] != "1" { t.Fatalf("bad: %v", s2.Stats()["raft"]) } }