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
|
|
|
"net/rpc"
|
2013-12-11 22:57:40 +00:00
|
|
|
"os"
|
2013-12-12 18:35:50 +00:00
|
|
|
"sort"
|
2014-04-21 19:08:00 +00:00
|
|
|
"strings"
|
2013-12-11 22:57:40 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
2014-10-09 18:54:47 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/consul/consul/structs"
|
|
|
|
"github.com/hashicorp/consul/testutil"
|
2015-10-13 23:43:52 +00:00
|
|
|
"github.com/hashicorp/net-rpc-msgpackrpc"
|
2013-12-11 22:57:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestCatalogRegister(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2013-12-11 22:57:40 +00:00
|
|
|
|
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",
|
2014-04-03 19:03:10 +00:00
|
|
|
Tags: []string{"master"},
|
2014-01-08 21:39:40 +00:00
|
|
|
Port: 8000,
|
|
|
|
},
|
2013-12-11 22:57:40 +00:00
|
|
|
}
|
|
|
|
var out struct{}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out)
|
2013-12-11 22:57:40 +00:00
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-05-07 00:48:25 +00:00
|
|
|
testutil.WaitForResult(func() (bool, error) {
|
2015-10-13 23:43:52 +00:00
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out)
|
2014-05-07 00:48:25 +00:00
|
|
|
return err == nil, err
|
|
|
|
}, func(err error) {
|
2013-12-11 22:57:40 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
2014-05-07 00:48:25 +00:00
|
|
|
})
|
2013-12-11 22:57:40 +00:00
|
|
|
}
|
2013-12-11 23:34:10 +00:00
|
|
|
|
2014-12-01 04:05:15 +00:00
|
|
|
func TestCatalogRegister_ACLDeny(t *testing.T) {
|
|
|
|
dir1, s1 := testServerWithConfig(t, func(c *Config) {
|
|
|
|
c.ACLDatacenter = "dc1"
|
|
|
|
c.ACLMasterToken = "root"
|
|
|
|
c.ACLDefaultPolicy = "deny"
|
|
|
|
})
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2014-12-01 04:05:15 +00:00
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2014-12-01 04:05:15 +00:00
|
|
|
|
|
|
|
// Create the ACL
|
|
|
|
arg := structs.ACLRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
Op: structs.ACLSet,
|
|
|
|
ACL: structs.ACL{
|
|
|
|
Name: "User token",
|
|
|
|
Type: structs.ACLTypeClient,
|
|
|
|
Rules: testRegisterRules,
|
|
|
|
},
|
|
|
|
WriteRequest: structs.WriteRequest{Token: "root"},
|
|
|
|
}
|
|
|
|
var out string
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out); err != nil {
|
2014-12-01 04:05:15 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
id := out
|
|
|
|
|
|
|
|
argR := structs.RegisterRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: "foo",
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
Service: "db",
|
|
|
|
Tags: []string{"master"},
|
|
|
|
Port: 8000,
|
|
|
|
},
|
|
|
|
WriteRequest: structs.WriteRequest{Token: id},
|
|
|
|
}
|
|
|
|
var outR struct{}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR)
|
2014-12-01 04:05:15 +00:00
|
|
|
if err == nil || !strings.Contains(err.Error(), permissionDenied) {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2014-12-01 04:10:42 +00:00
|
|
|
|
|
|
|
argR.Service.Service = "foo"
|
2015-10-13 23:43:52 +00:00
|
|
|
err = msgpackrpc.CallWithCodec(codec, "Catalog.Register", &argR, &outR)
|
2014-12-01 04:10:42 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2014-12-01 04:05:15 +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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec1 := rpcClient(t, s1)
|
|
|
|
defer codec1.Close()
|
2013-12-12 00:42:19 +00:00
|
|
|
|
|
|
|
dir2, s2 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir2)
|
|
|
|
defer s2.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec2 := rpcClient(t, s2)
|
|
|
|
defer codec2.Close()
|
2013-12-12 00:42:19 +00:00
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
|
|
|
testutil.WaitForLeader(t, s2.RPC, "dc1")
|
2013-12-12 00:42:19 +00:00
|
|
|
|
|
|
|
// Use the follower as the client
|
2015-10-13 23:43:52 +00:00
|
|
|
var codec rpc.ClientCodec
|
2013-12-12 00:42:19 +00:00
|
|
|
if !s1.IsLeader() {
|
2015-10-13 23:43:52 +00:00
|
|
|
codec = codec1
|
2013-12-12 00:42:19 +00:00
|
|
|
} else {
|
2015-10-13 23:43:52 +00:00
|
|
|
codec = codec2
|
2013-12-12 00:42:19 +00:00
|
|
|
}
|
|
|
|
|
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",
|
2014-04-03 19:03:10 +00:00
|
|
|
Tags: []string{"master"},
|
2014-01-08 21:39:40 +00:00
|
|
|
Port: 8000,
|
|
|
|
},
|
2013-12-12 00:42:19 +00:00
|
|
|
}
|
|
|
|
var out struct{}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil {
|
2013-12-12 00:42:19 +00:00
|
|
|
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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2013-12-12 00:33:19 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc2")
|
2013-12-12 00:33:19 +00:00
|
|
|
|
2013-12-19 20:03:57 +00:00
|
|
|
arg := structs.RegisterRequest{
|
2015-09-15 12:22:08 +00:00
|
|
|
Datacenter: "dc2", // Should forward through s1
|
2014-01-08 21:39:40 +00:00
|
|
|
Node: "foo",
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
Service: "db",
|
2014-04-03 19:03:10 +00:00
|
|
|
Tags: []string{"master"},
|
2014-01-08 21:39:40 +00:00
|
|
|
Port: 8000,
|
|
|
|
},
|
2013-12-12 00:33:19 +00:00
|
|
|
}
|
|
|
|
var out struct{}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil {
|
2013-12-12 00:33:19 +00:00
|
|
|
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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2013-12-11 23:34:10 +00:00
|
|
|
|
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{}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", &arg, &out)
|
2013-12-11 23:34:10 +00:00
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2013-12-11 23:34:10 +00:00
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.Deregister", &arg, &out); err != nil {
|
2013-12-11 23:34:10 +00:00
|
|
|
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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2013-12-12 18:35:50 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
2014-05-08 23:18:35 +00:00
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2013-12-12 18:35:50 +00:00
|
|
|
|
|
|
|
var out []string
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListDatacenters", struct{}{}, &out); err != nil {
|
2013-12-12 18:35:50 +00:00
|
|
|
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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2013-12-12 18:48:36 +00:00
|
|
|
|
2014-02-05 19:00:43 +00:00
|
|
|
args := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
}
|
|
|
|
var out structs.IndexedNodes
|
2015-10-13 23:43:52 +00:00
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out)
|
2013-12-12 18:48:36 +00:00
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2013-12-12 18:48:36 +00:00
|
|
|
|
|
|
|
// Just add a node
|
2015-09-10 21:40:11 +00:00
|
|
|
s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"})
|
2013-12-12 18:48:36 +00:00
|
|
|
|
2014-05-09 01:00:56 +00:00
|
|
|
testutil.WaitForResult(func() (bool, error) {
|
2015-10-13 23:43:52 +00:00
|
|
|
msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out)
|
2014-05-09 01:00:56 +00:00
|
|
|
return len(out.Nodes) == 2, nil
|
|
|
|
}, func(err error) {
|
2013-12-12 18:48:36 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
2014-05-09 01:00:56 +00:00
|
|
|
})
|
2014-01-10 01:22:01 +00:00
|
|
|
|
|
|
|
// Server node is auto added from Serf
|
2014-07-23 08:34:03 +00:00
|
|
|
if out.Nodes[1].Node != s1.config.NodeName {
|
2013-12-12 18:48:36 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-07-23 08:34:03 +00:00
|
|
|
if out.Nodes[0].Node != "foo" {
|
2013-12-12 18:48:36 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-07-23 08:34:03 +00:00
|
|
|
if out.Nodes[0].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-04-19 00:26:59 +00:00
|
|
|
func TestCatalogListNodes_StaleRaad(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec1 := rpcClient(t, s1)
|
|
|
|
defer codec1.Close()
|
2014-04-19 00:26:59 +00:00
|
|
|
|
2014-04-19 00:48:50 +00:00
|
|
|
dir2, s2 := testServerDCBootstrap(t, "dc1", false)
|
2014-04-19 00:26:59 +00:00
|
|
|
defer os.RemoveAll(dir2)
|
|
|
|
defer s2.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec2 := rpcClient(t, s2)
|
|
|
|
defer codec2.Close()
|
2014-04-19 00:26:59 +00:00
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
|
|
|
testutil.WaitForLeader(t, s2.RPC, "dc1")
|
2014-05-07 21:47:16 +00:00
|
|
|
|
2014-04-19 00:26:59 +00:00
|
|
|
// Use the follower as the client
|
2015-10-13 23:43:52 +00:00
|
|
|
var codec rpc.ClientCodec
|
2014-04-19 00:26:59 +00:00
|
|
|
if !s1.IsLeader() {
|
2015-10-13 23:43:52 +00:00
|
|
|
codec = codec1
|
2014-04-19 00:26:59 +00:00
|
|
|
|
|
|
|
// Inject fake data on the follower!
|
2015-09-10 21:40:11 +00:00
|
|
|
s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"})
|
2014-04-19 00:26:59 +00:00
|
|
|
} else {
|
2015-10-13 23:43:52 +00:00
|
|
|
codec = codec2
|
2014-04-19 00:26:59 +00:00
|
|
|
|
|
|
|
// Inject fake data on the follower!
|
2015-09-10 21:40:11 +00:00
|
|
|
s2.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"})
|
2014-04-19 00:26:59 +00:00
|
|
|
}
|
|
|
|
|
2014-05-07 21:51:15 +00:00
|
|
|
args := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
QueryOptions: structs.QueryOptions{AllowStale: true},
|
|
|
|
}
|
2014-04-19 00:26:59 +00:00
|
|
|
var out structs.IndexedNodes
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out); err != nil {
|
2014-04-19 00:26:59 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-04-19 00:48:50 +00:00
|
|
|
found := false
|
|
|
|
for _, n := range out.Nodes {
|
|
|
|
if n.Node == "foo" {
|
|
|
|
found = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
t.Fatalf("failed to find foo")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.QueryMeta.LastContact == 0 {
|
|
|
|
t.Fatalf("should have a last contact time")
|
|
|
|
}
|
|
|
|
if !out.QueryMeta.KnownLeader {
|
|
|
|
t.Fatalf("should have known leader")
|
2014-04-21 19:08:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCatalogListNodes_ConsistentRead_Fail(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec1 := rpcClient(t, s1)
|
|
|
|
defer codec1.Close()
|
2014-04-21 19:08:00 +00:00
|
|
|
|
|
|
|
dir2, s2 := testServerDCBootstrap(t, "dc1", false)
|
|
|
|
defer os.RemoveAll(dir2)
|
|
|
|
defer s2.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec2 := rpcClient(t, s2)
|
|
|
|
defer codec2.Close()
|
2014-04-21 19:08:00 +00:00
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
|
|
|
testutil.WaitForLeader(t, s2.RPC, "dc1")
|
2014-04-21 19:08:00 +00:00
|
|
|
|
|
|
|
// Use the leader as the client, kill the follower
|
2015-10-13 23:43:52 +00:00
|
|
|
var codec rpc.ClientCodec
|
2014-04-21 19:08:00 +00:00
|
|
|
if s1.IsLeader() {
|
2015-10-13 23:43:52 +00:00
|
|
|
codec = codec1
|
2014-04-21 19:08:00 +00:00
|
|
|
s2.Shutdown()
|
|
|
|
} else {
|
2015-10-13 23:43:52 +00:00
|
|
|
codec = codec2
|
2014-04-21 19:08:00 +00:00
|
|
|
s1.Shutdown()
|
|
|
|
}
|
|
|
|
|
|
|
|
args := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
QueryOptions: structs.QueryOptions{RequireConsistent: true},
|
|
|
|
}
|
|
|
|
var out structs.IndexedNodes
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out); !strings.HasPrefix(err.Error(), "leadership lost") {
|
2014-04-21 19:08:00 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.QueryMeta.LastContact != 0 {
|
|
|
|
t.Fatalf("should not have a last contact time")
|
|
|
|
}
|
|
|
|
if out.QueryMeta.KnownLeader {
|
|
|
|
t.Fatalf("should have no known leader")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCatalogListNodes_ConsistentRead(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec1 := rpcClient(t, s1)
|
|
|
|
defer codec1.Close()
|
2014-04-21 19:08:00 +00:00
|
|
|
|
|
|
|
dir2, s2 := testServerDCBootstrap(t, "dc1", false)
|
|
|
|
defer os.RemoveAll(dir2)
|
|
|
|
defer s2.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec2 := rpcClient(t, s2)
|
|
|
|
defer codec2.Close()
|
2014-04-21 19:08:00 +00:00
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
|
|
|
testutil.WaitForLeader(t, s2.RPC, "dc1")
|
2014-04-21 19:08:00 +00:00
|
|
|
|
|
|
|
// Use the leader as the client, kill the follower
|
2015-10-13 23:43:52 +00:00
|
|
|
var codec rpc.ClientCodec
|
2014-04-21 19:08:00 +00:00
|
|
|
if s1.IsLeader() {
|
2015-10-13 23:43:52 +00:00
|
|
|
codec = codec1
|
2014-04-21 19:08:00 +00:00
|
|
|
} else {
|
2015-10-13 23:43:52 +00:00
|
|
|
codec = codec2
|
2014-04-21 19:08:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
args := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
QueryOptions: structs.QueryOptions{RequireConsistent: true},
|
|
|
|
}
|
|
|
|
var out structs.IndexedNodes
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out); err != nil {
|
2014-04-21 19:08:00 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.QueryMeta.LastContact != 0 {
|
|
|
|
t.Fatalf("should not have a last contact time")
|
|
|
|
}
|
|
|
|
if !out.QueryMeta.KnownLeader {
|
|
|
|
t.Fatalf("should have known leader")
|
2014-04-19 00:26:59 +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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(nil, s1)
|
|
|
|
defer codec.Close()
|
2014-02-01 20:16:33 +00:00
|
|
|
|
|
|
|
// Just add a node
|
2015-09-10 21:40:11 +00:00
|
|
|
s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"})
|
2014-02-01 20:16:33 +00:00
|
|
|
|
2014-02-05 19:00:43 +00:00
|
|
|
args := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
}
|
2014-02-01 20:16:33 +00:00
|
|
|
for i := 0; i < t.N; i++ {
|
2014-02-05 19:00:43 +00:00
|
|
|
var out structs.IndexedNodes
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListNodes", &args, &out); err != nil {
|
2014-02-01 20:16:33 +00:00
|
|
|
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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2013-12-12 19:07:14 +00:00
|
|
|
|
2014-02-05 19:00:43 +00:00
|
|
|
args := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
}
|
|
|
|
var out structs.IndexedServices
|
2015-10-13 23:43:52 +00:00
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out)
|
2013-12-12 19:07:14 +00:00
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2013-12-12 19:07:14 +00:00
|
|
|
|
|
|
|
// Just add a node
|
2015-09-10 21:40:11 +00:00
|
|
|
s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"})
|
|
|
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000})
|
2013-12-12 19:07:14 +00:00
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil {
|
2013-12-12 19:07:14 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-02-05 19:00:43 +00:00
|
|
|
if len(out.Services) != 2 {
|
2014-01-10 01:57:13 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-05-13 07:18:36 +00:00
|
|
|
for _, s := range out.Services {
|
|
|
|
if s == nil {
|
|
|
|
t.Fatalf("bad: %v", s)
|
|
|
|
}
|
|
|
|
}
|
2014-01-10 01:57:13 +00:00
|
|
|
// Consul service should auto-register
|
2014-04-03 19:03:10 +00:00
|
|
|
if _, ok := out.Services["consul"]; !ok {
|
2014-02-05 19:00:43 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
if len(out.Services["db"]) != 1 {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
if out.Services["db"][0] != "primary" {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCatalogListServices_Blocking(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2014-02-05 19:00:43 +00:00
|
|
|
|
|
|
|
args := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
}
|
|
|
|
var out structs.IndexedServices
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2014-02-05 19:00:43 +00:00
|
|
|
|
|
|
|
// Run the query
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil {
|
2014-02-05 19:00:43 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup a blocking query
|
|
|
|
args.MinQueryIndex = out.Index
|
|
|
|
args.MaxQueryTime = time.Second
|
|
|
|
|
|
|
|
// Async cause a change
|
|
|
|
start := time.Now()
|
|
|
|
go func() {
|
2014-05-09 00:36:25 +00:00
|
|
|
time.Sleep(100 * time.Millisecond)
|
2015-09-10 21:40:11 +00:00
|
|
|
s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"})
|
|
|
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000})
|
2014-02-05 19:00:43 +00:00
|
|
|
}()
|
|
|
|
|
|
|
|
// Re-run the query
|
|
|
|
out = structs.IndexedServices{}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil {
|
2014-02-05 19:00:43 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should block at least 100ms
|
2014-05-16 22:49:47 +00:00
|
|
|
if time.Now().Sub(start) < 100*time.Millisecond {
|
2014-02-05 19:00:43 +00:00
|
|
|
t.Fatalf("too fast")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the indexes
|
|
|
|
if out.Index != 2 {
|
2013-12-12 19:07:14 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-02-05 19:00:43 +00:00
|
|
|
|
|
|
|
// Should find the service
|
|
|
|
if len(out.Services) != 2 {
|
2013-12-12 19:07:14 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-02-05 19:00:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestCatalogListServices_Timeout(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2014-02-05 19:00:43 +00:00
|
|
|
|
|
|
|
args := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
}
|
|
|
|
var out structs.IndexedServices
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2014-02-05 19:00:43 +00:00
|
|
|
|
|
|
|
// Run the query
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil {
|
2014-02-05 19:00:43 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup a blocking query
|
|
|
|
args.MinQueryIndex = out.Index
|
2014-05-09 00:36:25 +00:00
|
|
|
args.MaxQueryTime = 100 * time.Millisecond
|
2014-02-05 19:00:43 +00:00
|
|
|
|
|
|
|
// Re-run the query
|
|
|
|
start := time.Now()
|
|
|
|
out = structs.IndexedServices{}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil {
|
2014-02-05 19:00:43 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should block at least 100ms
|
2014-05-16 22:49:47 +00:00
|
|
|
if time.Now().Sub(start) < 100*time.Millisecond {
|
2014-02-05 19:00:43 +00:00
|
|
|
t.Fatalf("too fast")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the indexes, should not change
|
|
|
|
if out.Index != args.MinQueryIndex {
|
2013-12-12 19:07:14 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
}
|
2013-12-12 19:37:19 +00:00
|
|
|
|
2014-04-21 18:57:39 +00:00
|
|
|
func TestCatalogListServices_Stale(t *testing.T) {
|
|
|
|
dir1, s1 := testServer(t)
|
|
|
|
defer os.RemoveAll(dir1)
|
|
|
|
defer s1.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2014-04-21 18:57:39 +00:00
|
|
|
|
|
|
|
args := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
}
|
|
|
|
args.AllowStale = true
|
|
|
|
var out structs.IndexedServices
|
|
|
|
|
|
|
|
// Inject a fake service
|
2015-09-10 21:40:11 +00:00
|
|
|
s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"})
|
|
|
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000})
|
2014-04-21 18:57:39 +00:00
|
|
|
|
|
|
|
// Run the query, do not wait for leader!
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &args, &out); err != nil {
|
2014-04-21 18:57:39 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should find the service
|
|
|
|
if len(out.Services) != 1 {
|
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should not have a leader! Stale read
|
|
|
|
if out.KnownLeader {
|
|
|
|
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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2013-12-12 19:37:19 +00:00
|
|
|
|
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,
|
|
|
|
}
|
2014-02-05 19:10:10 +00:00
|
|
|
var out structs.IndexedServiceNodes
|
2015-10-13 23:43:52 +00:00
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out)
|
2013-12-12 19:37:19 +00:00
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2013-12-12 19:37:19 +00:00
|
|
|
|
|
|
|
// Just add a node
|
2015-09-10 21:40:11 +00:00
|
|
|
s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"})
|
|
|
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000})
|
2013-12-12 19:37:19 +00:00
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out); err != nil {
|
2013-12-12 19:37:19 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-02-05 19:10:10 +00:00
|
|
|
if len(out.ServiceNodes) != 1 {
|
2013-12-12 19:37:19 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try with a filter
|
|
|
|
args.TagFilter = true
|
2014-02-05 19:10:10 +00:00
|
|
|
out = structs.IndexedServiceNodes{}
|
2013-12-12 19:37:19 +00:00
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &args, &out); err != nil {
|
2013-12-12 19:37:19 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
2014-02-05 19:10:10 +00:00
|
|
|
if len(out.ServiceNodes) != 0 {
|
2013-12-12 19:37:19 +00:00
|
|
|
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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2013-12-12 19:46:25 +00:00
|
|
|
|
2014-01-08 21:52:09 +00:00
|
|
|
args := structs.NodeSpecificRequest{
|
2013-12-12 19:46:25 +00:00
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: "foo",
|
|
|
|
}
|
2014-02-05 19:10:10 +00:00
|
|
|
var out structs.IndexedNodeServices
|
2015-10-13 23:43:52 +00:00
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &args, &out)
|
2013-12-12 19:46:25 +00:00
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2013-12-12 19:46:25 +00:00
|
|
|
|
|
|
|
// Just add a node
|
2015-09-10 21:40:11 +00:00
|
|
|
s1.fsm.State().EnsureNode(1, structs.Node{Node: "foo", Address: "127.0.0.1"})
|
|
|
|
s1.fsm.State().EnsureService(2, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000})
|
|
|
|
s1.fsm.State().EnsureService(3, "foo", &structs.NodeService{ID: "web", Service: "web", Tags: nil, Address: "127.0.0.1", Port: 80})
|
2013-12-12 19:46:25 +00:00
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &args, &out); err != nil {
|
2013-12-12 19:46:25 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2014-02-05 19:10:10 +00:00
|
|
|
if out.NodeServices.Node.Address != "127.0.0.1" {
|
2014-01-03 01:29:39 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-02-05 19:10:10 +00:00
|
|
|
if len(out.NodeServices.Services) != 2 {
|
2013-12-12 19:46:25 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-02-05 19:10:10 +00:00
|
|
|
services := out.NodeServices.Services
|
2014-04-03 19:03:10 +00:00
|
|
|
if !strContains(services["db"].Tags, "primary") || services["db"].Port != 5000 {
|
2013-12-12 19:46:25 +00:00
|
|
|
t.Fatalf("bad: %v", out)
|
|
|
|
}
|
2014-10-09 18:54:47 +00:00
|
|
|
if len(services["web"].Tags) != 0 || 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()
|
2015-10-13 23:43:52 +00:00
|
|
|
codec := rpcClient(t, s1)
|
|
|
|
defer codec.Close()
|
2014-01-01 02:31:17 +00:00
|
|
|
|
|
|
|
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",
|
2014-04-03 19:03:10 +00:00
|
|
|
Tags: nil,
|
2014-01-08 21:39:40 +00:00
|
|
|
Port: 8000,
|
|
|
|
},
|
2014-01-01 02:31:17 +00:00
|
|
|
}
|
|
|
|
var out struct{}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out)
|
2014-01-01 02:31:17 +00:00
|
|
|
if err == nil || err.Error() != "No cluster leader" {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
2014-01-01 02:31:17 +00:00
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil {
|
2014-01-01 02:31:17 +00:00
|
|
|
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",
|
|
|
|
}
|
2014-02-05 19:10:10 +00:00
|
|
|
var out2 structs.IndexedServiceNodes
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", query, &out2); err != nil {
|
2014-01-01 02:31:17 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the output
|
2014-02-05 19:10:10 +00:00
|
|
|
if len(out2.ServiceNodes) != 1 {
|
|
|
|
t.Fatalf("Bad: %v", out2)
|
2014-01-01 02:31:17 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-01 04:05:15 +00:00
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
func testACLFilterServer(t *testing.T) (dir, token string, srv *Server, codec rpc.ClientCodec) {
|
2015-06-11 20:23:49 +00:00
|
|
|
dir, srv = testServerWithConfig(t, func(c *Config) {
|
2015-06-11 05:14:58 +00:00
|
|
|
c.ACLDatacenter = "dc1"
|
|
|
|
c.ACLMasterToken = "root"
|
|
|
|
c.ACLDefaultPolicy = "deny"
|
|
|
|
})
|
|
|
|
|
2015-10-13 23:43:52 +00:00
|
|
|
codec = rpcClient(t, srv)
|
|
|
|
testutil.WaitForLeader(t, srv.RPC, "dc1")
|
2015-06-11 05:14:58 +00:00
|
|
|
|
|
|
|
// Create a new token
|
|
|
|
arg := structs.ACLRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
Op: structs.ACLSet,
|
|
|
|
ACL: structs.ACL{
|
|
|
|
Name: "User token",
|
|
|
|
Type: structs.ACLTypeClient,
|
|
|
|
Rules: testRegisterRules,
|
|
|
|
},
|
|
|
|
WriteRequest: structs.WriteRequest{Token: "root"},
|
|
|
|
}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &token); err != nil {
|
2015-06-11 05:14:58 +00:00
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a service
|
|
|
|
regArg := structs.RegisterRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: srv.config.NodeName,
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
ID: "foo",
|
|
|
|
Service: "foo",
|
|
|
|
},
|
|
|
|
Check: &structs.HealthCheck{
|
|
|
|
CheckID: "service:foo",
|
|
|
|
Name: "service:foo",
|
|
|
|
ServiceID: "foo",
|
2015-07-27 23:57:56 +00:00
|
|
|
Status: structs.HealthPassing,
|
2015-06-11 05:14:58 +00:00
|
|
|
},
|
|
|
|
WriteRequest: structs.WriteRequest{Token: "root"},
|
|
|
|
}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", ®Arg, nil); err != nil {
|
2015-06-11 05:14:58 +00:00
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register a service which should be denied
|
|
|
|
regArg = structs.RegisterRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: srv.config.NodeName,
|
|
|
|
Address: "127.0.0.1",
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
ID: "bar",
|
|
|
|
Service: "bar",
|
|
|
|
},
|
|
|
|
Check: &structs.HealthCheck{
|
|
|
|
CheckID: "service:bar",
|
|
|
|
Name: "service:bar",
|
|
|
|
ServiceID: "bar",
|
|
|
|
},
|
|
|
|
WriteRequest: structs.WriteRequest{Token: "root"},
|
|
|
|
}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", ®Arg, nil); err != nil {
|
2015-06-11 05:14:58 +00:00
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
2015-06-11 20:23:49 +00:00
|
|
|
return
|
|
|
|
}
|
2015-06-11 05:14:58 +00:00
|
|
|
|
2015-06-11 20:23:49 +00:00
|
|
|
func TestCatalog_ListServices_FilterACL(t *testing.T) {
|
2015-10-13 23:43:52 +00:00
|
|
|
dir, token, srv, codec := testACLFilterServer(t)
|
2015-06-11 20:23:49 +00:00
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
defer srv.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
defer codec.Close()
|
2015-06-11 20:23:49 +00:00
|
|
|
|
|
|
|
opt := structs.DCSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
QueryOptions: structs.QueryOptions{Token: token},
|
2015-06-11 05:14:58 +00:00
|
|
|
}
|
2015-06-11 20:23:49 +00:00
|
|
|
reply := structs.IndexedServices{}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ListServices", &opt, &reply); err != nil {
|
2015-06-11 20:23:49 +00:00
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if _, ok := reply.Services["foo"]; !ok {
|
|
|
|
t.Fatalf("bad: %#v", reply.Services)
|
|
|
|
}
|
|
|
|
if _, ok := reply.Services["bar"]; ok {
|
|
|
|
t.Fatalf("bad: %#v", reply.Services)
|
|
|
|
}
|
|
|
|
}
|
2015-06-11 05:14:58 +00:00
|
|
|
|
2015-06-11 20:23:49 +00:00
|
|
|
func TestCatalog_ServiceNodes_FilterACL(t *testing.T) {
|
2015-10-13 23:43:52 +00:00
|
|
|
dir, token, srv, codec := testACLFilterServer(t)
|
2015-06-11 20:23:49 +00:00
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
defer srv.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
defer codec.Close()
|
2015-06-11 20:23:49 +00:00
|
|
|
|
|
|
|
opt := structs.ServiceSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
ServiceName: "foo",
|
|
|
|
QueryOptions: structs.QueryOptions{Token: token},
|
|
|
|
}
|
|
|
|
reply := structs.IndexedServiceNodes{}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &opt, &reply); err != nil {
|
2015-06-11 20:23:49 +00:00
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, sn := range reply.ServiceNodes {
|
|
|
|
if sn.ServiceID == "foo" {
|
|
|
|
found = true
|
|
|
|
break
|
2015-06-11 05:14:58 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-11 20:23:49 +00:00
|
|
|
if !found {
|
|
|
|
t.Fatalf("bad: %#v", reply.ServiceNodes)
|
|
|
|
}
|
2015-06-11 05:14:58 +00:00
|
|
|
|
2015-06-11 20:23:49 +00:00
|
|
|
// Filters services we can't access
|
|
|
|
opt = structs.ServiceSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
ServiceName: "bar",
|
|
|
|
QueryOptions: structs.QueryOptions{Token: token},
|
|
|
|
}
|
|
|
|
reply = structs.IndexedServiceNodes{}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.ServiceNodes", &opt, &reply); err != nil {
|
2015-06-11 20:23:49 +00:00
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
for _, sn := range reply.ServiceNodes {
|
|
|
|
if sn.ServiceID == "bar" {
|
|
|
|
t.Fatalf("bad: %#v", reply.ServiceNodes)
|
2015-06-11 05:14:58 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-11 20:23:49 +00:00
|
|
|
}
|
2015-06-11 05:14:58 +00:00
|
|
|
|
2015-06-11 20:23:49 +00:00
|
|
|
func TestCatalog_NodeServices_FilterACL(t *testing.T) {
|
2015-10-13 23:43:52 +00:00
|
|
|
dir, token, srv, codec := testACLFilterServer(t)
|
2015-06-11 20:23:49 +00:00
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
defer srv.Shutdown()
|
2015-10-13 23:43:52 +00:00
|
|
|
defer codec.Close()
|
2015-06-11 20:23:49 +00:00
|
|
|
|
|
|
|
opt := structs.NodeSpecificRequest{
|
|
|
|
Datacenter: "dc1",
|
|
|
|
Node: srv.config.NodeName,
|
|
|
|
QueryOptions: structs.QueryOptions{Token: token},
|
|
|
|
}
|
|
|
|
reply := structs.IndexedNodeServices{}
|
2015-10-13 23:43:52 +00:00
|
|
|
if err := msgpackrpc.CallWithCodec(codec, "Catalog.NodeServices", &opt, &reply); err != nil {
|
2015-06-11 20:23:49 +00:00
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, svc := range reply.NodeServices.Services {
|
|
|
|
if svc.ID == "bar" {
|
|
|
|
t.Fatalf("bad: %#v", reply.NodeServices.Services)
|
2015-06-11 05:14:58 +00:00
|
|
|
}
|
2015-06-11 20:23:49 +00:00
|
|
|
if svc.ID == "foo" {
|
|
|
|
found = true
|
|
|
|
break
|
2015-06-11 05:14:58 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-11 20:23:49 +00:00
|
|
|
if !found {
|
|
|
|
t.Fatalf("bad: %#v", reply.NodeServices)
|
|
|
|
}
|
2015-06-11 05:14:58 +00:00
|
|
|
}
|
|
|
|
|
2014-12-01 04:05:15 +00:00
|
|
|
var testRegisterRules = `
|
|
|
|
service "foo" {
|
2014-12-01 04:10:42 +00:00
|
|
|
policy = "write"
|
2014-12-01 04:05:15 +00:00
|
|
|
}
|
|
|
|
`
|