2013-12-11 22:57:40 +00:00
|
|
|
package consul
|
|
|
|
|
|
|
|
import (
|
2013-12-12 00:33:19 +00:00
|
|
|
"fmt"
|
2013-12-19 20:03:57 +00:00
|
|
|
"github.com/hashicorp/consul/consul/structs"
|
|
|
|
"net/rpc"
|
2013-12-11 22:57:40 +00:00
|
|
|
"os"
|
2013-12-12 18:35:50 +00:00
|
|
|
"sort"
|
2013-12-11 22:57:40 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestCatalogRegister(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(t, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
2013-12-19 20:03:57 +00:00
|
|
|
arg := structs.RegisterRequest{
|
2014-01-08 21:39:40 +00:00
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: "foo",
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
Service: "db",
|
|
|
|
Tag: "master",
|
|
|
|
Port: 8000,
|
|
|
|
},
|
2013-12-11 22:57:40 +00:00
|
|
|
}
|
|
|
|
var out struct{}
|
|
|
|
|
|
|
|
err := client.Call("Catalog.Register", &arg, &out)
|
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for leader
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
if err := client.Call("Catalog.Register", &arg, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
2013-12-11 23:34:10 +00:00
|
|
|
|
2013-12-12 00:42:19 +00:00
|
|
|
func TestCatalogRegister_ForwardLeader(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client1 := rpcClient(t, s1)
|
|
|
|
defer client1.Close()
|
|
|
|
|
|
|
|
dir2, s2 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir2)
|
|
|
|
defer s2.Shutdown()
|
|
|
|
client2 := rpcClient(t, s2)
|
|
|
|
defer client2.Close()
|
|
|
|
|
|
|
|
// Try to join
|
|
|
|
addr := fmt.Sprintf("127.0.0.1:%d",
|
2013-12-30 20:20:17 +00:00
|
|
|
s1.config.SerfLANConfig.MemberlistConfig.BindPort)
|
|
|
|
if _, err := s2.JoinLAN([]string{addr}); err != nil {
|
2013-12-12 00:42:19 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for a leader
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
// Use the follower as the client
|
2013-12-19 20:03:57 +00:00
|
|
|
var client *rpc.Client
|
2013-12-12 00:42:19 +00:00
|
|
|
if !s1.IsLeader() {
|
|
|
|
client = client1
|
|
|
|
} else {
|
|
|
|
client = client2
|
|
|
|
}
|
|
|
|
|
2013-12-19 20:03:57 +00:00
|
|
|
arg := structs.RegisterRequest{
|
2014-01-08 21:39:40 +00:00
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: "foo",
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
Service: "db",
|
|
|
|
Tag: "master",
|
|
|
|
Port: 8000,
|
|
|
|
},
|
2013-12-12 00:42:19 +00:00
|
|
|
}
|
|
|
|
var out struct{}
|
|
|
|
if err := client.Call("Catalog.Register", &arg, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 00:33:19 +00:00
|
|
|
func TestCatalogRegister_ForwardDC(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(t, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
dir2, s2 := testServerDC(t, "dc2")
|
|
|
|
defer os.RemoveAll(dir2)
|
|
|
|
defer s2.Shutdown()
|
|
|
|
|
|
|
|
// Try to join
|
|
|
|
addr := fmt.Sprintf("127.0.0.1:%d",
|
2013-12-30 20:20:17 +00:00
|
|
|
s1.config.SerfWANConfig.MemberlistConfig.BindPort)
|
|
|
|
if _, err := s2.JoinWAN([]string{addr}); err != nil {
|
2013-12-12 00:33:19 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for the leaders
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
2013-12-19 20:03:57 +00:00
|
|
|
arg := structs.RegisterRequest{
|
2014-01-08 21:39:40 +00:00
|
|
|
Datacenter: "dc2", // SHould forward through s1
|
|
|
|
Node: "foo",
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
Service: "db",
|
|
|
|
Tag: "master",
|
|
|
|
Port: 8000,
|
|
|
|
},
|
2013-12-12 00:33:19 +00:00
|
|
|
}
|
|
|
|
var out struct{}
|
|
|
|
if err := client.Call("Catalog.Register", &arg, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-11 23:34:10 +00:00
|
|
|
func TestCatalogDeregister(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(t, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
2013-12-19 20:03:57 +00:00
|
|
|
arg := structs.DeregisterRequest{
|
2013-12-11 23:34:10 +00:00
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: "foo",
|
|
|
|
}
|
|
|
|
var out struct{}
|
|
|
|
|
|
|
|
err := client.Call("Catalog.Deregister", &arg, &out)
|
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for leader
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
if err := client.Call("Catalog.Deregister", &arg, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
2013-12-12 18:35:50 +00:00
|
|
|
|
|
|
|
func TestCatalogListDatacenters(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(t, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
dir2, s2 := testServerDC(t, "dc2")
|
|
|
|
defer os.RemoveAll(dir2)
|
|
|
|
defer s2.Shutdown()
|
|
|
|
|
|
|
|
// Try to join
|
|
|
|
addr := fmt.Sprintf("127.0.0.1:%d",
|
2013-12-30 20:20:17 +00:00
|
|
|
s1.config.SerfWANConfig.MemberlistConfig.BindPort)
|
|
|
|
if _, err := s2.JoinWAN([]string{addr}); err != nil {
|
2013-12-12 18:35:50 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
|
|
|
|
var out []string
|
|
|
|
if err := client.Call("Catalog.ListDatacenters", struct{}{}, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort the dcs
|
|
|
|
sort.Strings(out)
|
|
|
|
|
|
|
|
if len(out) != 2 {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
if out[0] != "dc1" {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
if out[1] != "dc2" {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
2013-12-12 18:48:36 +00:00
|
|
|
|
|
|
|
func TestCatalogListNodes(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(t, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
2013-12-19 20:03:57 +00:00
|
|
|
var out structs.Nodes
|
2013-12-12 18:48:36 +00:00
|
|
|
err := client.Call("Catalog.ListNodes", "dc1", &out)
|
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for leader
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
// Just add a node
|
2014-01-08 18:31:42 +00:00
|
|
|
s1.fsm.State().EnsureNode(structs.Node{"foo", "127.0.0.1"})
|
2013-12-12 18:48:36 +00:00
|
|
|
|
|
|
|
if err := client.Call("Catalog.ListNodes", "dc1", &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-01-10 01:22:01 +00:00
|
|
|
if len(out) != 2 {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Server node is auto added from Serf
|
|
|
|
if out[0].Node != s1.config.NodeName {
|
2013-12-12 18:48:36 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-01-10 01:22:01 +00:00
|
|
|
if out[1].Node != "foo" {
|
2013-12-12 18:48:36 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-01-10 01:22:01 +00:00
|
|
|
if out[1].Address != "127.0.0.1" {
|
2013-12-12 18:48:36 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
2013-12-12 19:07:14 +00:00
|
|
|
|
2014-02-01 20:16:33 +00:00
|
|
|
func BenchmarkCatalogListNodes(t *testing.B) {
|
|
|
|
dir1, s1 := testServer(nil)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(nil, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Wait for leader
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
// Just add a node
|
|
|
|
s1.fsm.State().EnsureNode(structs.Node{"foo", "127.0.0.1"})
|
|
|
|
|
|
|
|
for i := 0; i < t.N; i++ {
|
|
|
|
var out structs.Nodes
|
|
|
|
if err := client.Call("Catalog.ListNodes", "dc1", &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 19:07:14 +00:00
|
|
|
func TestCatalogListServices(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(t, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
2013-12-19 20:03:57 +00:00
|
|
|
var out structs.Services
|
2013-12-12 19:07:14 +00:00
|
|
|
err := client.Call("Catalog.ListServices", "dc1", &out)
|
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for leader
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
// Just add a node
|
2014-01-08 18:31:42 +00:00
|
|
|
s1.fsm.State().EnsureNode(structs.Node{"foo", "127.0.0.1"})
|
2014-01-06 22:18:38 +00:00
|
|
|
s1.fsm.State().EnsureService("foo", "db", "db", "primary", 5000)
|
2013-12-12 19:07:14 +00:00
|
|
|
|
|
|
|
if err := client.Call("Catalog.ListServices", "dc1", &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-01-10 01:57:13 +00:00
|
|
|
if len(out) != 2 {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
// Consul service should auto-register
|
|
|
|
if len(out["consul"]) != 1 {
|
2013-12-12 19:07:14 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
if len(out["db"]) != 1 {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
if out["db"][0] != "primary" {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
2013-12-12 19:37:19 +00:00
|
|
|
|
|
|
|
func TestCatalogListServiceNodes(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(t, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
2014-01-08 21:52:09 +00:00
|
|
|
args := structs.ServiceSpecificRequest{
|
2013-12-12 19:37:19 +00:00
|
|
|
Datacenter: "dc1",
|
|
|
|
ServiceName: "db",
|
|
|
|
ServiceTag: "slave",
|
|
|
|
TagFilter: false,
|
|
|
|
}
|
2013-12-19 20:03:57 +00:00
|
|
|
var out structs.ServiceNodes
|
2013-12-12 19:37:19 +00:00
|
|
|
err := client.Call("Catalog.ServiceNodes", &args, &out)
|
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for leader
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
// Just add a node
|
2014-01-08 18:31:42 +00:00
|
|
|
s1.fsm.State().EnsureNode(structs.Node{"foo", "127.0.0.1"})
|
2014-01-06 22:18:38 +00:00
|
|
|
s1.fsm.State().EnsureService("foo", "db", "db", "primary", 5000)
|
2013-12-12 19:37:19 +00:00
|
|
|
|
|
|
|
if err := client.Call("Catalog.ServiceNodes", &args, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(out) != 1 {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try with a filter
|
|
|
|
args.TagFilter = true
|
2014-01-08 18:31:42 +00:00
|
|
|
out = nil
|
2013-12-12 19:37:19 +00:00
|
|
|
|
|
|
|
if err := client.Call("Catalog.ServiceNodes", &args, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
if len(out) != 0 {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
2013-12-12 19:46:25 +00:00
|
|
|
|
|
|
|
func TestCatalogNodeServices(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(t, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
2014-01-08 21:52:09 +00:00
|
|
|
args := structs.NodeSpecificRequest{
|
2013-12-12 19:46:25 +00:00
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: "foo",
|
|
|
|
}
|
2013-12-19 20:03:57 +00:00
|
|
|
var out structs.NodeServices
|
2013-12-12 19:46:25 +00:00
|
|
|
err := client.Call("Catalog.NodeServices", &args, &out)
|
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for leader
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
// Just add a node
|
2014-01-08 18:31:42 +00:00
|
|
|
s1.fsm.State().EnsureNode(structs.Node{"foo", "127.0.0.1"})
|
2014-01-06 22:18:38 +00:00
|
|
|
s1.fsm.State().EnsureService("foo", "db", "db", "primary", 5000)
|
|
|
|
s1.fsm.State().EnsureService("foo", "web", "web", "", 80)
|
2013-12-12 19:46:25 +00:00
|
|
|
|
|
|
|
if err := client.Call("Catalog.NodeServices", &args, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-01-08 22:43:36 +00:00
|
|
|
if out.Node.Address != "127.0.0.1" {
|
2014-01-03 01:29:39 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
if len(out.Services) != 2 {
|
2013-12-12 19:46:25 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-01-03 01:29:39 +00:00
|
|
|
if out.Services["db"].Tag != "primary" || out.Services["db"].Port != 5000 {
|
2013-12-12 19:46:25 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-01-03 01:29:39 +00:00
|
|
|
if out.Services["web"].Tag != "" || out.Services["web"].Port != 80 {
|
2013-12-12 19:46:25 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
2014-01-01 02:31:17 +00:00
|
|
|
|
|
|
|
// Used to check for a regression against a known bug
|
|
|
|
func TestCatalogRegister_FailedCase1(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
|
|
|
client := rpcClient(t, s1)
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
arg := structs.RegisterRequest{
|
2014-01-08 21:39:40 +00:00
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: "bar",
|
|
|
|
Address: "127.0.0.2",
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
Service: "web",
|
|
|
|
Tag: "",
|
|
|
|
Port: 8000,
|
|
|
|
},
|
2014-01-01 02:31:17 +00:00
|
|
|
}
|
|
|
|
var out struct{}
|
|
|
|
|
|
|
|
err := client.Call("Catalog.Register", &arg, &out)
|
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for leader
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
if err := client.Call("Catalog.Register", &arg, &out); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check we can get this back
|
2014-01-08 21:52:09 +00:00
|
|
|
query := &structs.ServiceSpecificRequest{
|
2014-01-01 02:31:17 +00:00
|
|
|
Datacenter: "dc1",
|
|
|
|
ServiceName: "web",
|
|
|
|
}
|
|
|
|
var nodes structs.ServiceNodes
|
|
|
|
if err := client.Call("Catalog.ServiceNodes", query, &nodes); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the output
|
|
|
|
if len(nodes) != 1 {
|
|
|
|
t.Fatalf("Bad: %v", nodes)
|
|
|
|
}
|
|
|
|
}
|