github.com/manicqin/nomad@v0.9.5/nomad/client_rpc_test.go (about)

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