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 }