github.com/clly/consul@v1.4.5/agent/consul/internal_endpoint_test.go (about)

     1  package consul
     2  
     3  import (
     4  	"encoding/base64"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/consul/acl"
     9  	"github.com/hashicorp/consul/agent/structs"
    10  	"github.com/hashicorp/consul/api"
    11  	"github.com/hashicorp/consul/lib"
    12  	"github.com/hashicorp/consul/testrpc"
    13  	"github.com/hashicorp/net-rpc-msgpackrpc"
    14  )
    15  
    16  func TestInternal_NodeInfo(t *testing.T) {
    17  	t.Parallel()
    18  	dir1, s1 := testServer(t)
    19  	defer os.RemoveAll(dir1)
    20  	defer s1.Shutdown()
    21  	codec := rpcClient(t, s1)
    22  	defer codec.Close()
    23  
    24  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
    25  
    26  	arg := structs.RegisterRequest{
    27  		Datacenter: "dc1",
    28  		Node:       "foo",
    29  		Address:    "127.0.0.1",
    30  		Service: &structs.NodeService{
    31  			ID:      "db",
    32  			Service: "db",
    33  			Tags:    []string{"master"},
    34  		},
    35  		Check: &structs.HealthCheck{
    36  			Name:      "db connect",
    37  			Status:    api.HealthPassing,
    38  			ServiceID: "db",
    39  		},
    40  	}
    41  	var out struct{}
    42  	if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil {
    43  		t.Fatalf("err: %v", err)
    44  	}
    45  
    46  	var out2 structs.IndexedNodeDump
    47  	req := structs.NodeSpecificRequest{
    48  		Datacenter: "dc1",
    49  		Node:       "foo",
    50  	}
    51  	if err := msgpackrpc.CallWithCodec(codec, "Internal.NodeInfo", &req, &out2); err != nil {
    52  		t.Fatalf("err: %v", err)
    53  	}
    54  
    55  	nodes := out2.Dump
    56  	if len(nodes) != 1 {
    57  		t.Fatalf("Bad: %v", nodes)
    58  	}
    59  	if nodes[0].Node != "foo" {
    60  		t.Fatalf("Bad: %v", nodes[0])
    61  	}
    62  	if !lib.StrContains(nodes[0].Services[0].Tags, "master") {
    63  		t.Fatalf("Bad: %v", nodes[0])
    64  	}
    65  	if nodes[0].Checks[0].Status != api.HealthPassing {
    66  		t.Fatalf("Bad: %v", nodes[0])
    67  	}
    68  }
    69  
    70  func TestInternal_NodeDump(t *testing.T) {
    71  	t.Parallel()
    72  	dir1, s1 := testServer(t)
    73  	defer os.RemoveAll(dir1)
    74  	defer s1.Shutdown()
    75  	codec := rpcClient(t, s1)
    76  	defer codec.Close()
    77  
    78  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
    79  
    80  	arg := structs.RegisterRequest{
    81  		Datacenter: "dc1",
    82  		Node:       "foo",
    83  		Address:    "127.0.0.1",
    84  		Service: &structs.NodeService{
    85  			ID:      "db",
    86  			Service: "db",
    87  			Tags:    []string{"master"},
    88  		},
    89  		Check: &structs.HealthCheck{
    90  			Name:      "db connect",
    91  			Status:    api.HealthPassing,
    92  			ServiceID: "db",
    93  		},
    94  	}
    95  	var out struct{}
    96  	if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil {
    97  		t.Fatalf("err: %v", err)
    98  	}
    99  
   100  	arg = structs.RegisterRequest{
   101  		Datacenter: "dc1",
   102  		Node:       "bar",
   103  		Address:    "127.0.0.2",
   104  		Service: &structs.NodeService{
   105  			ID:      "db",
   106  			Service: "db",
   107  			Tags:    []string{"slave"},
   108  		},
   109  		Check: &structs.HealthCheck{
   110  			Name:      "db connect",
   111  			Status:    api.HealthWarning,
   112  			ServiceID: "db",
   113  		},
   114  	}
   115  	if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil {
   116  		t.Fatalf("err: %v", err)
   117  	}
   118  
   119  	var out2 structs.IndexedNodeDump
   120  	req := structs.DCSpecificRequest{
   121  		Datacenter: "dc1",
   122  	}
   123  	if err := msgpackrpc.CallWithCodec(codec, "Internal.NodeDump", &req, &out2); err != nil {
   124  		t.Fatalf("err: %v", err)
   125  	}
   126  
   127  	nodes := out2.Dump
   128  	if len(nodes) != 3 {
   129  		t.Fatalf("Bad: %v", nodes)
   130  	}
   131  
   132  	var foundFoo, foundBar bool
   133  	for _, node := range nodes {
   134  		switch node.Node {
   135  		case "foo":
   136  			foundFoo = true
   137  			if !lib.StrContains(node.Services[0].Tags, "master") {
   138  				t.Fatalf("Bad: %v", nodes[0])
   139  			}
   140  			if node.Checks[0].Status != api.HealthPassing {
   141  				t.Fatalf("Bad: %v", nodes[0])
   142  			}
   143  
   144  		case "bar":
   145  			foundBar = true
   146  			if !lib.StrContains(node.Services[0].Tags, "slave") {
   147  				t.Fatalf("Bad: %v", nodes[1])
   148  			}
   149  			if node.Checks[0].Status != api.HealthWarning {
   150  				t.Fatalf("Bad: %v", nodes[1])
   151  			}
   152  
   153  		default:
   154  			continue
   155  		}
   156  	}
   157  	if !foundFoo || !foundBar {
   158  		t.Fatalf("missing foo or bar")
   159  	}
   160  }
   161  
   162  func TestInternal_KeyringOperation(t *testing.T) {
   163  	t.Parallel()
   164  	key1 := "H1dfkSZOVnP/JUnaBfTzXg=="
   165  	keyBytes1, err := base64.StdEncoding.DecodeString(key1)
   166  	if err != nil {
   167  		t.Fatalf("err: %s", err)
   168  	}
   169  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
   170  		c.SerfLANConfig.MemberlistConfig.SecretKey = keyBytes1
   171  		c.SerfWANConfig.MemberlistConfig.SecretKey = keyBytes1
   172  	})
   173  	defer os.RemoveAll(dir1)
   174  	defer s1.Shutdown()
   175  	codec := rpcClient(t, s1)
   176  	defer codec.Close()
   177  
   178  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   179  
   180  	var out structs.KeyringResponses
   181  	req := structs.KeyringRequest{
   182  		Operation:  structs.KeyringList,
   183  		Datacenter: "dc1",
   184  	}
   185  	if err := msgpackrpc.CallWithCodec(codec, "Internal.KeyringOperation", &req, &out); err != nil {
   186  		t.Fatalf("err: %v", err)
   187  	}
   188  
   189  	// Two responses (local lan/wan pools) from single-node cluster
   190  	if len(out.Responses) != 2 {
   191  		t.Fatalf("bad: %#v", out)
   192  	}
   193  	if _, ok := out.Responses[0].Keys[key1]; !ok {
   194  		t.Fatalf("bad: %#v", out)
   195  	}
   196  	wanResp, lanResp := 0, 0
   197  	for _, resp := range out.Responses {
   198  		if resp.WAN {
   199  			wanResp++
   200  		} else {
   201  			lanResp++
   202  		}
   203  	}
   204  	if lanResp != 1 || wanResp != 1 {
   205  		t.Fatalf("should have one lan and one wan response")
   206  	}
   207  
   208  	// Start a second agent to test cross-dc queries
   209  	dir2, s2 := testServerWithConfig(t, func(c *Config) {
   210  		c.SerfLANConfig.MemberlistConfig.SecretKey = keyBytes1
   211  		c.SerfWANConfig.MemberlistConfig.SecretKey = keyBytes1
   212  		c.Datacenter = "dc2"
   213  	})
   214  	defer os.RemoveAll(dir2)
   215  	defer s2.Shutdown()
   216  
   217  	// Try to join
   218  	joinWAN(t, s2, s1)
   219  
   220  	var out2 structs.KeyringResponses
   221  	req2 := structs.KeyringRequest{
   222  		Operation: structs.KeyringList,
   223  	}
   224  	if err := msgpackrpc.CallWithCodec(codec, "Internal.KeyringOperation", &req2, &out2); err != nil {
   225  		t.Fatalf("err: %v", err)
   226  	}
   227  
   228  	// 3 responses (one from each DC LAN, one from WAN) in two-node cluster
   229  	if len(out2.Responses) != 3 {
   230  		t.Fatalf("bad: %#v", out)
   231  	}
   232  	wanResp, lanResp = 0, 0
   233  	for _, resp := range out2.Responses {
   234  		if resp.WAN {
   235  			wanResp++
   236  		} else {
   237  			lanResp++
   238  		}
   239  	}
   240  	if lanResp != 2 || wanResp != 1 {
   241  		t.Fatalf("should have two lan and one wan response")
   242  	}
   243  }
   244  
   245  func TestInternal_NodeInfo_FilterACL(t *testing.T) {
   246  	t.Parallel()
   247  	dir, token, srv, codec := testACLFilterServer(t)
   248  	defer os.RemoveAll(dir)
   249  	defer srv.Shutdown()
   250  	defer codec.Close()
   251  
   252  	opt := structs.NodeSpecificRequest{
   253  		Datacenter:   "dc1",
   254  		Node:         srv.config.NodeName,
   255  		QueryOptions: structs.QueryOptions{Token: token},
   256  	}
   257  	reply := structs.IndexedNodeDump{}
   258  	if err := msgpackrpc.CallWithCodec(codec, "Health.NodeChecks", &opt, &reply); err != nil {
   259  		t.Fatalf("err: %s", err)
   260  	}
   261  	for _, info := range reply.Dump {
   262  		found := false
   263  		for _, chk := range info.Checks {
   264  			if chk.ServiceName == "foo" {
   265  				found = true
   266  			}
   267  			if chk.ServiceName == "bar" {
   268  				t.Fatalf("bad: %#v", info.Checks)
   269  			}
   270  		}
   271  		if !found {
   272  			t.Fatalf("bad: %#v", info.Checks)
   273  		}
   274  
   275  		found = false
   276  		for _, svc := range info.Services {
   277  			if svc.Service == "foo" {
   278  				found = true
   279  			}
   280  			if svc.Service == "bar" {
   281  				t.Fatalf("bad: %#v", info.Services)
   282  			}
   283  		}
   284  		if !found {
   285  			t.Fatalf("bad: %#v", info.Services)
   286  		}
   287  	}
   288  
   289  	// We've already proven that we call the ACL filtering function so we
   290  	// test node filtering down in acl.go for node cases. This also proves
   291  	// that we respect the version 8 ACL flag, since the test server sets
   292  	// that to false (the regression value of *not* changing this is better
   293  	// for now until we change the sense of the version 8 ACL flag).
   294  }
   295  
   296  func TestInternal_NodeDump_FilterACL(t *testing.T) {
   297  	t.Parallel()
   298  	dir, token, srv, codec := testACLFilterServer(t)
   299  	defer os.RemoveAll(dir)
   300  	defer srv.Shutdown()
   301  	defer codec.Close()
   302  
   303  	opt := structs.DCSpecificRequest{
   304  		Datacenter:   "dc1",
   305  		QueryOptions: structs.QueryOptions{Token: token},
   306  	}
   307  	reply := structs.IndexedNodeDump{}
   308  	if err := msgpackrpc.CallWithCodec(codec, "Health.NodeChecks", &opt, &reply); err != nil {
   309  		t.Fatalf("err: %s", err)
   310  	}
   311  	for _, info := range reply.Dump {
   312  		found := false
   313  		for _, chk := range info.Checks {
   314  			if chk.ServiceName == "foo" {
   315  				found = true
   316  			}
   317  			if chk.ServiceName == "bar" {
   318  				t.Fatalf("bad: %#v", info.Checks)
   319  			}
   320  		}
   321  		if !found {
   322  			t.Fatalf("bad: %#v", info.Checks)
   323  		}
   324  
   325  		found = false
   326  		for _, svc := range info.Services {
   327  			if svc.Service == "foo" {
   328  				found = true
   329  			}
   330  			if svc.Service == "bar" {
   331  				t.Fatalf("bad: %#v", info.Services)
   332  			}
   333  		}
   334  		if !found {
   335  			t.Fatalf("bad: %#v", info.Services)
   336  		}
   337  	}
   338  
   339  	// We've already proven that we call the ACL filtering function so we
   340  	// test node filtering down in acl.go for node cases. This also proves
   341  	// that we respect the version 8 ACL flag, since the test server sets
   342  	// that to false (the regression value of *not* changing this is better
   343  	// for now until we change the sense of the version 8 ACL flag).
   344  }
   345  
   346  func TestInternal_EventFire_Token(t *testing.T) {
   347  	t.Parallel()
   348  	dir, srv := testServerWithConfig(t, func(c *Config) {
   349  		c.ACLDatacenter = "dc1"
   350  		c.ACLsEnabled = true
   351  		c.ACLMasterToken = "root"
   352  		c.ACLDownPolicy = "deny"
   353  		c.ACLDefaultPolicy = "deny"
   354  	})
   355  	defer os.RemoveAll(dir)
   356  	defer srv.Shutdown()
   357  
   358  	codec := rpcClient(t, srv)
   359  	defer codec.Close()
   360  
   361  	testrpc.WaitForLeader(t, srv.RPC, "dc1")
   362  
   363  	// No token is rejected
   364  	event := structs.EventFireRequest{
   365  		Name:       "foo",
   366  		Datacenter: "dc1",
   367  		Payload:    []byte("nope"),
   368  	}
   369  	err := msgpackrpc.CallWithCodec(codec, "Internal.EventFire", &event, nil)
   370  	if !acl.IsErrPermissionDenied(err) {
   371  		t.Fatalf("bad: %s", err)
   372  	}
   373  
   374  	// Root token is allowed to fire
   375  	event.Token = "root"
   376  	err = msgpackrpc.CallWithCodec(codec, "Internal.EventFire", &event, nil)
   377  	if err != nil {
   378  		t.Fatalf("err: %s", err)
   379  	}
   380  }