github.com/hernad/nomad@v1.6.112/nomad/client_rpc_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package nomad
     5  
     6  import (
     7  	"net"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/hernad/nomad/ci"
    12  	"github.com/hernad/nomad/client"
    13  	"github.com/hernad/nomad/client/config"
    14  	"github.com/hernad/nomad/helper/uuid"
    15  	"github.com/hernad/nomad/nomad/structs"
    16  	"github.com/hernad/nomad/testutil"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  type namedConnWrapper struct {
    21  	net.Conn
    22  	name string
    23  }
    24  
    25  type namedAddr string
    26  
    27  func (n namedAddr) String() string  { return string(n) }
    28  func (n namedAddr) Network() string { return string(n) }
    29  
    30  func (n namedConnWrapper) LocalAddr() net.Addr {
    31  	return namedAddr(n.name)
    32  }
    33  
    34  func TestServer_removeNodeConn_differentAddrs(t *testing.T) {
    35  	ci.Parallel(t)
    36  	require := require.New(t)
    37  
    38  	s1, cleanupS1 := TestServer(t, nil)
    39  	defer cleanupS1()
    40  	testutil.WaitForLeader(t, s1.RPC)
    41  
    42  	p1, p2 := net.Pipe()
    43  	w1 := namedConnWrapper{
    44  		Conn: p1,
    45  		name: "a",
    46  	}
    47  	w2 := namedConnWrapper{
    48  		Conn: p2,
    49  		name: "b",
    50  	}
    51  
    52  	// Add the connections
    53  	nodeID := uuid.Generate()
    54  	ctx1 := &RPCContext{
    55  		Conn:   w1,
    56  		NodeID: nodeID,
    57  	}
    58  	ctx2 := &RPCContext{
    59  		Conn:   w2,
    60  		NodeID: nodeID,
    61  	}
    62  
    63  	s1.addNodeConn(ctx1)
    64  	s1.addNodeConn(ctx2)
    65  	require.Len(s1.connectedNodes(), 1)
    66  	require.Len(s1.nodeConns[nodeID], 2)
    67  
    68  	// Check that the value is the second conn.
    69  	state, ok := s1.getNodeConn(nodeID)
    70  	require.True(ok)
    71  	require.Equal(state.Ctx.Conn.LocalAddr().String(), w2.name)
    72  
    73  	// Delete the first
    74  	s1.removeNodeConn(ctx1)
    75  	require.Len(s1.connectedNodes(), 1)
    76  	require.Len(s1.nodeConns[nodeID], 1)
    77  
    78  	// Check that the value is the second conn.
    79  	state, ok = s1.getNodeConn(nodeID)
    80  	require.True(ok)
    81  	require.Equal(state.Ctx.Conn.LocalAddr().String(), w2.name)
    82  
    83  	// Delete the second
    84  	s1.removeNodeConn(ctx2)
    85  	require.Len(s1.connectedNodes(), 0)
    86  
    87  	_, ok = s1.getNodeConn(nodeID)
    88  	require.False(ok)
    89  }
    90  
    91  func TestServerWithNodeConn_NoPath(t *testing.T) {
    92  	ci.Parallel(t)
    93  	require := require.New(t)
    94  
    95  	s1, cleanupS1 := TestServer(t, func(c *Config) {
    96  		c.BootstrapExpect = 2
    97  	})
    98  	defer cleanupS1()
    99  	s2, cleanupS2 := TestServer(t, func(c *Config) {
   100  		c.BootstrapExpect = 2
   101  	})
   102  	defer cleanupS2()
   103  	TestJoin(t, s1, s2)
   104  	testutil.WaitForLeader(t, s1.RPC)
   105  	testutil.WaitForLeader(t, s2.RPC)
   106  
   107  	nodeID := uuid.Generate()
   108  	srv, err := s1.serverWithNodeConn(nodeID, s1.Region())
   109  	require.Nil(srv)
   110  	require.EqualError(err, structs.ErrNoNodeConn.Error())
   111  }
   112  
   113  func TestServerWithNodeConn_NoPath_Region(t *testing.T) {
   114  	ci.Parallel(t)
   115  	require := require.New(t)
   116  
   117  	s1, cleanupS1 := TestServer(t, nil)
   118  	defer cleanupS1()
   119  	testutil.WaitForLeader(t, s1.RPC)
   120  
   121  	nodeID := uuid.Generate()
   122  	srv, err := s1.serverWithNodeConn(nodeID, "fake-region")
   123  	require.Nil(srv)
   124  	require.EqualError(err, structs.ErrNoRegionPath.Error())
   125  }
   126  
   127  func TestServerWithNodeConn_Path(t *testing.T) {
   128  	ci.Parallel(t)
   129  	require := require.New(t)
   130  
   131  	s1, cleanupS1 := TestServer(t, func(c *Config) {
   132  		c.BootstrapExpect = 2
   133  	})
   134  	defer cleanupS1()
   135  	s2, cleanupS2 := TestServer(t, func(c *Config) {
   136  		c.BootstrapExpect = 2
   137  	})
   138  	defer cleanupS2()
   139  	TestJoin(t, s1, s2)
   140  	testutil.WaitForLeader(t, s1.RPC)
   141  	testutil.WaitForLeader(t, s2.RPC)
   142  
   143  	// Create a fake connection for the node on server 2
   144  	nodeID := uuid.Generate()
   145  	s2.addNodeConn(&RPCContext{
   146  		NodeID: nodeID,
   147  	})
   148  
   149  	srv, err := s1.serverWithNodeConn(nodeID, s1.Region())
   150  	require.NotNil(srv)
   151  	require.Equal(srv.Addr.String(), s2.config.RPCAddr.String())
   152  	require.Nil(err)
   153  }
   154  
   155  func TestServerWithNodeConn_Path_Region(t *testing.T) {
   156  	ci.Parallel(t)
   157  	require := require.New(t)
   158  
   159  	s1, cleanupS1 := TestServer(t, nil)
   160  	defer cleanupS1()
   161  	s2, cleanupS2 := TestServer(t, func(c *Config) {
   162  		c.Region = "two"
   163  	})
   164  	defer cleanupS2()
   165  	TestJoin(t, s1, s2)
   166  	testutil.WaitForLeader(t, s1.RPC)
   167  	testutil.WaitForLeader(t, s2.RPC)
   168  
   169  	// Create a fake connection for the node on server 2
   170  	nodeID := uuid.Generate()
   171  	s2.addNodeConn(&RPCContext{
   172  		NodeID: nodeID,
   173  	})
   174  
   175  	srv, err := s1.serverWithNodeConn(nodeID, s2.Region())
   176  	require.NotNil(srv)
   177  	require.Equal(srv.Addr.String(), s2.config.RPCAddr.String())
   178  	require.Nil(err)
   179  }
   180  
   181  func TestServerWithNodeConn_Path_Newest(t *testing.T) {
   182  	ci.Parallel(t)
   183  	require := require.New(t)
   184  
   185  	s1, cleanupS1 := TestServer(t, func(c *Config) {
   186  		c.BootstrapExpect = 3
   187  	})
   188  	defer cleanupS1()
   189  	s2, cleanupS2 := TestServer(t, func(c *Config) {
   190  		c.BootstrapExpect = 3
   191  	})
   192  	defer cleanupS2()
   193  	s3, cleanupS3 := TestServer(t, func(c *Config) {
   194  		c.BootstrapExpect = 3
   195  	})
   196  	defer cleanupS3()
   197  	TestJoin(t, s1, s2, s3)
   198  	testutil.WaitForLeader(t, s1.RPC)
   199  	testutil.WaitForLeader(t, s2.RPC)
   200  	testutil.WaitForLeader(t, s3.RPC)
   201  
   202  	// Create a fake connection for the node on server 2 and 3
   203  	nodeID := uuid.Generate()
   204  	s2.addNodeConn(&RPCContext{
   205  		NodeID: nodeID,
   206  	})
   207  	s3.addNodeConn(&RPCContext{
   208  		NodeID: nodeID,
   209  	})
   210  
   211  	srv, err := s1.serverWithNodeConn(nodeID, s1.Region())
   212  	require.NotNil(srv)
   213  	require.Equal(srv.Addr.String(), s3.config.RPCAddr.String())
   214  	require.Nil(err)
   215  }
   216  
   217  func TestServerWithNodeConn_PathAndErr(t *testing.T) {
   218  	ci.Parallel(t)
   219  	require := require.New(t)
   220  
   221  	s1, cleanupS1 := TestServer(t, func(c *Config) {
   222  		c.BootstrapExpect = 3
   223  	})
   224  	defer cleanupS1()
   225  	s2, cleanupS2 := TestServer(t, func(c *Config) {
   226  		c.BootstrapExpect = 3
   227  	})
   228  	defer cleanupS2()
   229  	s3, cleanupS3 := TestServer(t, func(c *Config) {
   230  		c.BootstrapExpect = 3
   231  	})
   232  	defer cleanupS3()
   233  	TestJoin(t, s1, s2, s3)
   234  	testutil.WaitForLeader(t, s1.RPC)
   235  	testutil.WaitForLeader(t, s2.RPC)
   236  	testutil.WaitForLeader(t, s3.RPC)
   237  
   238  	// Create a fake connection for the node on server 2
   239  	nodeID := uuid.Generate()
   240  	s2.addNodeConn(&RPCContext{
   241  		NodeID: nodeID,
   242  	})
   243  
   244  	// Shutdown the RPC layer for server 3
   245  	s3.rpcListener.Close()
   246  
   247  	srv, err := s1.serverWithNodeConn(nodeID, s1.Region())
   248  	require.NotNil(srv)
   249  	require.Equal(srv.Addr.String(), s2.config.RPCAddr.String())
   250  	require.Nil(err)
   251  }
   252  
   253  func TestServerWithNodeConn_NoPathAndErr(t *testing.T) {
   254  	ci.Parallel(t)
   255  	require := require.New(t)
   256  
   257  	s1, cleanupS1 := TestServer(t, func(c *Config) {
   258  		c.BootstrapExpect = 3
   259  	})
   260  	defer cleanupS1()
   261  	s2, cleanupS2 := TestServer(t, func(c *Config) {
   262  		c.BootstrapExpect = 3
   263  	})
   264  	defer cleanupS2()
   265  	s3, cleanupS3 := TestServer(t, func(c *Config) {
   266  		c.BootstrapExpect = 3
   267  	})
   268  	defer cleanupS3()
   269  	TestJoin(t, s1, s2, s3)
   270  	testutil.WaitForLeader(t, s1.RPC)
   271  	testutil.WaitForLeader(t, s2.RPC)
   272  	testutil.WaitForLeader(t, s3.RPC)
   273  
   274  	// Shutdown the RPC layer for server 3
   275  	s3.rpcListener.Close()
   276  
   277  	srv, err := s1.serverWithNodeConn(uuid.Generate(), s1.Region())
   278  	require.Nil(srv)
   279  	require.NotNil(err)
   280  
   281  	// the exact error seems to be dependent on timing and raft protocol version
   282  	if !strings.Contains(err.Error(), "failed querying") && !strings.Contains(err.Error(), "No path to node") {
   283  		require.Contains(err.Error(), "failed querying")
   284  	}
   285  }
   286  
   287  func TestNodeStreamingRpc_badEndpoint(t *testing.T) {
   288  	ci.Parallel(t)
   289  	require := require.New(t)
   290  	s1, cleanupS1 := TestServer(t, nil)
   291  	defer cleanupS1()
   292  	testutil.WaitForLeader(t, s1.RPC)
   293  
   294  	c, cleanupC := client.TestClient(t, func(c *config.Config) {
   295  		c.Servers = []string{s1.config.RPCAddr.String()}
   296  	})
   297  	defer cleanupC()
   298  
   299  	// Wait for the client to connect
   300  	testutil.WaitForResult(func() (bool, error) {
   301  		nodes := s1.connectedNodes()
   302  		return len(nodes) == 1, nil
   303  	}, func(err error) {
   304  		t.Fatalf("should have a clients")
   305  	})
   306  
   307  	state, ok := s1.getNodeConn(c.NodeID())
   308  	require.True(ok)
   309  
   310  	conn, err := NodeStreamingRpc(state.Session, "Bogus")
   311  	require.Nil(conn)
   312  	require.NotNil(err)
   313  	require.Contains(err.Error(), "Bogus")
   314  	require.True(structs.IsErrUnknownMethod(err))
   315  }