get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/test/leafnode_test.go (about) 1 // Copyright 2019-2020 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package test 15 16 import ( 17 "bytes" 18 "crypto/tls" 19 "crypto/x509" 20 "encoding/json" 21 "fmt" 22 "math/rand" 23 "net" 24 "net/url" 25 "os" 26 "strconv" 27 "strings" 28 "sync" 29 "sync/atomic" 30 "testing" 31 "time" 32 33 "get.pme.sh/pnats/logger" 34 "get.pme.sh/pnats/server" 35 "github.com/nats-io/jwt/v2" 36 "github.com/nats-io/nats.go" 37 "github.com/nats-io/nkeys" 38 "github.com/nats-io/nuid" 39 ) 40 41 func createLeafConn(t tLogger, host string, port int) net.Conn { 42 return createClientConn(t, host, port) 43 } 44 45 func testDefaultOptionsForLeafNodes() *server.Options { 46 o := DefaultTestOptions 47 o.Port = -1 48 o.LeafNode.Host = o.Host 49 o.LeafNode.Port = -1 50 o.NoSystemAccount = true 51 return &o 52 } 53 54 func runLeafServer() (*server.Server, *server.Options) { 55 o := testDefaultOptionsForLeafNodes() 56 return RunServer(o), o 57 } 58 59 func runLeafServerOnPort(port int) (*server.Server, *server.Options) { 60 o := testDefaultOptionsForLeafNodes() 61 o.LeafNode.Port = port 62 return RunServer(o), o 63 } 64 65 func runSolicitLeafServer(lso *server.Options) (*server.Server, *server.Options) { 66 return runSolicitLeafServerToURL(fmt.Sprintf("nats-leaf://%s:%d", lso.LeafNode.Host, lso.LeafNode.Port)) 67 } 68 69 func runSolicitLeafServerToURL(surl string) (*server.Server, *server.Options) { 70 o := DefaultTestOptions 71 o.Port = -1 72 o.NoSystemAccount = true 73 rurl, _ := url.Parse(surl) 74 o.LeafNode.Remotes = []*server.RemoteLeafOpts{{URLs: []*url.URL{rurl}}} 75 o.LeafNode.ReconnectInterval = 100 * time.Millisecond 76 return RunServer(&o), &o 77 } 78 79 func TestLeafNodeInfo(t *testing.T) { 80 s, opts := runLeafServer() 81 defer s.Shutdown() 82 83 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 84 defer lc.Close() 85 86 info := checkInfoMsg(t, lc) 87 if !info.AuthRequired { 88 t.Fatalf("AuthRequired should always be true for leaf nodes") 89 } 90 // By default headers should be true. 91 if !info.Headers { 92 t.Fatalf("Expected to have headers on by default") 93 } 94 95 sendProto(t, lc, "CONNECT {}\r\n") 96 checkLeafNodeConnected(t, s) 97 98 // Now close connection, make sure we are doing the right accounting in the server. 99 lc.Close() 100 101 checkLeafNodeConnections(t, s, 0) 102 } 103 104 func TestLeafNodeSplitBuffer(t *testing.T) { 105 s, opts := runLeafServer() 106 defer s.Shutdown() 107 108 nc, err := nats.Connect(s.ClientURL()) 109 if err != nil { 110 t.Fatalf("Error on connect: %v", err) 111 } 112 defer nc.Close() 113 114 nc.QueueSubscribe("foo", "bar", func(m *nats.Msg) { 115 m.Respond([]byte("ok")) 116 }) 117 nc.Flush() 118 119 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 120 defer lc.Close() 121 sendProto(t, lc, "CONNECT {}\r\n") 122 checkLeafNodeConnected(t, s) 123 124 leafSend, leafExpect := setupLeaf(t, lc, 2) 125 126 leafSend("LS+ reply\r\nPING\r\n") 127 leafExpect(pongRe) 128 129 leafSend("LMSG foo ") 130 time.Sleep(time.Millisecond) 131 leafSend("+ reply bar 2\r\n") 132 time.Sleep(time.Millisecond) 133 leafSend("OK\r") 134 time.Sleep(time.Millisecond) 135 leafSend("\n") 136 leafExpect(lmsgRe) 137 } 138 139 func TestNumLeafNodes(t *testing.T) { 140 s, opts := runLeafServer() 141 defer s.Shutdown() 142 143 createNewLeafNode := func() net.Conn { 144 t.Helper() 145 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 146 checkInfoMsg(t, lc) 147 sendProto(t, lc, "CONNECT {}\r\n") 148 return lc 149 } 150 checkLeafNodeConnections(t, s, 0) 151 152 lc1 := createNewLeafNode() 153 defer lc1.Close() 154 checkLeafNodeConnections(t, s, 1) 155 156 lc2 := createNewLeafNode() 157 defer lc2.Close() 158 checkLeafNodeConnections(t, s, 2) 159 160 // Now test remove works. 161 lc1.Close() 162 checkLeafNodeConnections(t, s, 1) 163 164 lc2.Close() 165 checkLeafNodeConnections(t, s, 0) 166 } 167 168 func TestLeafNodeRequiresConnect(t *testing.T) { 169 opts := testDefaultOptionsForLeafNodes() 170 opts.LeafNode.AuthTimeout = 0.001 171 s := RunServer(opts) 172 defer s.Shutdown() 173 174 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 175 defer lc.Close() 176 177 info := checkInfoMsg(t, lc) 178 if !info.AuthRequired { 179 t.Fatalf("Expected AuthRequired to force CONNECT") 180 } 181 if info.TLSRequired { 182 t.Fatalf("Expected TLSRequired to be false") 183 } 184 if info.TLSVerify { 185 t.Fatalf("Expected TLSVerify to be false") 186 } 187 188 // Now wait and make sure we get disconnected. 189 errBuf := expectResult(t, lc, errRe) 190 191 if !strings.Contains(string(errBuf), "Authentication Timeout") { 192 t.Fatalf("Authentication Timeout response incorrect: %q", errBuf) 193 } 194 expectDisconnect(t, lc) 195 } 196 197 func setupLeaf(t *testing.T, lc net.Conn, expectedSubs int) (sendFun, expectFun) { 198 t.Helper() 199 send, expect := setupConn(t, lc) 200 // A loop detection subscription is sent, so consume this here, along 201 // with the ones that caller expect on setup. 202 expectNumberOfProtos(t, expect, lsubRe, expectedSubs, infoStartRe, pingRe) 203 return send, expect 204 } 205 206 func TestLeafNodeSendsSubsAfterConnect(t *testing.T) { 207 s, opts := runLeafServer() 208 defer s.Shutdown() 209 210 c := createClientConn(t, opts.Host, opts.Port) 211 defer c.Close() 212 213 send, expect := setupConn(t, c) 214 send("SUB foo 1\r\n") 215 send("SUB bar 2\r\n") 216 send("SUB foo baz 3\r\n") 217 send("SUB foo baz 4\r\n") 218 send("SUB bar 5\r\n") 219 send("PING\r\n") 220 expect(pongRe) 221 222 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 223 defer lc.Close() 224 225 // This should compress down to 1 for foo, 1 for bar, and 1 for foo [baz] 226 // and one for the loop detection subject. 227 setupLeaf(t, lc, 4) 228 } 229 230 func TestLeafNodeSendsSubsOngoing(t *testing.T) { 231 s, opts := runLeafServer() 232 defer s.Shutdown() 233 234 c := createClientConn(t, opts.Host, opts.Port) 235 defer c.Close() 236 237 send, expect := setupConn(t, c) 238 send("PING\r\n") 239 expect(pongRe) 240 241 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 242 defer lc.Close() 243 244 leafSend, leafExpect := setupLeaf(t, lc, 1) 245 leafSend("PING\r\n") 246 leafExpect(pongRe) 247 248 send("SUB foo 1\r\n") 249 leafExpect(lsubRe) 250 251 // Check queues send updates each time. 252 // TODO(dlc) - If we decide to suppress this with a timer approach this test will break. 253 send("SUB foo bar 2\r\n") 254 leafExpect(lsubRe) 255 send("SUB foo bar 3\r\n") 256 leafExpect(lsubRe) 257 send("SUB foo bar 4\r\n") 258 leafExpect(lsubRe) 259 260 // Now check more normal subs do nothing. 261 send("SUB foo 5\r\n") 262 expectNothing(t, lc) 263 264 // Check going back down does nothing til we hit 0. 265 send("UNSUB 5\r\n") 266 expectNothing(t, lc) 267 send("UNSUB 1\r\n") 268 leafExpect(lunsubRe) 269 270 // Queues going down should always send updates. 271 send("UNSUB 2\r\n") 272 leafExpect(lsubRe) 273 send("UNSUB 3\r\n") 274 leafExpect(lsubRe) 275 send("UNSUB 4\r\n") 276 leafExpect(lunsubRe) 277 } 278 279 func TestLeafNodeSubs(t *testing.T) { 280 s, opts := runLeafServer() 281 defer s.Shutdown() 282 283 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 284 defer lc.Close() 285 286 leafSend, leafExpect := setupLeaf(t, lc, 1) 287 288 leafSend("PING\r\n") 289 leafExpect(pongRe) 290 291 leafSend("LS+ foo\r\n") 292 expectNothing(t, lc) 293 leafSend("PING\r\n") 294 leafExpect(pongRe) 295 296 c := createClientConn(t, opts.Host, opts.Port) 297 defer c.Close() 298 299 send, expect := setupConn(t, c) 300 send("PING\r\n") 301 expect(pongRe) 302 303 send("PUB foo 2\r\nOK\r\n") 304 matches := lmsgRe.FindAllSubmatch(leafExpect(lmsgRe), -1) 305 if len(matches) != 1 { 306 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 307 } 308 checkLmsg(t, matches[0], "foo", "", "2", "OK") 309 310 // Second sub should not change delivery 311 leafSend("LS+ foo\r\n") 312 expectNothing(t, lc) 313 leafSend("PING\r\n") 314 leafExpect(pongRe) 315 316 send("PUB foo 3\r\nOK!\r\n") 317 matches = lmsgRe.FindAllSubmatch(leafExpect(lmsgRe), -1) 318 if len(matches) != 1 { 319 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 320 } 321 checkLmsg(t, matches[0], "foo", "", "3", "OK!") 322 323 // Now add in a queue sub with weight 4. 324 leafSend("LS+ foo bar 4\r\n") 325 expectNothing(t, lc) 326 leafSend("PING\r\n") 327 leafExpect(pongRe) 328 329 send("PUB foo 4\r\nOKOK\r\n") 330 matches = lmsgRe.FindAllSubmatch(leafExpect(lmsgRe), -1) 331 if len(matches) != 1 { 332 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 333 } 334 checkLmsg(t, matches[0], "foo", "| bar", "4", "OKOK") 335 336 // Now add in a queue sub with weight 4. 337 leafSend("LS+ foo baz 2\r\n") 338 expectNothing(t, lc) 339 leafSend("PING\r\n") 340 leafExpect(pongRe) 341 342 send("PUB foo 5\r\nHELLO\r\n") 343 matches = lmsgRe.FindAllSubmatch(leafExpect(lmsgRe), -1) 344 if len(matches) != 1 { 345 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 346 } 347 checkLmsg(t, matches[0], "foo", "| bar baz", "5", "HELLO") 348 349 // Test Unsub 350 leafSend("LS- foo\r\n") 351 leafSend("LS- foo bar\r\n") 352 leafSend("LS- foo baz\r\n") 353 expectNothing(t, lc) 354 leafSend("PING\r\n") 355 leafExpect(pongRe) 356 357 send("PUB foo 5\r\nHELLO\r\n") 358 expectNothing(t, lc) 359 } 360 361 func TestLeafNodeMsgDelivery(t *testing.T) { 362 s, opts := runLeafServer() 363 defer s.Shutdown() 364 365 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 366 defer lc.Close() 367 368 leafSend, leafExpect := setupLeaf(t, lc, 1) 369 370 leafSend("PING\r\n") 371 leafExpect(pongRe) 372 373 c := createClientConn(t, opts.Host, opts.Port) 374 defer c.Close() 375 376 send, expect := setupConn(t, c) 377 send("PING\r\n") 378 expect(pongRe) 379 380 send("SUB foo 1\r\nPING\r\n") 381 expect(pongRe) 382 leafExpect(lsubRe) 383 384 // Now send from leaf side. 385 leafSend("LMSG foo 2\r\nOK\r\n") 386 expectNothing(t, lc) 387 388 matches := msgRe.FindAllSubmatch(expect(msgRe), -1) 389 if len(matches) != 1 { 390 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 391 } 392 checkMsg(t, matches[0], "foo", "1", "", "2", "OK") 393 394 send("UNSUB 1\r\nPING\r\n") 395 expect(pongRe) 396 leafExpect(lunsubRe) 397 send("SUB foo bar 2\r\nPING\r\n") 398 expect(pongRe) 399 leafExpect(lsubRe) 400 401 // Now send again from leaf side. This is targeted so this should 402 // not be delivered. 403 leafSend("LMSG foo 2\r\nOK\r\n") 404 expectNothing(t, lc) 405 expectNothing(t, c) 406 407 // Now send targeted, and we should receive it. 408 leafSend("LMSG foo | bar 2\r\nOK\r\n") 409 expectNothing(t, lc) 410 411 matches = msgRe.FindAllSubmatch(expect(msgRe), -1) 412 if len(matches) != 1 { 413 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 414 } 415 checkMsg(t, matches[0], "foo", "2", "", "2", "OK") 416 417 // Check reply + queues 418 leafSend("LMSG foo + myreply bar 2\r\nOK\r\n") 419 expectNothing(t, lc) 420 421 matches = msgRe.FindAllSubmatch(expect(msgRe), -1) 422 if len(matches) != 1 { 423 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 424 } 425 checkMsg(t, matches[0], "foo", "2", "myreply", "2", "OK") 426 } 427 428 func TestLeafNodeAndRoutes(t *testing.T) { 429 optsA := LoadConfig("./configs/srv_a_leaf.conf") 430 optsA.DisableShortFirstPing = true 431 optsB := LoadConfig("./configs/srv_b.conf") 432 optsB.DisableShortFirstPing = true 433 srvA := RunServer(optsA) 434 defer srvA.Shutdown() 435 srvB := RunServer(optsB) 436 defer srvB.Shutdown() 437 checkClusterFormed(t, srvA, srvB) 438 439 lc := createLeafConn(t, optsA.LeafNode.Host, optsA.LeafNode.Port) 440 defer lc.Close() 441 442 leafSend, leafExpect := setupLeaf(t, lc, 6) 443 leafSend("PING\r\n") 444 leafExpect(pongRe) 445 446 c := createClientConn(t, optsB.Host, optsB.Port) 447 defer c.Close() 448 449 send, expect := setupConn(t, c) 450 send("PING\r\n") 451 expect(pongRe) 452 453 send("SUB foo 1\r\nPING\r\n") 454 expect(pongRe) 455 leafExpect(lsubRe) 456 457 send("SUB foo 2\r\nPING\r\n") 458 expect(pongRe) 459 expectNothing(t, lc) 460 461 send("UNSUB 2\r\nPING\r\n") 462 expect(pongRe) 463 expectNothing(t, lc) 464 send("UNSUB 1\r\nPING\r\n") 465 expect(pongRe) 466 leafExpect(lunsubRe) 467 468 // Now put it back and test msg flow. 469 send("SUB foo 1\r\nPING\r\n") 470 expect(pongRe) 471 leafExpect(lsubRe) 472 473 leafSend("LMSG foo + myreply bar 2\r\nOK\r\n") 474 expectNothing(t, lc) 475 476 matches := msgRe.FindAllSubmatch(expect(msgRe), -1) 477 if len(matches) != 1 { 478 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 479 } 480 checkMsg(t, matches[0], "foo", "1", "myreply", "2", "OK") 481 482 // Now check reverse. 483 leafSend("LS+ bar\r\n") 484 expectNothing(t, lc) 485 leafSend("PING\r\n") 486 leafExpect(pongRe) 487 488 send("PUB bar 2\r\nOK\r\n") 489 matches = lmsgRe.FindAllSubmatch(leafExpect(lmsgRe), -1) 490 if len(matches) != 1 { 491 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 492 } 493 checkLmsg(t, matches[0], "bar", "", "2", "OK") 494 } 495 496 // Helper function to check that a leaf node has connected to our server. 497 func checkLeafNodeConnected(t *testing.T, s *server.Server) { 498 t.Helper() 499 checkLeafNodeConnections(t, s, 1) 500 } 501 502 func checkLeafNodeConnections(t *testing.T, s *server.Server, expected int) { 503 t.Helper() 504 checkFor(t, 5*time.Second, 100*time.Millisecond, func() error { 505 if nln := s.NumLeafNodes(); nln != expected { 506 return fmt.Errorf("Expected a connected leafnode for server %q, got %d", s.ID(), nln) 507 } 508 return nil 509 }) 510 } 511 512 func TestLeafNodeSolicit(t *testing.T) { 513 s, opts := runLeafServer() 514 defer s.Shutdown() 515 516 sl, _ := runSolicitLeafServer(opts) 517 defer sl.Shutdown() 518 519 checkLeafNodeConnected(t, s) 520 521 // Now test reconnect. 522 s.Shutdown() 523 // Need to restart it on the same port. 524 s, _ = runLeafServerOnPort(opts.LeafNode.Port) 525 defer s.Shutdown() 526 checkLeafNodeConnected(t, s) 527 } 528 529 func TestLeafNodeNoEcho(t *testing.T) { 530 s, opts := runLeafServer() 531 defer s.Shutdown() 532 533 c := createClientConn(t, opts.Host, opts.Port) 534 defer c.Close() 535 536 send, expect := setupConn(t, c) 537 send("PING\r\n") 538 expect(pongRe) 539 540 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 541 defer lc.Close() 542 543 leafSend, leafExpect := setupLeaf(t, lc, 1) 544 leafSend("PING\r\n") 545 leafExpect(pongRe) 546 547 // We should not echo back to ourselves. Set up 'foo' subscriptions 548 // on both sides and send message across the leafnode connection. It 549 // should not come back. 550 551 send("SUB foo 1\r\n") 552 leafExpect(lsubRe) 553 554 leafSend("LS+ foo\r\n") 555 expectNothing(t, lc) 556 leafSend("PING\r\n") 557 leafExpect(pongRe) 558 559 leafSend("LMSG foo 2\r\nOK\r\n") 560 expectNothing(t, lc) 561 } 562 563 func TestLeafNodeHeaderSupport(t *testing.T) { 564 srvA, optsA := runLeafServer() 565 defer srvA.Shutdown() 566 567 srvB, optsB := runSolicitLeafServer(optsA) 568 defer srvB.Shutdown() 569 570 clientA := createClientConn(t, optsA.Host, optsA.Port) 571 defer clientA.Close() 572 573 clientB := createClientConn(t, optsB.Host, optsB.Port) 574 defer clientB.Close() 575 576 sendA, expectA := setupHeaderConn(t, clientA) 577 sendA("SUB foo bar 22\r\n") 578 sendA("SUB bar 11\r\n") 579 sendA("PING\r\n") 580 expectA(pongRe) 581 582 if err := checkExpectedSubs(3, srvB); err != nil { 583 t.Fatalf("%v", err) 584 } 585 586 sendB, expectB := setupHeaderConn(t, clientB) 587 // Can not have \r\n in payload fyi for regex. 588 // With reply 589 sendB("HPUB foo reply 12 14\r\nK1:V1,K2:V2 ok\r\n") 590 sendB("PING\r\n") 591 expectB(pongRe) 592 593 expectHeaderMsgs := expectHeaderMsgsCommand(t, expectA) 594 matches := expectHeaderMsgs(1) 595 checkHmsg(t, matches[0], "foo", "22", "reply", "12", "14", "K1:V1,K2:V2 ", "ok") 596 597 // Without reply 598 sendB("HPUB foo 12 14\r\nK1:V1,K2:V2 ok\r\n") 599 sendB("PING\r\n") 600 expectB(pongRe) 601 602 matches = expectHeaderMsgs(1) 603 checkHmsg(t, matches[0], "foo", "22", "", "12", "14", "K1:V1,K2:V2 ", "ok") 604 605 // Without queues or reply 606 sendB("HPUB bar 12 14\r\nK1:V1,K2:V2 ok\r\n") 607 sendB("PING\r\n") 608 expectB(pongRe) 609 610 matches = expectHeaderMsgs(1) 611 checkHmsg(t, matches[0], "bar", "11", "", "12", "14", "K1:V1,K2:V2 ", "ok") 612 613 // Without queues but with reply 614 sendB("HPUB bar reply 12 14\r\nK1:V1,K2:V2 ok\r\n") 615 sendB("PING\r\n") 616 expectB(pongRe) 617 618 matches = expectHeaderMsgs(1) 619 checkHmsg(t, matches[0], "bar", "11", "reply", "12", "14", "K1:V1,K2:V2 ", "ok") 620 } 621 622 // Used to setup clusters of clusters for tests. 623 type cluster struct { 624 servers []*server.Server 625 opts []*server.Options 626 name string 627 t *testing.T 628 } 629 630 func testDefaultClusterOptionsForLeafNodes() *server.Options { 631 o := DefaultTestOptions 632 o.Port = -1 633 o.Cluster.Host = o.Host 634 o.Cluster.Port = -1 635 o.Gateway.Host = o.Host 636 o.Gateway.Port = -1 637 o.LeafNode.Host = o.Host 638 o.LeafNode.Port = -1 639 return &o 640 } 641 642 func (c *cluster) shutdown() { 643 if c == nil { 644 return 645 } 646 for i, s := range c.servers { 647 if cf := c.opts[i].ConfigFile; cf != "" { 648 os.RemoveAll(cf) 649 } 650 if sd := s.StoreDir(); sd != "" { 651 os.RemoveAll(sd) 652 } 653 s.Shutdown() 654 } 655 } 656 657 func shutdownCluster(c *cluster) { 658 c.shutdown() 659 } 660 661 func (c *cluster) totalSubs() int { 662 totalSubs := 0 663 for _, s := range c.servers { 664 totalSubs += int(s.NumSubscriptions()) 665 } 666 return totalSubs 667 } 668 669 // Wait for the expected number of outbound gateways, or fails. 670 func waitForOutboundGateways(t *testing.T, s *server.Server, expected int, timeout time.Duration) { 671 t.Helper() 672 if timeout < 2*time.Second { 673 timeout = 2 * time.Second 674 } 675 checkFor(t, timeout, 15*time.Millisecond, func() error { 676 if n := s.NumOutboundGateways(); n != expected { 677 return fmt.Errorf("Expected %v outbound gateway(s), got %v (ulimit -n too low?)", 678 expected, n) 679 } 680 return nil 681 }) 682 } 683 684 // Creates a full cluster with numServers and given name and makes sure its well formed. 685 // Will have Gateways and Leaf Node connections active. 686 func createClusterWithName(t *testing.T, clusterName string, numServers int, connectTo ...*cluster) *cluster { 687 t.Helper() 688 return createClusterEx(t, false, 5*time.Millisecond, true, clusterName, numServers, connectTo...) 689 } 690 691 // Creates a cluster and optionally additional accounts and users. 692 // Will have Gateways and Leaf Node connections active. 693 func createClusterEx(t *testing.T, doAccounts bool, gwSolicit time.Duration, waitOnGWs bool, clusterName string, numServers int, connectTo ...*cluster) *cluster { 694 t.Helper() 695 696 if clusterName == "" || numServers < 1 { 697 t.Fatalf("Bad params") 698 } 699 700 // Setup some accounts and users. 701 // $SYS is always the system account. And we have default FOO and BAR accounts, as well 702 // as DLC and NGS which do a service import. 703 createAccountsAndUsers := func() ([]*server.Account, []*server.User) { 704 if !doAccounts { 705 return []*server.Account{server.NewAccount("$SYS")}, nil 706 } 707 708 sys := server.NewAccount("$SYS") 709 ngs := server.NewAccount("NGS") 710 dlc := server.NewAccount("DLC") 711 foo := server.NewAccount("FOO") 712 bar := server.NewAccount("BAR") 713 714 accounts := []*server.Account{sys, foo, bar, ngs, dlc} 715 716 ngs.AddServiceExport("ngs.usage.*", nil) 717 dlc.AddServiceImport(ngs, "ngs.usage", "ngs.usage.dlc") 718 719 // Setup users 720 users := []*server.User{ 721 {Username: "dlc", Password: "pass", Permissions: nil, Account: dlc}, 722 {Username: "ngs", Password: "pass", Permissions: nil, Account: ngs}, 723 {Username: "foo", Password: "pass", Permissions: nil, Account: foo}, 724 {Username: "bar", Password: "pass", Permissions: nil, Account: bar}, 725 {Username: "sys", Password: "pass", Permissions: nil, Account: sys}, 726 } 727 return accounts, users 728 } 729 730 bindGlobal := func(s *server.Server) { 731 ngs, err := s.LookupAccount("NGS") 732 if err != nil { 733 return 734 } 735 // Bind global to service import 736 gacc, _ := s.LookupAccount("$G") 737 gacc.AddServiceImport(ngs, "ngs.usage", "ngs.usage.$G") 738 } 739 740 // If we are going to connect to another cluster set that up now for options. 741 var gws []*server.RemoteGatewayOpts 742 for _, c := range connectTo { 743 // Gateways autodiscover here too, so just need one address from the set. 744 gwAddr := fmt.Sprintf("nats-gw://%s:%d", c.opts[0].Gateway.Host, c.opts[0].Gateway.Port) 745 gwurl, _ := url.Parse(gwAddr) 746 gws = append(gws, &server.RemoteGatewayOpts{Name: c.name, URLs: []*url.URL{gwurl}}) 747 } 748 749 // Make the GWs form faster for the tests. 750 server.SetGatewaysSolicitDelay(gwSolicit) 751 defer server.ResetGatewaysSolicitDelay() 752 753 // Create seed first. 754 o := testDefaultClusterOptionsForLeafNodes() 755 o.Gateway.Name = clusterName 756 o.Gateway.Gateways = gws 757 // All of these need system accounts. 758 o.Accounts, o.Users = createAccountsAndUsers() 759 o.SystemAccount = "$SYS" 760 o.ServerName = fmt.Sprintf("%s1", clusterName) 761 // Run the server 762 s := RunServer(o) 763 bindGlobal(s) 764 765 c := &cluster{servers: make([]*server.Server, 0, numServers), opts: make([]*server.Options, 0, numServers), name: clusterName} 766 c.servers = append(c.servers, s) 767 c.opts = append(c.opts, o) 768 769 // For connecting to seed server above. 770 routeAddr := fmt.Sprintf("nats-route://%s:%d", o.Cluster.Host, o.Cluster.Port) 771 rurl, _ := url.Parse(routeAddr) 772 routes := []*url.URL{rurl} 773 774 for i := 1; i < numServers; i++ { 775 o := testDefaultClusterOptionsForLeafNodes() 776 o.Gateway.Name = clusterName 777 o.Gateway.Gateways = gws 778 o.Routes = routes 779 // All of these need system accounts. 780 o.Accounts, o.Users = createAccountsAndUsers() 781 o.SystemAccount = "$SYS" 782 o.ServerName = fmt.Sprintf("%s%d", clusterName, i+1) 783 s := RunServer(o) 784 bindGlobal(s) 785 786 c.servers = append(c.servers, s) 787 c.opts = append(c.opts, o) 788 } 789 checkClusterFormed(t, c.servers...) 790 791 if waitOnGWs { 792 // Wait on gateway connections if we were asked to connect to other gateways. 793 if numGWs := len(connectTo); numGWs > 0 { 794 for _, s := range c.servers { 795 waitForOutboundGateways(t, s, numGWs, 2*time.Second) 796 } 797 } 798 } 799 c.t = t 800 return c 801 } 802 803 func TestLeafNodeGatewayRequiresSystemAccount(t *testing.T) { 804 o := testDefaultClusterOptionsForLeafNodes() 805 o.Gateway.Name = "CLUSTER-A" 806 _, err := server.NewServer(o) 807 if err == nil { 808 t.Fatalf("Expected an error with no system account defined") 809 } 810 } 811 812 func TestLeafNodeGatewaySendsSystemEvent(t *testing.T) { 813 server.SetGatewaysSolicitDelay(50 * time.Millisecond) 814 defer server.ResetGatewaysSolicitDelay() 815 816 ca := createClusterWithName(t, "A", 1) 817 defer shutdownCluster(ca) 818 cb := createClusterWithName(t, "B", 1, ca) 819 defer shutdownCluster(cb) 820 821 // Create client on a server in cluster A 822 opts := ca.opts[0] 823 c := createClientConn(t, opts.Host, opts.Port) 824 defer c.Close() 825 826 // Listen for the leaf node event. 827 send, expect := setupConnWithAccount(t, ca.servers[0], c, "$SYS") 828 send("SUB $SYS.ACCOUNT.$G.LEAFNODE.CONNECT 1\r\nPING\r\n") 829 expect(pongRe) 830 831 opts = cb.opts[0] 832 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 833 defer lc.Close() 834 835 // This is for our global responses since we are setting up GWs above. 836 leafSend, leafExpect := setupLeaf(t, lc, 8) 837 leafSend("PING\r\n") 838 leafExpect(pongRe) 839 840 matches := rawMsgRe.FindAllSubmatch(expect(rawMsgRe), -1) 841 if len(matches) != 1 { 842 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 843 } 844 m := matches[0] 845 if string(m[subIndex]) != "$SYS.ACCOUNT.$G.LEAFNODE.CONNECT" { 846 t.Fatalf("Got wrong subject for leaf node event, got %q, wanted %q", 847 m[subIndex], "$SYS.ACCOUNT.$G.LEAFNODE.CONNECT") 848 } 849 } 850 851 func TestLeafNodeGatewayInterestPropagation(t *testing.T) { 852 server.SetGatewaysSolicitDelay(10 * time.Millisecond) 853 defer server.ResetGatewaysSolicitDelay() 854 855 ca := createClusterWithName(t, "A", 3) 856 defer shutdownCluster(ca) 857 cb := createClusterWithName(t, "B", 3, ca) 858 defer shutdownCluster(cb) 859 860 sl1, sl1Opts := runSolicitLeafServer(ca.opts[1]) 861 defer sl1.Shutdown() 862 863 c := createClientConn(t, sl1Opts.Host, sl1Opts.Port) 864 defer c.Close() 865 866 send, expect := setupConn(t, c) 867 send("SUB foo 1\r\n") 868 send("PING\r\n") 869 expect(pongRe) 870 871 // Now we will create a new leaf node on cluster B, expect to get the 872 // interest for "foo". 873 opts := cb.opts[0] 874 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 875 defer lc.Close() 876 _, leafExpect := setupConn(t, lc) 877 buf := leafExpect(infoStartRe) 878 buf = infoStartRe.ReplaceAll(buf, []byte(nil)) 879 880 foundFoo := false 881 for count := 0; count < 10; { 882 // skip first time if we still have data (buf from above may already have some left) 883 if count != 0 || len(buf) == 0 { 884 buf = append(buf, leafExpect(anyRe)...) 885 } 886 count += len(lsubRe.FindAllSubmatch(buf, -1)) 887 if count > 10 { 888 t.Fatalf("Expected %v matches, got %v (buf=%s)", 10, count, buf) 889 } 890 if strings.Contains(string(buf), "foo") { 891 foundFoo = true 892 } 893 buf = lsubRe.ReplaceAll(buf, []byte(nil)) 894 } 895 if len(buf) != 0 { 896 t.Fatalf("did not consume everything, left with: %q", buf) 897 } 898 if !foundFoo { 899 t.Fatalf("Expected interest for 'foo' as 'LS+ foo\\r\\n', got %q", buf) 900 } 901 } 902 903 func TestLeafNodeAuthSystemEventNoCrash(t *testing.T) { 904 ca := createClusterWithName(t, "A", 1) 905 defer shutdownCluster(ca) 906 907 opts := ca.opts[0] 908 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 909 defer lc.Close() 910 911 leafSend := sendCommand(t, lc) 912 leafSend("LS+ foo\r\n") 913 checkInfoMsg(t, lc) 914 } 915 916 func TestLeafNodeWithRouteAndGateway(t *testing.T) { 917 server.SetGatewaysSolicitDelay(50 * time.Millisecond) 918 defer server.ResetGatewaysSolicitDelay() 919 920 ca := createClusterWithName(t, "A", 3) 921 defer shutdownCluster(ca) 922 cb := createClusterWithName(t, "B", 3, ca) 923 defer shutdownCluster(cb) 924 925 // Create client on a server in cluster A 926 opts := ca.opts[0] 927 c := createClientConn(t, opts.Host, opts.Port) 928 defer c.Close() 929 930 send, expect := setupConn(t, c) 931 send("PING\r\n") 932 expect(pongRe) 933 934 // Create a leaf node connection on a server in cluster B 935 opts = cb.opts[0] 936 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 937 defer lc.Close() 938 939 // This is for our global responses since we are setting up GWs above. 940 leafSend, leafExpect := setupLeaf(t, lc, 8) 941 leafSend("PING\r\n") 942 leafExpect(pongRe) 943 944 // Make sure we see interest graph propagation on the leaf node 945 // connection. This is required since leaf nodes only send data 946 // in the presence of interest. 947 send("SUB foo 1\r\nPING\r\n") 948 expect(pongRe) 949 leafExpect(lsubRe) 950 951 send("SUB foo 2\r\nPING\r\n") 952 expect(pongRe) 953 expectNothing(t, lc) 954 955 send("UNSUB 2\r\n") 956 expectNothing(t, lc) 957 send("UNSUB 1\r\n") 958 leafExpect(lunsubRe) 959 960 // Now put it back and test msg flow. 961 send("SUB foo 1\r\nPING\r\n") 962 expect(pongRe) 963 leafExpect(lsubRe) 964 965 leafSend("LMSG foo 2\r\nOK\r\n") 966 expectNothing(t, lc) 967 968 matches := msgRe.FindAllSubmatch(expect(msgRe), -1) 969 if len(matches) != 1 { 970 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 971 } 972 checkMsg(t, matches[0], "foo", "1", "", "2", "OK") 973 974 // Now check reverse. 975 leafSend("LS+ bar\r\n") 976 expectNothing(t, lc) 977 leafSend("PING\r\n") 978 leafExpect(pongRe) 979 980 send("PUB bar 2\r\nOK\r\n") 981 matches = lmsgRe.FindAllSubmatch(leafExpect(lmsgRe), -1) 982 if len(matches) != 1 { 983 t.Fatalf("Expected only 1 msg, got %d", len(matches)) 984 } 985 checkLmsg(t, matches[0], "bar", "", "2", "OK") 986 } 987 988 // This will test that we propagate interest only mode after a leafnode 989 // has been established and a new server joins a remote cluster. 990 func TestLeafNodeWithGatewaysAndStaggeredStart(t *testing.T) { 991 ca := createClusterWithName(t, "A", 3) 992 defer shutdownCluster(ca) 993 994 // Create the leafnode on a server in cluster A. 995 opts := ca.opts[0] 996 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 997 defer lc.Close() 998 999 leafSend, leafExpect := setupLeaf(t, lc, 8) 1000 leafSend("PING\r\n") 1001 leafExpect(pongRe) 1002 1003 // Now setup the cluster B. 1004 cb := createClusterWithName(t, "B", 3, ca) 1005 defer shutdownCluster(cb) 1006 1007 // Create client on a server in cluster B 1008 opts = cb.opts[0] 1009 c := createClientConn(t, opts.Host, opts.Port) 1010 defer c.Close() 1011 1012 send, expect := setupConn(t, c) 1013 send("PING\r\n") 1014 expect(pongRe) 1015 1016 // Make sure we see interest graph propagation on the leaf node 1017 // connection. This is required since leaf nodes only send data 1018 // in the presence of interest. 1019 send("SUB foo 1\r\nPING\r\n") 1020 expect(pongRe) 1021 leafExpect(lsubRe) 1022 } 1023 1024 // This will test that we propagate interest only mode after a leafnode 1025 // has been established and a server is restarted.. 1026 func TestLeafNodeWithGatewaysServerRestart(t *testing.T) { 1027 ca := createClusterWithName(t, "A", 3) 1028 defer shutdownCluster(ca) 1029 1030 // Now setup the cluster B. 1031 cb := createClusterWithName(t, "B", 3, ca) 1032 defer shutdownCluster(cb) 1033 1034 // Create the leafnode on a server in cluster B. 1035 opts := cb.opts[1] 1036 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 1037 defer lc.Close() 1038 1039 leafSend, leafExpect := setupLeaf(t, lc, 8) 1040 leafSend("PING\r\n") 1041 leafExpect(pongRe) 1042 1043 // Create client on a server in cluster A 1044 opts = ca.opts[1] 1045 c := createClientConn(t, opts.Host, opts.Port) 1046 defer c.Close() 1047 1048 send, expect := setupConn(t, c) 1049 send("PING\r\n") 1050 expect(pongRe) 1051 1052 // Make sure we see interest graph propagation on the leaf node 1053 // connection. This is required since leaf nodes only send data 1054 // in the presence of interest. 1055 send("SUB foo 1\r\nPING\r\n") 1056 expect(pongRe) 1057 leafExpect(lsubRe) 1058 1059 // Close old leaf connection and simulate a reconnect. 1060 lc.Close() 1061 1062 // Shutdown and recreate B and the leafnode connection to it. 1063 shutdownCluster(cb) 1064 1065 // Create new cluster with longer solicit and don't wait for GW connect. 1066 cb = createClusterEx(t, false, 500*time.Millisecond, false, "B", 1, ca) 1067 defer shutdownCluster(cb) 1068 1069 opts = cb.opts[0] 1070 lc = createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 1071 defer lc.Close() 1072 1073 _, leafExpect = setupLeaf(t, lc, 8) 1074 1075 // Now wait on GW solicit to fire 1076 time.Sleep(500 * time.Millisecond) 1077 1078 // We should see the interest for 'foo' here. 1079 leafExpect(lsubRe) 1080 } 1081 1082 func TestLeafNodeLocalizedDQ(t *testing.T) { 1083 s, opts := runLeafServer() 1084 defer s.Shutdown() 1085 1086 sl, slOpts := runSolicitLeafServer(opts) 1087 defer sl.Shutdown() 1088 1089 checkLeafNodeConnected(t, s) 1090 1091 c := createClientConn(t, slOpts.Host, slOpts.Port) 1092 defer c.Close() 1093 1094 send, expect := setupConn(t, c) 1095 send("SUB foo bar 1\r\n") 1096 send("SUB foo bar 2\r\n") 1097 send("SUB foo bar 3\r\n") 1098 send("SUB foo bar 4\r\n") 1099 send("PING\r\n") 1100 expect(pongRe) 1101 1102 // Now create another client on the main leaf server. 1103 sc := createClientConn(t, opts.Host, opts.Port) 1104 defer sc.Close() 1105 1106 sendL, expectL := setupConn(t, sc) 1107 sendL("SUB foo bar 11\r\n") 1108 sendL("SUB foo bar 12\r\n") 1109 sendL("SUB foo bar 13\r\n") 1110 sendL("SUB foo bar 14\r\n") 1111 sendL("PING\r\n") 1112 expectL(pongRe) 1113 1114 for i := 0; i < 10; i++ { 1115 send("PUB foo 2\r\nOK\r\n") 1116 } 1117 expectNothing(t, sc) 1118 1119 matches := msgRe.FindAllSubmatch(expect(msgRe), -1) 1120 if len(matches) != 10 { 1121 t.Fatalf("Expected 10 msgs, got %d", len(matches)) 1122 } 1123 for i := 0; i < 10; i++ { 1124 checkMsg(t, matches[i], "foo", "", "", "2", "OK") 1125 } 1126 } 1127 1128 func TestLeafNodeBasicAuth(t *testing.T) { 1129 content := ` 1130 listen: "127.0.0.1:-1" 1131 1132 leafnodes { 1133 listen: "127.0.0.1:-1" 1134 authorization { 1135 user: "derek" 1136 password: "s3cr3t!" 1137 timeout: 2.2 1138 } 1139 } 1140 ` 1141 conf := createConfFile(t, []byte(content)) 1142 1143 s, opts := RunServerWithConfig(conf) 1144 defer s.Shutdown() 1145 1146 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 1147 defer lc.Close() 1148 1149 // This should fail since we want u/p 1150 setupConn(t, lc) 1151 errBuf := expectResult(t, lc, errRe) 1152 if !strings.Contains(string(errBuf), "Authorization Violation") { 1153 t.Fatalf("Authentication Timeout response incorrect: %q", errBuf) 1154 } 1155 expectDisconnect(t, lc) 1156 1157 // Try bad password as well. 1158 lc = createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 1159 defer lc.Close() 1160 1161 // This should fail since we want u/p 1162 setupConnWithUserPass(t, lc, "derek", "badpassword") 1163 errBuf = expectResult(t, lc, errRe) 1164 if !strings.Contains(string(errBuf), "Authorization Violation") { 1165 t.Fatalf("Authentication Timeout response incorrect: %q", errBuf) 1166 } 1167 expectDisconnect(t, lc) 1168 1169 // This one should work. 1170 lc = createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 1171 defer lc.Close() 1172 leafSend, leafExpect := setupConnWithUserPass(t, lc, "derek", "s3cr3t!") 1173 leafExpect(infoRe) 1174 leafExpect(lsubRe) 1175 leafSend("PING\r\n") 1176 expectResult(t, lc, pongRe) 1177 1178 checkLeafNodeConnected(t, s) 1179 } 1180 1181 func runTLSSolicitLeafServer(lso *server.Options) (*server.Server, *server.Options) { 1182 o := DefaultTestOptions 1183 o.Port = -1 1184 rurl, _ := url.Parse(fmt.Sprintf("nats-leaf://%s:%d", lso.LeafNode.Host, lso.LeafNode.Port)) 1185 remote := &server.RemoteLeafOpts{URLs: []*url.URL{rurl}} 1186 remote.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12} 1187 host, _, _ := net.SplitHostPort(lso.LeafNode.Host) 1188 remote.TLSConfig.ServerName = host 1189 remote.TLSConfig.InsecureSkipVerify = true 1190 remote.Compression.Mode = server.CompressionOff 1191 o.LeafNode.Remotes = []*server.RemoteLeafOpts{remote} 1192 o.LeafNode.Compression.Mode = server.CompressionOff 1193 return RunServer(&o), &o 1194 } 1195 1196 func TestLeafNodeTLS(t *testing.T) { 1197 content := ` 1198 listen: "127.0.0.1:-1" 1199 1200 leafnodes { 1201 listen: "127.0.0.1:-1" 1202 tls { 1203 cert_file: "./configs/certs/server-cert.pem" 1204 key_file: "./configs/certs/server-key.pem" 1205 timeout: 0.1 1206 } 1207 } 1208 ` 1209 conf := createConfFile(t, []byte(content)) 1210 1211 s, opts := RunServerWithConfig(conf) 1212 defer s.Shutdown() 1213 1214 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 1215 defer lc.Close() 1216 1217 info := checkInfoMsg(t, lc) 1218 if !info.TLSRequired { 1219 t.Fatalf("Expected TLSRequired to be true") 1220 } 1221 if info.TLSVerify { 1222 t.Fatalf("Expected TLSVerify to be false") 1223 } 1224 // We should get a disconnect here since we have not upgraded to TLS. 1225 expectDisconnect(t, lc) 1226 1227 // This should work ok. 1228 sl, _ := runTLSSolicitLeafServer(opts) 1229 defer sl.Shutdown() 1230 1231 checkLeafNodeConnected(t, s) 1232 } 1233 1234 func TestLeafNodeTLSConnCloseEarly(t *testing.T) { 1235 content := ` 1236 listen: "127.0.0.1:-1" 1237 1238 leafnodes { 1239 listen: "127.0.0.1:-1" 1240 tls { 1241 cert_file: "./configs/certs/server-cert.pem" 1242 key_file: "./configs/certs/server-key.pem" 1243 timeout: 2.0 1244 } 1245 } 1246 ` 1247 conf := createConfFile(t, []byte(content)) 1248 1249 s, opts := RunServerWithConfig(conf) 1250 defer s.Shutdown() 1251 1252 lc, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", opts.LeafNode.Port)) 1253 if err != nil { 1254 t.Fatalf("Unable to connect: %v", err) 1255 } 1256 // Then close right away 1257 lc.Close() 1258 1259 // Check server does not crash... 1260 time.Sleep(250 * time.Millisecond) 1261 if s.ID() == "" { 1262 t.Fatalf("should not happen") 1263 } 1264 } 1265 1266 type captureLeafNodeErrLogger struct { 1267 dummyLogger 1268 ch chan string 1269 } 1270 1271 func (c *captureLeafNodeErrLogger) Errorf(format string, v ...interface{}) { 1272 msg := fmt.Sprintf(format, v...) 1273 select { 1274 case c.ch <- msg: 1275 default: 1276 } 1277 } 1278 1279 func TestLeafNodeTLSMixIP(t *testing.T) { 1280 content := ` 1281 listen: "127.0.0.1:-1" 1282 leafnodes { 1283 listen: "127.0.0.1:-1" 1284 authorization { 1285 user: dlc 1286 pass: monkey 1287 } 1288 tls { 1289 cert_file: "./configs/certs/server-noip.pem" 1290 key_file: "./configs/certs/server-key-noip.pem" 1291 ca_file: "./configs/certs/ca.pem" 1292 } 1293 } 1294 ` 1295 conf := createConfFile(t, []byte(content)) 1296 1297 s, opts := RunServerWithConfig(conf) 1298 defer s.Shutdown() 1299 1300 slContent := ` 1301 listen: "127.0.0.1:-1" 1302 leafnodes { 1303 reconnect: 1 1304 remotes: [ 1305 { 1306 url: [tls://127.0.0.1:%d, "tls://localhost:%d"] 1307 tls { ca_file: "./configs/certs/ca.pem" } 1308 } 1309 ] 1310 } 1311 ` 1312 slconf := createConfFile(t, []byte(fmt.Sprintf(slContent, opts.LeafNode.Port, opts.LeafNode.Port))) 1313 1314 // This will fail but we want to make sure in the correct way, not with 1315 // TLS issue because we used an IP for serverName. 1316 sl, _ := RunServerWithConfig(slconf) 1317 defer sl.Shutdown() 1318 1319 ll := &captureLeafNodeErrLogger{ch: make(chan string, 2)} 1320 sl.SetLogger(ll, false, false) 1321 1322 // We may or may not get an error depending on timing. For the handshake bug 1323 // we would always get it, so make sure if we have anything it is not that. 1324 select { 1325 case msg := <-ll.ch: 1326 if strings.Contains(msg, "TLS handshake error") && strings.Contains(msg, "doesn't contain any IP SANs") { 1327 t.Fatalf("Got bad error about TLS handshake") 1328 } 1329 default: 1330 } 1331 } 1332 1333 func runLeafNodeOperatorServer(t *testing.T) (*server.Server, *server.Options, string) { 1334 t.Helper() 1335 content := ` 1336 port: -1 1337 server_name: OP 1338 operator = "./configs/nkeys/op.jwt" 1339 resolver = MEMORY 1340 listen: "127.0.0.1:-1" 1341 leafnodes { 1342 listen: "127.0.0.1:-1" 1343 } 1344 ` 1345 conf := createConfFile(t, []byte(content)) 1346 s, opts := RunServerWithConfig(conf) 1347 return s, opts, conf 1348 } 1349 1350 func genCredsFile(t *testing.T, jwt string, seed []byte) string { 1351 creds := ` 1352 -----BEGIN NATS USER JWT----- 1353 %s 1354 ------END NATS USER JWT------ 1355 1356 ************************* IMPORTANT ************************* 1357 NKEY Seed printed below can be used to sign and prove identity. 1358 NKEYs are sensitive and should be treated as secrets. 1359 1360 -----BEGIN USER NKEY SEED----- 1361 %s 1362 ------END USER NKEY SEED------ 1363 1364 ************************************************************* 1365 ` 1366 return createConfFile(t, []byte(strings.Replace(fmt.Sprintf(creds, jwt, seed), "\t\t", "", -1))) 1367 } 1368 1369 func runSolicitWithCredentials(t *testing.T, opts *server.Options, creds string) (*server.Server, *server.Options, string) { 1370 content := ` 1371 port: -1 1372 leafnodes { 1373 remotes = [ 1374 { 1375 url: nats-leaf://127.0.0.1:%d 1376 credentials: '%s' 1377 } 1378 ] 1379 } 1380 ` 1381 config := fmt.Sprintf(content, opts.LeafNode.Port, creds) 1382 conf := createConfFile(t, []byte(config)) 1383 s, opts := RunServerWithConfig(conf) 1384 return s, opts, conf 1385 } 1386 1387 func TestLeafNodeOperatorModel(t *testing.T) { 1388 s, opts, _ := runLeafNodeOperatorServer(t) 1389 defer s.Shutdown() 1390 1391 // Make sure we get disconnected without proper credentials etc. 1392 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 1393 defer lc.Close() 1394 1395 // This should fail since we want user jwt, signed nonce etc. 1396 setupConn(t, lc) 1397 errBuf := expectResult(t, lc, errRe) 1398 if !strings.Contains(string(errBuf), "Authorization Violation") { 1399 t.Fatalf("Authentication Timeout response incorrect: %q", errBuf) 1400 } 1401 expectDisconnect(t, lc) 1402 1403 // Setup account and a user that will be used by the remote leaf node server. 1404 // createAccount automatically registers with resolver etc.. 1405 _, akp := createAccount(t, s) 1406 kp, _ := nkeys.CreateUser() 1407 pub, _ := kp.PublicKey() 1408 nuc := jwt.NewUserClaims(pub) 1409 ujwt, err := nuc.Encode(akp) 1410 if err != nil { 1411 t.Fatalf("Error generating user JWT: %v", err) 1412 } 1413 seed, _ := kp.Seed() 1414 mycreds := genCredsFile(t, ujwt, seed) 1415 1416 sl, _, _ := runSolicitWithCredentials(t, opts, mycreds) 1417 defer sl.Shutdown() 1418 1419 checkLeafNodeConnected(t, s) 1420 } 1421 1422 func TestLeafNodeUserPermsForConnection(t *testing.T) { 1423 s, opts, _ := runLeafNodeOperatorServer(t) 1424 defer s.Shutdown() 1425 1426 // Setup account and a user that will be used by the remote leaf node server. 1427 // createAccount automatically registers with resolver etc.. 1428 acc, akp := createAccount(t, s) 1429 kp, _ := nkeys.CreateUser() 1430 pub, _ := kp.PublicKey() 1431 nuc := jwt.NewUserClaims(pub) 1432 nuc.Permissions.Pub.Allow.Add("foo.>") 1433 nuc.Permissions.Pub.Allow.Add("baz.>") 1434 nuc.Permissions.Sub.Allow.Add("foo.>") 1435 // we would be immediately disconnected if that would not work 1436 nuc.Permissions.Sub.Deny.Add("$SYS.>") 1437 ujwt, err := nuc.Encode(akp) 1438 if err != nil { 1439 t.Fatalf("Error generating user JWT: %v", err) 1440 } 1441 seed, _ := kp.Seed() 1442 mycreds := genCredsFile(t, ujwt, seed) 1443 1444 content := ` 1445 port: -1 1446 leafnodes { 1447 remotes = [ 1448 { 1449 url: nats-leaf://127.0.0.1:%d 1450 credentials: '%s' 1451 deny_import: "foo.33" 1452 deny_export: "foo.33" 1453 } 1454 ] 1455 } 1456 ` 1457 config := fmt.Sprintf(content, opts.LeafNode.Port, mycreds) 1458 lnconf := createConfFile(t, []byte(config)) 1459 sl, _ := RunServerWithConfig(lnconf) 1460 defer sl.Shutdown() 1461 1462 checkLeafNodeConnected(t, s) 1463 1464 // Create credentials for a normal unrestricted user that we will connect to the op server. 1465 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 1466 nc, err := nats.Connect(url, createUserCreds(t, s, akp)) 1467 if err != nil { 1468 t.Fatalf("Error on connect: %v", err) 1469 } 1470 defer nc.Close() 1471 1472 // Create a user on the leafnode server that solicited. 1473 nc2, err := nats.Connect(sl.ClientURL()) 1474 if err != nil { 1475 t.Fatalf("Error on connect: %v", err) 1476 } 1477 defer nc2.Close() 1478 1479 // Make sure subscriptions properly do or do not make it to the hub. 1480 nc2.SubscribeSync("bar") 1481 checkNoSubInterest(t, s, acc.GetName(), "bar", 20*time.Millisecond) 1482 // This one should. 1483 nc2.SubscribeSync("foo.22") 1484 checkSubInterest(t, s, acc.GetName(), "foo.22", 100*time.Millisecond) 1485 1486 // Capture everything. 1487 sub, _ := nc.SubscribeSync(">") 1488 nc.Flush() 1489 1490 checkSubInterest(t, sl, "$G", ">", 100*time.Millisecond) 1491 // Now check local pubs are not forwarded. 1492 nc2.Publish("baz.22", nil) 1493 m, err := sub.NextMsg(1 * time.Second) 1494 if err != nil || m.Subject != "baz.22" { 1495 t.Fatalf("Expected to received this message") 1496 } 1497 nc2.Publish("bar.22", nil) 1498 if _, err := sub.NextMsg(100 * time.Millisecond); err == nil { 1499 t.Fatalf("Did not expect to receive this message") 1500 } 1501 1502 // Check local overrides work. 1503 nc2.Publish("foo.33", nil) 1504 if _, err := sub.NextMsg(100 * time.Millisecond); err == nil { 1505 t.Fatalf("Did not expect to receive this message") 1506 } 1507 1508 // This would trigger the sub interest below. 1509 sub.Unsubscribe() 1510 nc.Flush() 1511 1512 nc2.SubscribeSync("foo.33") 1513 checkNoSubInterest(t, s, acc.GetName(), "foo.33", 20*time.Millisecond) 1514 } 1515 1516 func TestLeafNodeMultipleAccounts(t *testing.T) { 1517 // So we will create a main server with two accounts. The remote server, acting as a leaf node, will simply have 1518 // the $G global account and no auth. Make sure things work properly here. 1519 s, opts, _ := runLeafNodeOperatorServer(t) 1520 defer s.Shutdown() 1521 1522 // Setup the two accounts for this server. 1523 a, akp1 := createAccount(t, s) 1524 kp1, _ := nkeys.CreateUser() 1525 pub1, _ := kp1.PublicKey() 1526 nuc1 := jwt.NewUserClaims(pub1) 1527 ujwt1, err := nuc1.Encode(akp1) 1528 if err != nil { 1529 t.Fatalf("Error generating user JWT: %v", err) 1530 } 1531 1532 // Create second account. 1533 createAccount(t, s) 1534 1535 // Create the leaf node server using the first account. 1536 seed, _ := kp1.Seed() 1537 mycreds := genCredsFile(t, ujwt1, seed) 1538 1539 sl, lopts, _ := runSolicitWithCredentials(t, opts, mycreds) 1540 defer sl.Shutdown() 1541 1542 checkLeafNodeConnected(t, s) 1543 1544 // To connect to main server. 1545 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 1546 1547 nc1, err := nats.Connect(url, createUserCreds(t, s, akp1)) 1548 if err != nil { 1549 t.Fatalf("Error on connect: %v", err) 1550 } 1551 defer nc1.Close() 1552 1553 // This is a client connected to the leaf node with no auth, 1554 // binding to account1 via leafnode connection. 1555 // To connect to leafnode server. 1556 lurl := fmt.Sprintf("nats://%s:%d", lopts.Host, lopts.Port) 1557 ncl, err := nats.Connect(lurl) 1558 if err != nil { 1559 t.Fatalf("Error on connect: %v", err) 1560 } 1561 defer ncl.Close() 1562 1563 lsub, _ := ncl.SubscribeSync("foo.test") 1564 1565 // Wait for the subs to propagate. LDS + foo.test 1566 checkSubInterest(t, s, a.GetName(), "foo.test", 2*time.Second) 1567 1568 // Now send from nc1 with account 1, should be received by our leafnode subscriber. 1569 nc1.Publish("foo.test", nil) 1570 1571 _, err = lsub.NextMsg(1 * time.Second) 1572 if err != nil { 1573 t.Fatalf("Error during wait for next message: %s", err) 1574 } 1575 } 1576 1577 func TestLeafNodeOperatorAndPermissions(t *testing.T) { 1578 s, opts, conf := runLeafNodeOperatorServer(t) 1579 defer os.Remove(conf) 1580 defer s.Shutdown() 1581 1582 acc, akp := createAccount(t, s) 1583 kp, _ := nkeys.CreateUser() 1584 pub, _ := kp.PublicKey() 1585 1586 // Create SRV user, with no limitations 1587 srvnuc := jwt.NewUserClaims(pub) 1588 srvujwt, err := srvnuc.Encode(akp) 1589 if err != nil { 1590 t.Fatalf("Error generating user JWT: %v", err) 1591 } 1592 seed, _ := kp.Seed() 1593 srvcreds := genCredsFile(t, srvujwt, seed) 1594 defer os.Remove(srvcreds) 1595 1596 // Create connection for SRV 1597 srvnc, err := nats.Connect(s.ClientURL(), nats.UserCredentials(srvcreds)) 1598 if err != nil { 1599 t.Fatalf("Error on connect: %v", err) 1600 } 1601 defer srvnc.Close() 1602 1603 // Create on the server "s" a subscription on "*" and on "foo". 1604 // We check that the subscription on "*" will be able to receive 1605 // messages since LEAF has publish permissions on "foo", so msg 1606 // should be received. 1607 srvsubStar, err := srvnc.SubscribeSync("*") 1608 if err != nil { 1609 t.Fatalf("Error on subscribe: %v", err) 1610 } 1611 srvsubFoo, err := srvnc.SubscribeSync("foo") 1612 if err != nil { 1613 t.Fatalf("Error on subscribe: %v", err) 1614 } 1615 srvnc.Flush() 1616 1617 // Create LEAF user, with pub perms on "foo" and sub perms on "bar" 1618 leafnuc := jwt.NewUserClaims(pub) 1619 leafnuc.Permissions.Pub.Allow.Add("foo") 1620 leafnuc.Permissions.Sub.Allow.Add("bar") 1621 leafnuc.Permissions.Sub.Allow.Add("baz") 1622 leafujwt, err := leafnuc.Encode(akp) 1623 if err != nil { 1624 t.Fatalf("Error generating user JWT: %v", err) 1625 } 1626 leafcreds := genCredsFile(t, leafujwt, seed) 1627 defer os.Remove(leafcreds) 1628 1629 content := ` 1630 port: -1 1631 server_name: LN 1632 leafnodes { 1633 remotes = [ 1634 { 1635 url: nats-leaf://127.0.0.1:%d 1636 credentials: '%s' 1637 } 1638 ] 1639 } 1640 ` 1641 config := fmt.Sprintf(content, opts.LeafNode.Port, leafcreds) 1642 lnconf := createConfFile(t, []byte(config)) 1643 defer os.Remove(lnconf) 1644 sl, _ := RunServerWithConfig(lnconf) 1645 defer sl.Shutdown() 1646 1647 checkLeafNodeConnected(t, s) 1648 1649 // Check that interest makes it to "sl" server. 1650 // This helper does not check for wildcard interest... 1651 checkSubInterest(t, sl, "$G", "foo", time.Second) 1652 1653 // Create connection for LEAF and subscribe on "bar" 1654 leafnc, err := nats.Connect(sl.ClientURL(), nats.UserCredentials(leafcreds)) 1655 if err != nil { 1656 t.Fatalf("Error on connect: %v", err) 1657 } 1658 defer leafnc.Close() 1659 1660 leafsub, err := leafnc.SubscribeSync("bar") 1661 if err != nil { 1662 t.Fatalf("Error on subscribe: %v", err) 1663 } 1664 1665 // To check that we can pull in 'baz'. 1666 leafsubpwc, err := leafnc.SubscribeSync("*") 1667 if err != nil { 1668 t.Fatalf("Error on subscribe: %v", err) 1669 } 1670 leafnc.Flush() 1671 1672 // Make sure the interest on "bar" from "sl" server makes it to the "s" server. 1673 checkSubInterest(t, s, acc.GetName(), "bar", time.Second) 1674 // Check for local interest too. 1675 checkSubInterest(t, sl, "$G", "bar", time.Second) 1676 1677 // Now that we know that "s" has received interest on "bar", create 1678 // the sub on "bar" locally on "s" 1679 srvsub, err := srvnc.SubscribeSync("bar") 1680 if err != nil { 1681 t.Fatalf("Error on subscribe: %v", err) 1682 } 1683 1684 srvnc.Publish("bar", []byte("hello")) 1685 if _, err := srvsub.NextMsg(time.Second); err != nil { 1686 t.Fatalf("SRV did not get message: %v", err) 1687 } 1688 if _, err := leafsub.NextMsg(time.Second); err != nil { 1689 t.Fatalf("LEAF did not get message: %v", err) 1690 } 1691 if _, err := leafsubpwc.NextMsg(time.Second); err != nil { 1692 t.Fatalf("LEAF did not get message: %v", err) 1693 } 1694 1695 // The leafnode has a sub on '*', that should pull in a publish to 'baz'. 1696 srvnc.Publish("baz", []byte("hello")) 1697 if _, err := leafsubpwc.NextMsg(time.Second); err != nil { 1698 t.Fatalf("LEAF did not get message: %v", err) 1699 } 1700 1701 // User LEAF user on "sl" server, publish on "foo" 1702 leafnc.Publish("foo", []byte("hello")) 1703 // The user SRV on "s" receives it because the LN connection 1704 // is allowed to publish on "foo". 1705 if _, err := srvsubFoo.NextMsg(time.Second); err != nil { 1706 t.Fatalf("SRV did not get message: %v", err) 1707 } 1708 // The wildcard subscription should get it too. 1709 if _, err := srvsubStar.NextMsg(time.Second); err != nil { 1710 t.Fatalf("SRV did not get message: %v", err) 1711 } 1712 1713 // However, even when using an unrestricted user connects to "sl" and 1714 // publishes on "bar", the user SRV on "s" should not receive it because 1715 // the LN connection is not allowed to publish (send msg over) on "bar". 1716 nc, err := nats.Connect(sl.ClientURL(), nats.UserCredentials(srvcreds)) 1717 if err != nil { 1718 t.Fatalf("Error on connect: %v", err) 1719 } 1720 defer nc.Close() 1721 nc.Publish("bar", []byte("should not received")) 1722 if _, err := srvsub.NextMsg(250 * time.Millisecond); err == nil { 1723 t.Fatal("Should not have received message") 1724 } 1725 } 1726 1727 func TestLeafNodeSignerUser(t *testing.T) { 1728 s, opts, _ := runLeafNodeOperatorServer(t) 1729 defer s.Shutdown() 1730 1731 // Setup the two accounts for this server. 1732 _, akp1 := createAccount(t, s) 1733 apk1, _ := akp1.PublicKey() 1734 1735 // add a signing key to the account 1736 akp2, err := nkeys.CreateAccount() 1737 if err != nil { 1738 t.Fatal(err) 1739 } 1740 apk2, _ := akp2.PublicKey() 1741 1742 token, err := s.AccountResolver().Fetch(apk1) 1743 if err != nil { 1744 t.Fatal(err) 1745 } 1746 ac, err := jwt.DecodeAccountClaims(token) 1747 if err != nil { 1748 t.Fatal(err) 1749 } 1750 1751 ac.SigningKeys.Add(apk2) 1752 okp, _ := nkeys.FromSeed(oSeed) 1753 token, err = ac.Encode(okp) 1754 if err != nil { 1755 t.Fatal(err) 1756 } 1757 // update the resolver 1758 account, _ := s.LookupAccount(apk1) 1759 err = s.AccountResolver().Store(apk1, token) 1760 if err != nil { 1761 t.Fatal(err) 1762 } 1763 s.UpdateAccountClaims(account, ac) 1764 1765 tt, err := s.AccountResolver().Fetch(apk1) 1766 if err != nil { 1767 t.Fatal(err) 1768 } 1769 ac2, err := jwt.DecodeAccountClaims(tt) 1770 if err != nil { 1771 t.Fatal(err) 1772 } 1773 if len(ac2.SigningKeys) != 1 { 1774 t.Fatal("signing key is not added") 1775 } 1776 if _, ok := ac2.SigningKeys[apk2]; !ok { 1777 t.Fatal("signing key is not added") 1778 } 1779 1780 // create an user signed by the signing key 1781 kp1, _ := nkeys.CreateUser() 1782 pub1, _ := kp1.PublicKey() 1783 nuc1 := jwt.NewUserClaims(pub1) 1784 nuc1.IssuerAccount = apk1 1785 ujwt1, err := nuc1.Encode(akp2) 1786 if err != nil { 1787 t.Fatalf("Error generating user JWT: %v", err) 1788 } 1789 1790 // Create the leaf node server using the first account. 1791 seed, _ := kp1.Seed() 1792 mycreds := genCredsFile(t, ujwt1, seed) 1793 1794 sl, _, _ := runSolicitWithCredentials(t, opts, mycreds) 1795 defer sl.Shutdown() 1796 1797 checkLeafNodeConnected(t, s) 1798 } 1799 1800 func TestLeafNodeExportsImports(t *testing.T) { 1801 // So we will create a main server with two accounts. The remote server, acting as a leaf node, will simply have 1802 // the $G global account and no auth. Make sure things work properly here. 1803 s, opts, _ := runLeafNodeOperatorServer(t) 1804 defer s.Shutdown() 1805 1806 // Setup the two accounts for this server. 1807 okp, _ := nkeys.FromSeed(oSeed) 1808 1809 // Create second account with exports 1810 acc2, akp2 := createAccount(t, s) 1811 akp2Pub, _ := akp2.PublicKey() 1812 akp2AC := jwt.NewAccountClaims(akp2Pub) 1813 streamExport := &jwt.Export{Subject: "foo.stream", Type: jwt.Stream} 1814 serviceExport := &jwt.Export{Subject: "req.echo", Type: jwt.Service} 1815 akp2AC.Exports.Add(streamExport, serviceExport) 1816 akp2ACJWT, err := akp2AC.Encode(okp) 1817 if err != nil { 1818 t.Fatalf("Error generating account JWT: %v", err) 1819 } 1820 1821 if err := s.AccountResolver().Store(akp2Pub, akp2ACJWT); err != nil { 1822 t.Fatalf("Account Resolver returned an error: %v", err) 1823 } 1824 s.UpdateAccountClaims(acc2, akp2AC) 1825 1826 // Now create the first account and add on the imports. This will be what is used in the leafnode. 1827 acc1, akp1 := createAccount(t, s) 1828 akp1Pub, _ := akp1.PublicKey() 1829 akp1AC := jwt.NewAccountClaims(akp1Pub) 1830 streamImport := &jwt.Import{Account: akp2Pub, Subject: "foo.stream", To: "import", Type: jwt.Stream} 1831 serviceImport := &jwt.Import{Account: akp2Pub, Subject: "import.request", To: "req.echo", Type: jwt.Service} 1832 akp1AC.Imports.Add(streamImport, serviceImport) 1833 akp1ACJWT, err := akp1AC.Encode(okp) 1834 if err != nil { 1835 t.Fatalf("Error generating account JWT: %v", err) 1836 } 1837 if err := s.AccountResolver().Store(akp1Pub, akp1ACJWT); err != nil { 1838 t.Fatalf("Account Resolver returned an error: %v", err) 1839 } 1840 s.UpdateAccountClaims(acc1, akp1AC) 1841 1842 // Create the user will we use to connect the leafnode. 1843 kp1, _ := nkeys.CreateUser() 1844 pub1, _ := kp1.PublicKey() 1845 nuc1 := jwt.NewUserClaims(pub1) 1846 ujwt1, err := nuc1.Encode(akp1) 1847 if err != nil { 1848 t.Fatalf("Error generating user JWT: %v", err) 1849 } 1850 1851 // Create the leaf node server using the first account. 1852 seed, _ := kp1.Seed() 1853 mycreds := genCredsFile(t, ujwt1, seed) 1854 1855 sl, lopts, _ := runSolicitWithCredentials(t, opts, mycreds) 1856 defer sl.Shutdown() 1857 1858 checkLeafNodeConnected(t, s) 1859 1860 // To connect to main server. 1861 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 1862 1863 // Imported 1864 nc1, err := nats.Connect(url, createUserCreds(t, s, akp1)) 1865 if err != nil { 1866 t.Fatalf("Error on connect: %v", err) 1867 } 1868 defer nc1.Close() 1869 1870 // Exported 1871 nc2, err := nats.Connect(url, createUserCreds(t, s, akp2)) 1872 if err != nil { 1873 t.Fatalf("Error on connect: %v", err) 1874 } 1875 defer nc2.Close() 1876 1877 // Leaf node connection. 1878 lurl := fmt.Sprintf("nats://%s:%d", lopts.Host, lopts.Port) 1879 ncl, err := nats.Connect(lurl) 1880 if err != nil { 1881 t.Fatalf("Error on connect: %v", err) 1882 } 1883 defer ncl.Close() 1884 1885 // So everything should be setup here. So let's test streams first. 1886 lsub, _ := ncl.SubscribeSync("import.foo.stream") 1887 1888 // Wait for all subs to propagate. 1889 checkSubInterest(t, s, acc1.GetName(), "import.foo.stream", time.Second) 1890 1891 // Pub to other account with export on original subject. 1892 nc2.Publish("foo.stream", nil) 1893 1894 _, err = lsub.NextMsg(1 * time.Second) 1895 if err != nil { 1896 t.Fatalf("Error during wait for next message: %s", err) 1897 } 1898 1899 // Services 1900 // Create listener on nc2 1901 nc2.Subscribe("req.echo", func(msg *nats.Msg) { 1902 nc2.Publish(msg.Reply, []byte("WORKED")) 1903 }) 1904 nc2.Flush() 1905 1906 // Now send the request on the leaf node client. 1907 if _, err := ncl.Request("import.request", []byte("fingers crossed"), 500*time.Millisecond); err != nil { 1908 t.Fatalf("Did not receive response: %v", err) 1909 } 1910 } 1911 1912 func TestLeafNodeExportImportComplexSetup(t *testing.T) { 1913 content := ` 1914 port: -1 1915 operator = "./configs/nkeys/op.jwt" 1916 resolver = MEMORY 1917 cluster { 1918 port: -1 1919 name: xyz 1920 } 1921 leafnodes { 1922 listen: "127.0.0.1:-1" 1923 } 1924 ` 1925 conf := createConfFile(t, []byte(content)) 1926 s1, s1Opts := RunServerWithConfig(conf) 1927 defer s1.Shutdown() 1928 1929 content = fmt.Sprintf(` 1930 port: -1 1931 operator = "./configs/nkeys/op.jwt" 1932 resolver = MEMORY 1933 cluster { 1934 port: -1 1935 name: xyz 1936 routes: ["nats://%s:%d"] 1937 } 1938 leafnodes { 1939 listen: "127.0.0.1:-1" 1940 } 1941 `, s1Opts.Cluster.Host, s1Opts.Cluster.Port) 1942 conf = createConfFile(t, []byte(content)) 1943 s2, s2Opts := RunServerWithConfig(conf) 1944 defer s2.Shutdown() 1945 1946 // Setup the two accounts for this server. 1947 okp, _ := nkeys.FromSeed(oSeed) 1948 1949 // Create second account with exports 1950 acc2, akp2 := createAccount(t, s1) 1951 akp2Pub, _ := akp2.PublicKey() 1952 akp2AC := jwt.NewAccountClaims(akp2Pub) 1953 streamExport := &jwt.Export{Subject: "foo.stream", Type: jwt.Stream} 1954 serviceExport := &jwt.Export{Subject: "req.echo", Type: jwt.Service} 1955 akp2AC.Exports.Add(streamExport, serviceExport) 1956 akp2ACJWT, err := akp2AC.Encode(okp) 1957 if err != nil { 1958 t.Fatalf("Error generating account JWT: %v", err) 1959 } 1960 1961 if err := s1.AccountResolver().Store(akp2Pub, akp2ACJWT); err != nil { 1962 t.Fatalf("Account Resolver returned an error: %v", err) 1963 } 1964 s1.UpdateAccountClaims(acc2, akp2AC) 1965 1966 // Now create the first account and add on the imports. This will be what is used in the leafnode. 1967 acc1, akp1 := createAccount(t, s1) 1968 akp1Pub, _ := akp1.PublicKey() 1969 akp1AC := jwt.NewAccountClaims(akp1Pub) 1970 streamImport := &jwt.Import{Account: akp2Pub, Subject: "foo.stream", To: "import", Type: jwt.Stream} 1971 serviceImport := &jwt.Import{Account: akp2Pub, Subject: "import.request", To: "req.echo", Type: jwt.Service} 1972 akp1AC.Imports.Add(streamImport, serviceImport) 1973 akp1ACJWT, err := akp1AC.Encode(okp) 1974 if err != nil { 1975 t.Fatalf("Error generating account JWT: %v", err) 1976 } 1977 if err := s1.AccountResolver().Store(akp1Pub, akp1ACJWT); err != nil { 1978 t.Fatalf("Account Resolver returned an error: %v", err) 1979 } 1980 s1.UpdateAccountClaims(acc1, akp1AC) 1981 1982 if err := s2.AccountResolver().Store(akp2Pub, akp2ACJWT); err != nil { 1983 t.Fatalf("Account Resolver returned an error: %v", err) 1984 } 1985 // Just make sure that account object registered in S2 is not acc2 1986 if a, err := s2.LookupAccount(acc2.Name); err != nil || a == acc2 { 1987 t.Fatalf("Lookup account error: %v - accounts are same: %v", err, a == acc2) 1988 } 1989 1990 if err := s2.AccountResolver().Store(akp1Pub, akp1ACJWT); err != nil { 1991 t.Fatalf("Account Resolver returned an error: %v", err) 1992 } 1993 // Just make sure that account object registered in S2 is not acc1 1994 if a, err := s2.LookupAccount(acc1.Name); err != nil || a == acc1 { 1995 t.Fatalf("Lookup account error: %v - accounts are same: %v", err, a == acc1) 1996 } 1997 1998 // Create the user will we use to connect the leafnode. 1999 kp1, _ := nkeys.CreateUser() 2000 pub1, _ := kp1.PublicKey() 2001 nuc1 := jwt.NewUserClaims(pub1) 2002 ujwt1, err := nuc1.Encode(akp1) 2003 if err != nil { 2004 t.Fatalf("Error generating user JWT: %v", err) 2005 } 2006 2007 // Create the leaf node server using the first account. 2008 seed, _ := kp1.Seed() 2009 mycreds := genCredsFile(t, ujwt1, seed) 2010 2011 sl, lopts, _ := runSolicitWithCredentials(t, s1Opts, mycreds) 2012 defer sl.Shutdown() 2013 2014 checkLeafNodeConnected(t, s1) 2015 2016 // Url to server s2 2017 s2URL := fmt.Sprintf("nats://%s:%d", s2Opts.Host, s2Opts.Port) 2018 2019 // Imported 2020 nc1, err := nats.Connect(s2URL, createUserCreds(t, s2, akp1)) 2021 if err != nil { 2022 t.Fatalf("Error on connect: %v", err) 2023 } 2024 defer nc1.Close() 2025 2026 // Exported 2027 nc2, err := nats.Connect(s2URL, createUserCreds(t, s2, akp2)) 2028 if err != nil { 2029 t.Fatalf("Error on connect: %v", err) 2030 } 2031 defer nc2.Close() 2032 2033 // Leaf node connection. 2034 lurl := fmt.Sprintf("nats://%s:%d", lopts.Host, lopts.Port) 2035 ncl, err := nats.Connect(lurl) 2036 if err != nil { 2037 t.Fatalf("Error on connect: %v", err) 2038 } 2039 defer ncl.Close() 2040 2041 // So everything should be setup here. So let's test streams first. 2042 lsub, _ := ncl.SubscribeSync("import.foo.stream") 2043 2044 // Wait for the sub to propagate to s2. LDS + subject above. 2045 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 2046 if acc1.RoutedSubs() != 6 { 2047 return fmt.Errorf("Still no routed subscription: %d", acc1.RoutedSubs()) 2048 } 2049 return nil 2050 }) 2051 2052 // Pub to other account with export on original subject. 2053 nc2.Publish("foo.stream", nil) 2054 2055 if _, err = lsub.NextMsg(1 * time.Second); err != nil { 2056 t.Fatalf("Did not receive stream message: %s", err) 2057 } 2058 2059 // Services 2060 // Create listener on nc2 (which connects to s2) 2061 gotIt := int32(0) 2062 nc2.Subscribe("req.echo", func(msg *nats.Msg) { 2063 atomic.AddInt32(&gotIt, 1) 2064 nc2.Publish(msg.Reply, []byte("WORKED")) 2065 }) 2066 nc2.Flush() 2067 2068 // Wait for it to make it across. 2069 time.Sleep(250 * time.Millisecond) 2070 2071 // Now send the request on the leaf node client. 2072 if _, err := ncl.Request("import.request", []byte("fingers crossed"), 5500*time.Millisecond); err != nil { 2073 if atomic.LoadInt32(&gotIt) == 0 { 2074 t.Fatalf("Request was not received") 2075 } 2076 t.Fatalf("Did not receive response: %v", err) 2077 } 2078 } 2079 2080 func TestLeafNodeInfoURLs(t *testing.T) { 2081 for _, test := range []struct { 2082 name string 2083 useAdvertise bool 2084 }{ 2085 { 2086 "without advertise", 2087 false, 2088 }, 2089 { 2090 "with advertise", 2091 true, 2092 }, 2093 } { 2094 t.Run(test.name, func(t *testing.T) { 2095 opts := testDefaultOptionsForLeafNodes() 2096 opts.Cluster.Name = "A" 2097 opts.Cluster.Port = -1 2098 opts.LeafNode.Host = "127.0.0.1" 2099 if test.useAdvertise { 2100 opts.LeafNode.Advertise = "me:1" 2101 } 2102 s1 := RunServer(opts) 2103 defer s1.Shutdown() 2104 2105 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 2106 defer lc.Close() 2107 info := checkInfoMsg(t, lc) 2108 if sz := len(info.LeafNodeURLs); sz != 1 { 2109 t.Fatalf("Expected LeafNodeURLs array to be size 1, got %v", sz) 2110 } 2111 var s1LNURL string 2112 if test.useAdvertise { 2113 s1LNURL = "me:1" 2114 } else { 2115 s1LNURL = net.JoinHostPort(opts.LeafNode.Host, strconv.Itoa(opts.LeafNode.Port)) 2116 } 2117 if url := info.LeafNodeURLs[0]; url != s1LNURL { 2118 t.Fatalf("Expected URL to be %s, got %s", s1LNURL, url) 2119 } 2120 lc.Close() 2121 2122 opts2 := testDefaultOptionsForLeafNodes() 2123 opts2.Cluster.Name = "A" 2124 opts2.Cluster.Port = -1 2125 opts2.Routes = server.RoutesFromStr(fmt.Sprintf("nats://%s:%d", opts.Cluster.Host, opts.Cluster.Port)) 2126 opts2.LeafNode.Host = "127.0.0.1" 2127 if test.useAdvertise { 2128 opts2.LeafNode.Advertise = "me:2" 2129 } 2130 s2 := RunServer(opts2) 2131 defer s2.Shutdown() 2132 2133 checkClusterFormed(t, s1, s2) 2134 2135 lc = createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 2136 defer lc.Close() 2137 info = checkInfoMsg(t, lc) 2138 if sz := len(info.LeafNodeURLs); sz != 2 { 2139 t.Fatalf("Expected LeafNodeURLs array to be size 2, got %v", sz) 2140 } 2141 var s2LNURL string 2142 if test.useAdvertise { 2143 s2LNURL = "me:2" 2144 } else { 2145 s2LNURL = net.JoinHostPort(opts2.LeafNode.Host, strconv.Itoa(opts2.LeafNode.Port)) 2146 } 2147 var ok [2]int 2148 for _, url := range info.LeafNodeURLs { 2149 if url == s1LNURL { 2150 ok[0]++ 2151 } else if url == s2LNURL { 2152 ok[1]++ 2153 } 2154 } 2155 for i, res := range ok { 2156 if res != 1 { 2157 t.Fatalf("URL from server %v was found %v times", i+1, res) 2158 } 2159 } 2160 lc.Close() 2161 2162 // Remove s2, and wait for route to be lost on s1. 2163 s2.Shutdown() 2164 checkNumRoutes(t, s1, 0) 2165 2166 // Now check that s1 returns only itself in the URLs array. 2167 lc = createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 2168 defer lc.Close() 2169 info = checkInfoMsg(t, lc) 2170 if sz := len(info.LeafNodeURLs); sz != 1 { 2171 t.Fatalf("Expected LeafNodeURLs array to be size 1, got %v", sz) 2172 } 2173 if url := info.LeafNodeURLs[0]; url != s1LNURL { 2174 t.Fatalf("Expected URL to be %s, got %s", s1LNURL, url) 2175 } 2176 lc.Close() 2177 2178 s1.Shutdown() 2179 2180 // Now we need a configuration where both s1 and s2 have a route 2181 // to each other, so we need explicit configuration. We are trying 2182 // to get S1->S2 and S2->S1 so one of the route is dropped. This 2183 // should not affect the number of URLs reported in INFO. 2184 2185 opts.Cluster.Port = 5223 2186 opts.Routes = server.RoutesFromStr(fmt.Sprintf("nats://%s:5224", opts2.Host)) 2187 s1, _ = server.NewServer(opts) 2188 defer s1.Shutdown() 2189 2190 opts2.Cluster.Port = 5224 2191 opts2.Routes = server.RoutesFromStr(fmt.Sprintf("nats://%s:5223", opts.Host)) 2192 s2, _ = server.NewServer(opts2) 2193 defer s2.Shutdown() 2194 2195 // Start this way to increase chance of having the two connect 2196 // to each other at the same time. This will cause one of the 2197 // route to be dropped. 2198 wg := &sync.WaitGroup{} 2199 wg.Add(2) 2200 go func() { 2201 s1.Start() 2202 wg.Done() 2203 }() 2204 go func() { 2205 s2.Start() 2206 wg.Done() 2207 }() 2208 2209 checkClusterFormed(t, s1, s2) 2210 2211 lc = createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 2212 defer lc.Close() 2213 info = checkInfoMsg(t, lc) 2214 if sz := len(info.LeafNodeURLs); sz != 2 { 2215 t.Fatalf("Expected LeafNodeURLs array to be size 2, got %v", sz) 2216 } 2217 ok[0], ok[1] = 0, 0 2218 for _, url := range info.LeafNodeURLs { 2219 if url == s1LNURL { 2220 ok[0]++ 2221 } else if url == s2LNURL { 2222 ok[1]++ 2223 } 2224 } 2225 for i, res := range ok { 2226 if res != 1 { 2227 t.Fatalf("URL from server %v was found %v times", i+1, res) 2228 } 2229 } 2230 }) 2231 } 2232 } 2233 2234 func TestLeafNodeFailover(t *testing.T) { 2235 server.SetGatewaysSolicitDelay(50 * time.Millisecond) 2236 defer server.ResetGatewaysSolicitDelay() 2237 2238 ca := createClusterWithName(t, "A", 2) 2239 defer shutdownCluster(ca) 2240 2241 cb := createClusterWithName(t, "B", 1, ca) 2242 defer shutdownCluster(cb) 2243 2244 // Start a server that creates LeafNode connection to first 2245 // server in cluster A. 2246 s, opts := runSolicitLeafServer(ca.opts[0]) 2247 defer s.Shutdown() 2248 2249 // Shutdown that server on A. 2250 ca.servers[0].Shutdown() 2251 2252 // Make sure that s reconnects its LN connection 2253 checkLeafNodeConnected(t, ca.servers[1]) 2254 2255 // Verify that LeafNode info protocol is sent to the server `s` 2256 // with list of new servers. To do that, we will restart 2257 // ca[0] but with a different LN listen port. 2258 ca.opts[0].Port = -1 2259 ca.opts[0].Cluster.Port = -1 2260 ca.opts[0].Routes = server.RoutesFromStr(fmt.Sprintf("nats://%s:%d", ca.opts[1].Cluster.Host, ca.opts[1].Cluster.Port)) 2261 ca.opts[0].LeafNode.Port = -1 2262 newa0 := RunServer(ca.opts[0]) 2263 defer newa0.Shutdown() 2264 2265 checkClusterFormed(t, newa0, ca.servers[1]) 2266 2267 // Shutdown the server the LN is currently connected to. It should 2268 // reconnect to newa0. 2269 ca.servers[1].Shutdown() 2270 checkLeafNodeConnected(t, newa0) 2271 2272 // Now shutdown newa0 and make sure `s` does not reconnect 2273 // to server in gateway. 2274 newa0.Shutdown() 2275 2276 // Wait for more than the reconnect attempts. 2277 time.Sleep(opts.LeafNode.ReconnectInterval + 50*time.Millisecond) 2278 2279 checkLeafNodeConnections(t, cb.servers[0], 0) 2280 } 2281 2282 func TestLeafNodeAdvertise(t *testing.T) { 2283 // Create a dummy listener which will we use for the advertise address. 2284 // We will then stop the server and the test will be a success if 2285 // this listener accepts a connection. 2286 ch := make(chan struct{}, 1) 2287 l, err := net.Listen("tcp", "127.0.0.1:0") 2288 if err != nil { 2289 t.Fatalf("Error starting listener: %v", err) 2290 } 2291 defer l.Close() 2292 2293 wg := sync.WaitGroup{} 2294 wg.Add(1) 2295 go func() { 2296 defer wg.Done() 2297 c, _ := l.Accept() 2298 if c != nil { 2299 c.Close() 2300 } 2301 l.Close() 2302 ch <- struct{}{} 2303 }() 2304 2305 port := l.Addr().(*net.TCPAddr).Port 2306 2307 o2 := testDefaultOptionsForLeafNodes() 2308 o2.LeafNode.Advertise = fmt.Sprintf("127.0.0.1:%d", port) 2309 o2.Cluster.Name = "A" 2310 o2.Cluster.Port = -1 2311 s2 := RunServer(o2) 2312 defer s2.Shutdown() 2313 2314 o1 := testDefaultOptionsForLeafNodes() 2315 o1.Cluster.Name = "A" 2316 o1.Cluster.Port = -1 2317 o1.Routes = server.RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", o2.Cluster.Port)) 2318 s1 := RunServer(o1) 2319 defer s1.Shutdown() 2320 2321 checkClusterFormed(t, s1, s2) 2322 2323 // Start a server that connects to s1. It should be made aware 2324 // of s2 (and its advertise address). 2325 s, _ := runSolicitLeafServer(o1) 2326 defer s.Shutdown() 2327 2328 // Wait for leaf node connection to be established on s1. 2329 checkLeafNodeConnected(t, s1) 2330 2331 // Shutdown s1. The listener that we created should be the one 2332 // receiving the connection from s. 2333 s1.Shutdown() 2334 2335 select { 2336 case <-ch: 2337 case <-time.After(5 * time.Second): 2338 t.Fatalf("Server did not reconnect to advertised address") 2339 } 2340 wg.Wait() 2341 } 2342 2343 func TestLeafNodeConnectionLimitsSingleServer(t *testing.T) { 2344 s, opts, _ := runLeafNodeOperatorServer(t) 2345 defer s.Shutdown() 2346 2347 // Setup account and a user that will be used by the remote leaf node server. 2348 // createAccount automatically registers with resolver etc.. 2349 acc, akp := createAccount(t, s) 2350 2351 // Now update with limits for lead node connections. 2352 const maxleafs = 2 2353 2354 apub, _ := akp.PublicKey() 2355 nac := jwt.NewAccountClaims(apub) 2356 nac.Limits.LeafNodeConn = maxleafs 2357 s.UpdateAccountClaims(acc, nac) 2358 2359 // Make sure we have the limits updated in acc. 2360 if mleafs := acc.MaxActiveLeafNodes(); mleafs != maxleafs { 2361 t.Fatalf("Expected to have max leafnodes of %d, got %d", maxleafs, mleafs) 2362 } 2363 2364 // Create the user credentials for the leadnode connection. 2365 kp, _ := nkeys.CreateUser() 2366 pub, _ := kp.PublicKey() 2367 nuc := jwt.NewUserClaims(pub) 2368 ujwt, err := nuc.Encode(akp) 2369 if err != nil { 2370 t.Fatalf("Error generating user JWT: %v", err) 2371 } 2372 seed, _ := kp.Seed() 2373 mycreds := genCredsFile(t, ujwt, seed) 2374 2375 checkAccConnectionCounts := func(t *testing.T, expected int) { 2376 t.Helper() 2377 checkFor(t, 2*time.Second, 15*time.Millisecond, func() error { 2378 // Make sure we are accounting properly here. 2379 if nln := acc.NumLeafNodes(); nln != expected { 2380 return fmt.Errorf("expected %v leaf node, got %d", expected, nln) 2381 } 2382 // clients and leafnodes counted together. 2383 if nc := acc.NumConnections(); nc != expected { 2384 return fmt.Errorf("expected %v for total connections, got %d", expected, nc) 2385 } 2386 return nil 2387 }) 2388 } 2389 2390 checkAccNLF := func(n int) { 2391 t.Helper() 2392 checkFor(t, time.Second, 10*time.Millisecond, func() error { 2393 if nln := acc.NumLeafNodes(); nln != n { 2394 return fmt.Errorf("Expected %d leaf node, got %d", n, nln) 2395 } 2396 return nil 2397 }) 2398 } 2399 2400 sl, _, _ := runSolicitWithCredentials(t, opts, mycreds) 2401 defer sl.Shutdown() 2402 2403 checkLeafNodeConnections(t, s, 1) 2404 2405 // Make sure we are accounting properly here. 2406 checkAccNLF(1) 2407 // clients and leafnodes counted together. 2408 if nc := acc.NumConnections(); nc != 1 { 2409 t.Fatalf("Expected 1 for total connections, got %d", nc) 2410 } 2411 2412 s2, _, _ := runSolicitWithCredentials(t, opts, mycreds) 2413 defer s2.Shutdown() 2414 checkLeafNodeConnections(t, s, 2) 2415 checkAccConnectionCounts(t, 2) 2416 2417 s2.Shutdown() 2418 checkLeafNodeConnections(t, s, 1) 2419 checkAccConnectionCounts(t, 1) 2420 2421 // Make sure we are accounting properly here. 2422 checkAccNLF(1) 2423 // clients and leafnodes counted together. 2424 if nc := acc.NumConnections(); nc != 1 { 2425 t.Fatalf("Expected 1 for total connections, got %d", nc) 2426 } 2427 2428 // Now add back the second one as #3. 2429 s3, _, _ := runSolicitWithCredentials(t, opts, mycreds) 2430 defer s3.Shutdown() 2431 checkLeafNodeConnections(t, s, 2) 2432 2433 checkAccConnectionCounts(t, 2) 2434 2435 // Once we are here we should not be able to create anymore. Limit == 2. 2436 s4, _, _ := runSolicitWithCredentials(t, opts, mycreds) 2437 defer s4.Shutdown() 2438 2439 checkAccConnectionCounts(t, 2) 2440 2441 // Make sure s4 has 0 still. We need checkFor because it is possible 2442 // that when we check we have actually the connection registered for 2443 // a short period before it is closed due to limit. 2444 checkFor(t, time.Second, 15*time.Millisecond, func() error { 2445 if nln := s4.NumLeafNodes(); nln != 0 { 2446 return fmt.Errorf("Expected no leafnodes accounted for in s4, got %d", nln) 2447 } 2448 return nil 2449 }) 2450 2451 // Make sure this is still 2. 2452 checkLeafNodeConnections(t, s, 2) 2453 } 2454 2455 func TestLeafNodeConnectionLimitsCluster(t *testing.T) { 2456 content := ` 2457 port: -1 2458 operator = "./configs/nkeys/op.jwt" 2459 system_account = "AD2VB6C25DQPEUUQ7KJBUFX2J4ZNVBPOHSCBISC7VFZXVWXZA7VASQZG" 2460 resolver = MEMORY 2461 cluster { 2462 port: -1 2463 name: xyz 2464 } 2465 leafnodes { 2466 listen: "127.0.0.1:-1" 2467 } 2468 resolver_preload = { 2469 AD2VB6C25DQPEUUQ7KJBUFX2J4ZNVBPOHSCBISC7VFZXVWXZA7VASQZG : "eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJDSzU1UERKSUlTWU5QWkhLSUpMVURVVTdJT1dINlM3UkE0RUc2TTVGVUQzUEdGQ1RWWlJRIiwiaWF0IjoxNTQzOTU4NjU4LCJpc3MiOiJPQ0FUMzNNVFZVMlZVT0lNR05HVU5YSjY2QUgyUkxTREFGM01VQkNZQVk1UU1JTDY1TlFNNlhRRyIsInN1YiI6IkFEMlZCNkMyNURRUEVVVVE3S0pCVUZYMko0Wk5WQlBPSFNDQklTQzdWRlpYVldYWkE3VkFTUVpHIiwidHlwZSI6ImFjY291bnQiLCJuYXRzIjp7ImxpbWl0cyI6e319fQ.7m1fysYUsBw15Lj88YmYoHxOI4HlOzu6qgP8Zg-1q9mQXUURijuDGVZrtb7gFYRlo-nG9xZyd2ZTRpMA-b0xCQ" 2470 } 2471 ` 2472 conf := createConfFile(t, []byte(content)) 2473 s1, s1Opts := RunServerWithConfig(conf) 2474 defer s1.Shutdown() 2475 2476 content = fmt.Sprintf(` 2477 port: -1 2478 operator = "./configs/nkeys/op.jwt" 2479 system_account = "AD2VB6C25DQPEUUQ7KJBUFX2J4ZNVBPOHSCBISC7VFZXVWXZA7VASQZG" 2480 resolver = MEMORY 2481 cluster { 2482 port: -1 2483 name: xyz 2484 routes: ["nats://%s:%d"] 2485 } 2486 leafnodes { 2487 listen: "127.0.0.1:-1" 2488 } 2489 resolver_preload = { 2490 AD2VB6C25DQPEUUQ7KJBUFX2J4ZNVBPOHSCBISC7VFZXVWXZA7VASQZG : "eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJDSzU1UERKSUlTWU5QWkhLSUpMVURVVTdJT1dINlM3UkE0RUc2TTVGVUQzUEdGQ1RWWlJRIiwiaWF0IjoxNTQzOTU4NjU4LCJpc3MiOiJPQ0FUMzNNVFZVMlZVT0lNR05HVU5YSjY2QUgyUkxTREFGM01VQkNZQVk1UU1JTDY1TlFNNlhRRyIsInN1YiI6IkFEMlZCNkMyNURRUEVVVVE3S0pCVUZYMko0Wk5WQlBPSFNDQklTQzdWRlpYVldYWkE3VkFTUVpHIiwidHlwZSI6ImFjY291bnQiLCJuYXRzIjp7ImxpbWl0cyI6e319fQ.7m1fysYUsBw15Lj88YmYoHxOI4HlOzu6qgP8Zg-1q9mQXUURijuDGVZrtb7gFYRlo-nG9xZyd2ZTRpMA-b0xCQ" 2491 } 2492 `, s1Opts.Cluster.Host, s1Opts.Cluster.Port) 2493 conf = createConfFile(t, []byte(content)) 2494 s2, s2Opts := RunServerWithConfig(conf) 2495 defer s2.Shutdown() 2496 2497 // Setup the two accounts for this server. 2498 okp, _ := nkeys.FromSeed(oSeed) 2499 2500 // Setup account and a user that will be used by the remote leaf node server. 2501 // createAccount automatically registers with resolver etc.. 2502 acc, akp := createAccount(t, s1) 2503 2504 // Now update with limits for lead node connections. 2505 const maxleafs = 10 2506 2507 apub, _ := akp.PublicKey() 2508 nac := jwt.NewAccountClaims(apub) 2509 nac.Limits.LeafNodeConn = maxleafs 2510 2511 ajwt, err := nac.Encode(okp) 2512 if err != nil { 2513 t.Fatalf("Error generating account JWT: %v", err) 2514 } 2515 if err := s1.AccountResolver().Store(apub, ajwt); err != nil { 2516 t.Fatalf("Account Resolver returned an error: %v", err) 2517 } 2518 s1.UpdateAccountClaims(acc, nac) 2519 2520 if err := s2.AccountResolver().Store(apub, ajwt); err != nil { 2521 t.Fatalf("Account Resolver returned an error: %v", err) 2522 } 2523 // Make sure that account object registered in S2 is not acc2 2524 acc2, err := s2.LookupAccount(acc.Name) 2525 if err != nil || acc == acc2 { 2526 t.Fatalf("Lookup account error: %v - accounts are same: %v", err, acc == acc2) 2527 } 2528 2529 // Create the user credentials for the leadnode connection. 2530 kp, _ := nkeys.CreateUser() 2531 pub, _ := kp.PublicKey() 2532 nuc := jwt.NewUserClaims(pub) 2533 ujwt, err := nuc.Encode(akp) 2534 if err != nil { 2535 t.Fatalf("Error generating user JWT: %v", err) 2536 } 2537 seed, _ := kp.Seed() 2538 mycreds := genCredsFile(t, ujwt, seed) 2539 2540 loop := maxleafs / 2 2541 2542 // Now create maxleafs/2 leaf node servers on each operator server. 2543 for i := 0; i < loop; i++ { 2544 sl1, _, _ := runSolicitWithCredentials(t, s1Opts, mycreds) 2545 defer sl1.Shutdown() 2546 2547 sl2, _, _ := runSolicitWithCredentials(t, s2Opts, mycreds) 2548 defer sl2.Shutdown() 2549 } 2550 2551 checkLeafNodeConnections(t, s1, loop) 2552 checkLeafNodeConnections(t, s2, loop) 2553 2554 // Now check that we have the remotes registered. This will prove we are sending 2555 // and processing the leaf node connect events properly etc. 2556 checkAccLFCount := func(acc *server.Account, remote bool, n int) { 2557 t.Helper() 2558 checkFor(t, time.Second, 10*time.Millisecond, func() error { 2559 str := "" 2560 var nln int 2561 if remote { 2562 nln = acc.NumRemoteLeafNodes() 2563 str = "remote" 2564 } else { 2565 nln = acc.NumLeafNodes() 2566 } 2567 if nln != n { 2568 return fmt.Errorf("number of expected %sleaf nodes is %v, got %v", str, n, nln) 2569 } 2570 return nil 2571 }) 2572 } 2573 checkAccLFCount(acc, true, loop) 2574 checkAccLFCount(acc2, true, loop) 2575 2576 // Now that we are here we should not be allowed anymore leaf nodes. 2577 l, _, _ := runSolicitWithCredentials(t, s1Opts, mycreds) 2578 defer l.Shutdown() 2579 2580 checkAccLFCount(acc, false, maxleafs) 2581 // Should still be at loop size. 2582 checkLeafNodeConnections(t, s1, loop) 2583 2584 l, _, _ = runSolicitWithCredentials(t, s2Opts, mycreds) 2585 defer l.Shutdown() 2586 checkAccLFCount(acc2, false, maxleafs) 2587 // Should still be at loop size. 2588 checkLeafNodeConnections(t, s2, loop) 2589 } 2590 2591 func TestLeafNodeSwitchGatewayToInterestModeOnly(t *testing.T) { 2592 server.SetGatewaysSolicitDelay(50 * time.Millisecond) 2593 defer server.ResetGatewaysSolicitDelay() 2594 2595 ca := createClusterWithName(t, "A", 3) 2596 defer shutdownCluster(ca) 2597 cb := createClusterWithName(t, "B", 3, ca) 2598 defer shutdownCluster(cb) 2599 2600 // Create client on a server in cluster A 2601 opts := ca.opts[0] 2602 c := createClientConn(t, opts.Host, opts.Port) 2603 defer c.Close() 2604 2605 send, expect := setupConn(t, c) 2606 send("PING\r\n") 2607 expect(pongRe) 2608 2609 // Send a message from this client on "foo" so that B 2610 // registers a no-interest for account "$G" 2611 send("PUB foo 2\r\nok\r\nPING\r\n") 2612 expect(pongRe) 2613 2614 // Create a leaf node connection on a server in cluster B 2615 opts = cb.opts[0] 2616 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 2617 defer lc.Close() 2618 2619 // This is for our global responses since we are setting up GWs above. 2620 leafSend, leafExpect := setupLeaf(t, lc, 8) 2621 leafSend("PING\r\n") 2622 leafExpect(pongRe) 2623 } 2624 2625 // The MSG proto for routes and gateways is RMSG, and we have an 2626 // optimization that a scratch buffer has RMSG and when doing a 2627 // client we just start at scratch[1]. For leaf nodes its LMSG and we 2628 // rewrite scratch[0], but never reset it which causes protocol 2629 // errors when used with routes or gateways after use to send 2630 // to a leafnode. 2631 // We will create a server with a leafnode connection and a route 2632 // and a gateway connection. 2633 2634 // route connections to simulate. 2635 func TestLeafNodeResetsMSGProto(t *testing.T) { 2636 server.GatewayDoNotForceInterestOnlyMode(true) 2637 defer server.GatewayDoNotForceInterestOnlyMode(false) 2638 2639 opts := testDefaultOptionsForLeafNodes() 2640 opts.Cluster.Name = "xyz" 2641 opts.Cluster.Host = opts.Host 2642 opts.Cluster.Port = -1 2643 opts.Gateway.Name = "xyz" 2644 opts.Gateway.Host = opts.Host 2645 opts.Gateway.Port = -1 2646 opts.Accounts = []*server.Account{server.NewAccount("$SYS")} 2647 opts.SystemAccount = "$SYS" 2648 2649 s := RunServer(opts) 2650 defer s.Shutdown() 2651 2652 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 2653 defer lc.Close() 2654 2655 leafSend, leafExpect := setupConn(t, lc) 2656 2657 // To avoid possible INFO when switching to interest mode only, 2658 // delay start of gateway. 2659 time.Sleep(500 * time.Millisecond) 2660 2661 gw := createGatewayConn(t, opts.Gateway.Host, opts.Gateway.Port) 2662 defer gw.Close() 2663 2664 gwSend, gwExpect := setupGatewayConn(t, gw, "A", "xyz") 2665 gwSend("PING\r\n") 2666 gwExpect(pongRe) 2667 2668 // This is for our global responses since we are setting up GWs above. 2669 leafExpect(lsubRe) 2670 2671 // Now setup interest in the leaf node for 'foo'. 2672 leafSend("LS+ foo\r\nPING\r\n") 2673 leafExpect(pongRe) 2674 2675 // Send msg from the gateway. 2676 gwSend("RMSG $G foo 2\r\nok\r\nPING\r\n") 2677 gwExpect(pongRe) 2678 2679 leafExpect(lmsgRe) 2680 2681 // At this point the gw inside our main server's scratch buffer is LMSG. When we do 2682 // same with a connected route with interest it should fail. 2683 rc := createRouteConn(t, opts.Cluster.Host, opts.Cluster.Port) 2684 defer rc.Close() 2685 checkInfoMsg(t, rc) 2686 routeSend, routeExpect := setupRouteEx(t, rc, opts, "RC") 2687 2688 routeSend("RS+ $G foo\r\nPING\r\n") 2689 routeExpect(pongRe) 2690 2691 // This is for the route interest we just created. 2692 leafExpect(lsubRe) 2693 2694 // Send msg from the gateway. 2695 gwSend("RMSG $G foo 2\r\nok\r\nPING\r\n") 2696 gwExpect(pongRe) 2697 2698 leafExpect(lmsgRe) 2699 2700 // Now make sure we get it on route. This will fail with the proto bug. 2701 routeExpect(rmsgRe) 2702 } 2703 2704 // We need to make sure that as a remote server we also send our local subs on connect. 2705 func TestLeafNodeSendsRemoteSubsOnConnect(t *testing.T) { 2706 s, opts := runLeafServer() 2707 defer s.Shutdown() 2708 2709 sl, slOpts := runSolicitLeafServer(opts) 2710 defer sl.Shutdown() 2711 2712 checkLeafNodeConnected(t, s) 2713 s.Shutdown() 2714 2715 c := createClientConn(t, slOpts.Host, slOpts.Port) 2716 defer c.Close() 2717 2718 send, expect := setupConn(t, c) 2719 send("SUB foo 1\r\n") 2720 send("PING\r\n") 2721 expect(pongRe) 2722 2723 // Need to restart it on the same port. 2724 s, _ = runLeafServerOnPort(opts.LeafNode.Port) 2725 defer s.Shutdown() 2726 checkLeafNodeConnected(t, s) 2727 2728 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 2729 defer lc.Close() 2730 2731 setupLeaf(t, lc, 3) 2732 } 2733 2734 func TestLeafNodeServiceImportLikeNGS(t *testing.T) { 2735 gwSolicit := 10 * time.Millisecond 2736 ca := createClusterEx(t, true, gwSolicit, true, "A", 3) 2737 defer shutdownCluster(ca) 2738 cb := createClusterEx(t, true, gwSolicit, true, "B", 3, ca) 2739 defer shutdownCluster(cb) 2740 2741 // Hang a responder off of cluster A. 2742 opts := ca.opts[0] 2743 url := fmt.Sprintf("nats://ngs:pass@%s:%d", opts.Host, opts.Port) 2744 nc, err := nats.Connect(url) 2745 if err != nil { 2746 t.Fatalf("Error on connect: %v", err) 2747 } 2748 defer nc.Close() 2749 2750 // Create a queue subscriber to send results 2751 nc.QueueSubscribe("ngs.usage.*", "ngs", func(m *nats.Msg) { 2752 m.Respond([]byte("22")) 2753 }) 2754 nc.Flush() 2755 2756 // Now create a leafnode server on B. 2757 opts = cb.opts[1] 2758 sl, slOpts := runSolicitLeafServer(opts) 2759 defer sl.Shutdown() 2760 2761 checkLeafNodeConnected(t, sl) 2762 2763 // Create a normal direct connect client on B. 2764 url = fmt.Sprintf("nats://dlc:pass@%s:%d", opts.Host, opts.Port) 2765 nc2, err := nats.Connect(url) 2766 if err != nil { 2767 t.Fatalf("Error on connect: %v", err) 2768 } 2769 defer nc2.Close() 2770 2771 if _, err := nc2.Request("ngs.usage", []byte("fingers crossed"), 500*time.Millisecond); err != nil { 2772 t.Fatalf("Did not receive response: %v", err) 2773 } 2774 2775 // Now create a client on the leafnode. 2776 url = fmt.Sprintf("nats://%s:%d", slOpts.Host, slOpts.Port) 2777 ncl, err := nats.Connect(url) 2778 if err != nil { 2779 t.Fatalf("Error on connect: %v", err) 2780 } 2781 defer ncl.Close() 2782 2783 if _, err := ncl.Request("ngs.usage", []byte("fingers crossed"), 500*time.Millisecond); err != nil { 2784 t.Fatalf("Did not receive response: %v", err) 2785 } 2786 } 2787 2788 func TestLeafNodeServiceImportResponderOnLeaf(t *testing.T) { 2789 gwSolicit := 10 * time.Millisecond 2790 ca := createClusterEx(t, true, gwSolicit, true, "A", 3) 2791 defer shutdownCluster(ca) 2792 2793 // Now create a leafnode server on A that will bind to the NGS account. 2794 opts := ca.opts[1] 2795 sl, slOpts := runSolicitLeafServerToURL(fmt.Sprintf("nats-leaf://ngs:pass@%s:%d", opts.LeafNode.Host, opts.LeafNode.Port)) 2796 defer sl.Shutdown() 2797 2798 checkLeafNodeConnected(t, sl) 2799 2800 // Now create a client on the leafnode. 2801 ncl, err := nats.Connect(fmt.Sprintf("nats://%s:%d", slOpts.Host, slOpts.Port)) 2802 if err != nil { 2803 t.Fatalf("Error on connect: %v", err) 2804 } 2805 defer ncl.Close() 2806 2807 // Create a queue subscriber to send results 2808 ncl.QueueSubscribe("ngs.usage.*", "ngs", func(m *nats.Msg) { 2809 m.Respond([]byte("22")) 2810 }) 2811 ncl.Flush() 2812 2813 // Create a normal direct connect client on A. Needs to be same server as leafnode. 2814 opts = ca.opts[1] 2815 nc, err := nats.Connect(fmt.Sprintf("nats://dlc:pass@%s:%d", opts.Host, opts.Port)) 2816 if err != nil { 2817 t.Fatalf("Error on connect: %v", err) 2818 } 2819 defer nc.Close() 2820 2821 if _, err := nc.Request("ngs.usage", []byte("fingers crossed"), 500*time.Millisecond); err != nil { 2822 t.Fatalf("Did not receive response: %v", err) 2823 } 2824 } 2825 2826 func TestLeafNodeSendsAccountingEvents(t *testing.T) { 2827 s, opts, _ := runLeafNodeOperatorServer(t) 2828 defer s.Shutdown() 2829 2830 // System account 2831 acc, akp := createAccount(t, s) 2832 if err := s.SetSystemAccount(acc.Name); err != nil { 2833 t.Fatalf("Expected this succeed, got %v", err) 2834 } 2835 2836 // Leafnode Account 2837 lacc, lakp := createAccount(t, s) 2838 2839 // Create a system account user and connect a client to listen for the events. 2840 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 2841 nc, err := nats.Connect(url, createUserCreds(t, s, akp)) 2842 if err != nil { 2843 t.Fatalf("Error on connect: %v", err) 2844 } 2845 defer nc.Close() 2846 2847 // Watch only for our leaf node account. 2848 cSub, _ := nc.SubscribeSync(fmt.Sprintf("$SYS.ACCOUNT.%s.CONNECT", lacc.Name)) 2849 dSub, _ := nc.SubscribeSync(fmt.Sprintf("$SYS.ACCOUNT.%s.DISCONNECT", lacc.Name)) 2850 nc.Flush() 2851 2852 // Now create creds for the leafnode and connect the server. 2853 kp, _ := nkeys.CreateUser() 2854 pub, _ := kp.PublicKey() 2855 nuc := jwt.NewUserClaims(pub) 2856 ujwt, err := nuc.Encode(lakp) 2857 if err != nil { 2858 t.Fatalf("Error generating user JWT: %v", err) 2859 } 2860 seed, _ := kp.Seed() 2861 mycreds := genCredsFile(t, ujwt, seed) 2862 2863 sl, _, _ := runSolicitWithCredentials(t, opts, mycreds) 2864 defer sl.Shutdown() 2865 2866 // Wait for connect event 2867 msg, err := cSub.NextMsg(time.Second) 2868 if err != nil { 2869 t.Fatalf("Error waiting for account connect event: %v", err) 2870 } 2871 m := server.ConnectEventMsg{} 2872 if err := json.Unmarshal(msg.Data, &m); err != nil { 2873 t.Fatal("Did not get correctly formatted event") 2874 } 2875 2876 // Shutdown leafnode to generate disconnect event. 2877 sl.Shutdown() 2878 2879 msg, err = dSub.NextMsg(time.Second) 2880 if err != nil { 2881 t.Fatalf("Error waiting for account disconnect event: %v", err) 2882 } 2883 dm := server.DisconnectEventMsg{} 2884 if err := json.Unmarshal(msg.Data, &dm); err != nil { 2885 t.Fatal("Did not get correctly formatted event") 2886 } 2887 } 2888 2889 func TestLeafNodeDistributedQueueAcrossGWs(t *testing.T) { 2890 gwSolicit := 10 * time.Millisecond 2891 ca := createClusterEx(t, true, gwSolicit, true, "A", 3) 2892 defer shutdownCluster(ca) 2893 cb := createClusterEx(t, true, gwSolicit, true, "B", 3, ca) 2894 defer shutdownCluster(cb) 2895 cc := createClusterEx(t, true, gwSolicit, true, "C", 3, ca, cb) 2896 defer shutdownCluster(cc) 2897 2898 // Create queue subscribers 2899 createQS := func(c *cluster) *nats.Conn { 2900 t.Helper() 2901 opts := c.opts[rand.Intn(len(c.opts))] 2902 url := fmt.Sprintf("nats://ngs:pass@%s:%d", opts.Host, opts.Port) 2903 nc, err := nats.Connect(url) 2904 if err != nil { 2905 t.Fatalf("Error on connect: %v", err) 2906 } 2907 nc.QueueSubscribe("ngs.usage.*", "dq", func(m *nats.Msg) { 2908 m.Respond([]byte(c.name)) 2909 }) 2910 nc.Flush() 2911 return nc 2912 } 2913 2914 ncA := createQS(ca) 2915 defer ncA.Close() 2916 ncB := createQS(cb) 2917 defer ncB.Close() 2918 ncC := createQS(cc) 2919 defer ncC.Close() 2920 2921 connectAndRequest := func(url, clusterName string, nreqs int) { 2922 t.Helper() 2923 nc, err := nats.Connect(url) 2924 if err != nil { 2925 t.Fatalf("Error on connect: %v", err) 2926 } 2927 defer nc.Close() 2928 for i := 0; i < nreqs; i++ { 2929 m, err := nc.Request("ngs.usage", nil, 500*time.Millisecond) 2930 if err != nil { 2931 t.Fatalf("Did not receive a response: %v", err) 2932 } 2933 if string(m.Data) != clusterName { 2934 t.Fatalf("Expected to prefer %q, but got response from %q", clusterName, m.Data) 2935 } 2936 } 2937 } 2938 2939 checkClientDQ := func(c *cluster, nreqs int) { 2940 t.Helper() 2941 // Pick one at random. 2942 opts := c.opts[rand.Intn(len(c.opts))] 2943 url := fmt.Sprintf("nats://dlc:pass@%s:%d", opts.Host, opts.Port) 2944 connectAndRequest(url, c.name, nreqs) 2945 } 2946 2947 // First check that this works with direct connected clients. 2948 checkClientDQ(ca, 100) 2949 checkClientDQ(cb, 100) 2950 checkClientDQ(cc, 100) 2951 2952 createLNS := func(c *cluster) (*server.Server, *server.Options) { 2953 t.Helper() 2954 // Pick one at random. 2955 s, opts := runSolicitLeafServer(c.opts[rand.Intn(len(c.servers))]) 2956 checkLeafNodeConnected(t, s) 2957 return s, opts 2958 } 2959 2960 checkLeafDQ := func(opts *server.Options, clusterName string, nreqs int) { 2961 t.Helper() 2962 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 2963 connectAndRequest(url, clusterName, nreqs) 2964 } 2965 2966 // Test leafnodes to all clusters. 2967 for _, c := range []*cluster{ca, cb, cc} { 2968 // Now create a leafnode on cluster. 2969 sl, slOpts := createLNS(c) 2970 defer sl.Shutdown() 2971 // Now connect to the leafnode server and run test. 2972 checkLeafDQ(slOpts, c.name, 100) 2973 } 2974 } 2975 2976 func TestLeafNodeDistributedQueueEvenly(t *testing.T) { 2977 gwSolicit := 10 * time.Millisecond 2978 ca := createClusterEx(t, true, gwSolicit, true, "A", 3) 2979 defer shutdownCluster(ca) 2980 cb := createClusterEx(t, true, gwSolicit, true, "B", 3, ca) 2981 defer shutdownCluster(cb) 2982 2983 // Create queue subscribers 2984 createQS := func(c *cluster) *nats.Conn { 2985 t.Helper() 2986 opts := c.opts[rand.Intn(len(c.opts))] 2987 url := fmt.Sprintf("nats://ngs:pass@%s:%d", opts.Host, opts.Port) 2988 nc, err := nats.Connect(url) 2989 if err != nil { 2990 t.Fatalf("Error on connect: %v", err) 2991 } 2992 cid, _ := nc.GetClientID() 2993 response := []byte(fmt.Sprintf("%s:%d:%d", c.name, opts.Port, cid)) 2994 nc.QueueSubscribe("ngs.usage.*", "dq", func(m *nats.Msg) { 2995 m.Respond(response) 2996 }) 2997 nc.Flush() 2998 return nc 2999 } 3000 3001 ncA1 := createQS(ca) 3002 defer ncA1.Close() 3003 3004 ncA2 := createQS(ca) 3005 defer ncA2.Close() 3006 3007 ncA3 := createQS(ca) 3008 defer ncA3.Close() 3009 3010 resp := make(map[string]int) 3011 3012 connectAndRequest := func(url, clusterName string, nreqs int) { 3013 t.Helper() 3014 nc, err := nats.Connect(url) 3015 if err != nil { 3016 t.Fatalf("Error on connect: %v", err) 3017 } 3018 defer nc.Close() 3019 for i := 0; i < nreqs; i++ { 3020 m, err := nc.Request("ngs.usage", nil, 500*time.Millisecond) 3021 if err != nil { 3022 t.Fatalf("Did not receive a response: %v", err) 3023 } 3024 if string(m.Data[0]) != clusterName { 3025 t.Fatalf("Expected to prefer %q, but got response from %q", clusterName, m.Data[0]) 3026 } 3027 resp[string(m.Data)]++ 3028 } 3029 } 3030 3031 createLNS := func(c *cluster) (*server.Server, *server.Options) { 3032 t.Helper() 3033 // Pick one at random. 3034 copts := c.opts[rand.Intn(len(c.servers))] 3035 s, opts := runSolicitLeafServer(copts) 3036 checkLeafNodeConnected(t, s) 3037 return s, opts 3038 } 3039 3040 checkLeafDQ := func(opts *server.Options, clusterName string, nreqs int) { 3041 t.Helper() 3042 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 3043 connectAndRequest(url, clusterName, nreqs) 3044 } 3045 3046 // Now create a leafnode on cluster A. 3047 sl, slOpts := createLNS(ca) 3048 defer sl.Shutdown() 3049 3050 // Now connect to the leafnode server and run test. 3051 checkLeafDQ(slOpts, ca.name, 100) 3052 3053 // Should have some for all 3 QS [ncA1, ncA2, ncA3] 3054 if lr := len(resp); lr != 3 { 3055 t.Fatalf("Expected all 3 queue subscribers to have received some messages, only got %d", lr) 3056 } 3057 // Now check that we have at least 10% for each subscriber. 3058 for _, r := range resp { 3059 if r < 10 { 3060 t.Fatalf("Got a subscriber with less than 10 responses: %d", r) 3061 } 3062 } 3063 } 3064 3065 func TestLeafNodeDefaultPort(t *testing.T) { 3066 o := testDefaultOptionsForLeafNodes() 3067 o.LeafNode.Port = server.DEFAULT_LEAFNODE_PORT 3068 s := RunServer(o) 3069 defer s.Shutdown() 3070 3071 conf := createConfFile(t, []byte(` 3072 port: -1 3073 leaf { 3074 remotes = [ 3075 { 3076 url: "leafnode://127.0.0.1" 3077 } 3078 ] 3079 } 3080 `)) 3081 3082 sl, _ := RunServerWithConfig(conf) 3083 defer sl.Shutdown() 3084 3085 checkLeafNodeConnected(t, s) 3086 } 3087 3088 // Since leafnode's are true interest only we need to make sure that we 3089 // register the proper interest with global routing $GR.xxxxxx._INBOX.> 3090 func TestLeafNodeAndGatewayGlobalRouting(t *testing.T) { 3091 server.SetGatewaysSolicitDelay(50 * time.Millisecond) 3092 defer server.ResetGatewaysSolicitDelay() 3093 3094 ca := createClusterWithName(t, "A", 3) 3095 defer shutdownCluster(ca) 3096 cb := createClusterWithName(t, "B", 3, ca) 3097 defer shutdownCluster(cb) 3098 3099 sl, slOpts := runSolicitLeafServer(ca.opts[1]) 3100 defer sl.Shutdown() 3101 3102 checkLeafNodeConnected(t, ca.servers[1]) 3103 3104 // Create a client on the leafnode. This will listen for requests. 3105 ncl, err := nats.Connect(fmt.Sprintf("nats://%s:%d", slOpts.Host, slOpts.Port)) 3106 if err != nil { 3107 t.Fatalf("Error on connect: %v", err) 3108 } 3109 defer ncl.Close() 3110 3111 ncl.Subscribe("foo", func(m *nats.Msg) { 3112 m.Respond([]byte("World")) 3113 }) 3114 ncl.Flush() 3115 3116 // Since for leafnodes the account becomes interest-only mode, 3117 // let's make sure that the interest on "foo" has time to propagate 3118 // to cluster B. 3119 time.Sleep(250 * time.Millisecond) 3120 3121 // Create a direct connect requestor. Try with all possible 3122 // servers in cluster B to make sure that we also receive the 3123 // reply when the accepting leafnode server does not have 3124 // its outbound GW connection to the requestor's server. 3125 for i := 0; i < 3; i++ { 3126 opts := cb.opts[i] 3127 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 3128 nc, err := nats.Connect(url) 3129 if err != nil { 3130 t.Fatalf("Error on connect: %v", err) 3131 } 3132 defer nc.Close() 3133 3134 // We don't use an INBOX here because we had a bug where 3135 // leafnode would subscribe to _GR_.*.*.*.> instead of 3136 // _GR_.>, and inbox masked that because of their number 3137 // of tokens. 3138 reply := nuid.Next() 3139 sub, err := nc.SubscribeSync(reply) 3140 if err != nil { 3141 t.Fatalf("Error on subscribe: %v", err) 3142 } 3143 if err := nc.PublishRequest("foo", reply, []byte("Hello")); err != nil { 3144 t.Fatalf("Failed to send request: %v", err) 3145 } 3146 if _, err := sub.NextMsg(250 * time.Millisecond); err != nil { 3147 t.Fatalf("Did not get reply from server %d: %v", i, err) 3148 } 3149 nc.Close() 3150 } 3151 } 3152 3153 func checkLeafNode2Connected(t *testing.T, s *server.Server) { 3154 t.Helper() 3155 checkFor(t, 5*time.Second, 100*time.Millisecond, func() error { 3156 if nln := s.NumLeafNodes(); nln != 2 { 3157 return fmt.Errorf("Expected a connected leafnode for server %q, got none", s.ID()) 3158 } 3159 return nil 3160 }) 3161 } 3162 3163 func TestLeafNodesStaggeredSubPub(t *testing.T) { 3164 s, opts := runLeafServer() 3165 defer s.Shutdown() 3166 3167 sl1, sl1Opts := runSolicitLeafServer(opts) 3168 defer sl1.Shutdown() 3169 3170 checkLeafNodeConnected(t, s) 3171 3172 // Create a client on the leafnode and a subscription. 3173 ncl, err := nats.Connect(fmt.Sprintf("nats://%s:%d", sl1Opts.Host, sl1Opts.Port)) 3174 if err != nil { 3175 t.Fatalf("Error on connect: %v", err) 3176 } 3177 defer ncl.Close() 3178 3179 sub, err := ncl.SubscribeSync("foo") 3180 if err != nil { 3181 t.Fatalf("Failed to subscribe: %v", err) 3182 } 3183 3184 sl2, sl2Opts := runSolicitLeafServer(opts) 3185 defer sl2.Shutdown() 3186 3187 checkLeafNode2Connected(t, s) 3188 3189 // Create a client on the second leafnode and publish a message. 3190 ncl2, err := nats.Connect(fmt.Sprintf("nats://%s:%d", sl2Opts.Host, sl2Opts.Port)) 3191 if err != nil { 3192 t.Fatalf("Error on connect: %v", err) 3193 } 3194 defer ncl2.Close() 3195 3196 ncl2.Publish("foo", nil) 3197 3198 checkFor(t, 250*time.Millisecond, 10*time.Millisecond, func() error { 3199 if nmsgs, _, err := sub.Pending(); err != nil || nmsgs != 1 { 3200 return fmt.Errorf("Did not receive the message: %v", err) 3201 } 3202 return nil 3203 }) 3204 } 3205 3206 func TestLeafNodeMultipleRemoteURLs(t *testing.T) { 3207 s, opts := runLeafServer() 3208 defer s.Shutdown() 3209 3210 content := ` 3211 port: -1 3212 leafnodes { 3213 remotes = [ 3214 { 3215 urls: [nats-leaf://127.0.0.1:%d,nats-leaf://localhost:%d] 3216 } 3217 ] 3218 } 3219 ` 3220 3221 config := fmt.Sprintf(content, opts.LeafNode.Port, opts.LeafNode.Port) 3222 conf := createConfFile(t, []byte(config)) 3223 sl, _ := RunServerWithConfig(conf) 3224 defer sl.Shutdown() 3225 3226 checkLeafNodeConnected(t, s) 3227 } 3228 3229 func runSolicitLeafCluster(t *testing.T, clusterName string, d1, d2 *cluster) *cluster { 3230 c := &cluster{servers: make([]*server.Server, 0, 2), opts: make([]*server.Options, 0, 2), name: clusterName} 3231 3232 // Who we will solicit for server 1 3233 ci := rand.Intn(len(d1.opts)) 3234 opts := d1.opts[ci] 3235 surl := fmt.Sprintf("nats-leaf://%s:%d", opts.LeafNode.Host, opts.LeafNode.Port) 3236 3237 o := DefaultTestOptions 3238 o.Port = -1 3239 rurl, _ := url.Parse(surl) 3240 o.LeafNode.Remotes = []*server.RemoteLeafOpts{{URLs: []*url.URL{rurl}}} 3241 o.LeafNode.ReconnectInterval = 100 * time.Millisecond 3242 o.Cluster.Name = clusterName 3243 o.Cluster.Host = o.Host 3244 o.Cluster.Port = -1 3245 s := RunServer(&o) 3246 checkLeafNodeConnected(t, d1.servers[ci]) 3247 3248 c.servers = append(c.servers, s) 3249 c.opts = append(c.opts, &o) 3250 3251 // Grab route info 3252 routeAddr := fmt.Sprintf("nats-route://%s:%d", o.Cluster.Host, o.Cluster.Port) 3253 curl, _ := url.Parse(routeAddr) 3254 3255 // Who we will solicit for server 2 3256 ci = rand.Intn(len(d2.opts)) 3257 opts = d2.opts[ci] 3258 surl = fmt.Sprintf("nats-leaf://%s:%d", opts.LeafNode.Host, opts.LeafNode.Port) 3259 3260 // This is for the case were d1 == d2 and we select the same server. 3261 plfn := d2.servers[ci].NumLeafNodes() 3262 3263 o2 := DefaultTestOptions 3264 o2.Port = -1 3265 rurl, _ = url.Parse(surl) 3266 o2.LeafNode.Remotes = []*server.RemoteLeafOpts{{URLs: []*url.URL{rurl}}} 3267 o2.LeafNode.ReconnectInterval = 100 * time.Millisecond 3268 o2.Cluster.Name = clusterName 3269 o2.Cluster.Host = o.Host 3270 o2.Cluster.Port = -1 3271 o2.Routes = []*url.URL{curl} 3272 s = RunServer(&o2) 3273 3274 if plfn == 0 { 3275 checkLeafNodeConnected(t, d2.servers[ci]) 3276 } else { 3277 checkLeafNode2Connected(t, d2.servers[ci]) 3278 } 3279 3280 c.servers = append(c.servers, s) 3281 c.opts = append(c.opts, &o2) 3282 3283 checkClusterFormed(t, c.servers...) 3284 3285 return c 3286 } 3287 3288 func clientForCluster(t *testing.T, c *cluster) *nats.Conn { 3289 t.Helper() 3290 opts := c.opts[rand.Intn(len(c.opts))] 3291 url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port) 3292 nc, err := nats.Connect(url) 3293 if err != nil { 3294 t.Fatalf("Error on connect: %v", err) 3295 } 3296 return nc 3297 } 3298 3299 func TestLeafNodeCycleWithSolicited(t *testing.T) { 3300 server.SetGatewaysSolicitDelay(10 * time.Millisecond) 3301 defer server.ResetGatewaysSolicitDelay() 3302 3303 // Accepting leafnode cluster, e.g. NGS 3304 ca := createClusterWithName(t, "A", 3) 3305 defer shutdownCluster(ca) 3306 cb := createClusterWithName(t, "B", 3, ca) 3307 defer shutdownCluster(cb) 3308 3309 // Create the responders. 3310 requestsReceived := int32(0) 3311 3312 nc := clientForCluster(t, ca) 3313 defer nc.Close() 3314 nc.QueueSubscribe("request", "cycles", func(m *nats.Msg) { 3315 atomic.AddInt32(&requestsReceived, 1) 3316 m.Respond([]byte("22")) 3317 }) 3318 3319 nc = clientForCluster(t, cb) 3320 defer nc.Close() 3321 nc.QueueSubscribe("request", "cycles", func(m *nats.Msg) { 3322 atomic.AddInt32(&requestsReceived, 1) 3323 m.Respond([]byte("33")) 3324 }) 3325 3326 // Soliciting cluster, both solicited connected to the "A" cluster 3327 sc := runSolicitLeafCluster(t, "SC", ca, ca) 3328 defer shutdownCluster(sc) 3329 3330 checkInterest := func(s *server.Server, subject string) bool { 3331 t.Helper() 3332 acc, _ := s.LookupAccount("$G") 3333 return acc.SubscriptionInterest(subject) 3334 } 3335 3336 waitForInterest := func(subject string, servers ...*server.Server) { 3337 t.Helper() 3338 checkFor(t, time.Second, 10*time.Millisecond, func() error { 3339 for _, s := range servers { 3340 if !checkInterest(s, subject) { 3341 return fmt.Errorf("No interest") 3342 } 3343 } 3344 return nil 3345 }) 3346 } 3347 3348 waitForInterest("request", 3349 sc.servers[0], sc.servers[1], 3350 ca.servers[0], ca.servers[1], ca.servers[2], 3351 cb.servers[0], cb.servers[1], cb.servers[2], 3352 ) 3353 3354 // Connect a client to a random server in sc 3355 createClientAndRequest := func(c *cluster) (*nats.Conn, *nats.Subscription) { 3356 nc := clientForCluster(t, c) 3357 reply := nats.NewInbox() 3358 sub, err := nc.SubscribeSync(reply) 3359 if err != nil { 3360 t.Fatalf("Could not subscribe: %v", err) 3361 } 3362 if err := nc.PublishRequest("request", reply, []byte("fingers crossed")); err != nil { 3363 t.Fatalf("Error sending request: %v", err) 3364 } 3365 return nc, sub 3366 } 3367 3368 verifyOneResponse := func(sub *nats.Subscription) { 3369 time.Sleep(250 * time.Millisecond) 3370 m, _, err := sub.Pending() 3371 if err != nil { 3372 t.Fatalf("Error calling Pending(): %v", err) 3373 } 3374 if m > 1 { 3375 t.Fatalf("Received more then one response, cycle indicated: %d", m) 3376 } 3377 } 3378 3379 verifyRequestTotal := func(nre int32) { 3380 if nr := atomic.LoadInt32(&requestsReceived); nr != nre { 3381 t.Fatalf("Expected %d requests received, got %d", nre, nr) 3382 } 3383 } 3384 3385 // This should pass to here, but if we have a cycle things will be spinning and we will receive 3386 // too many responses when it should only be 1. 3387 nc, rsub := createClientAndRequest(sc) 3388 defer nc.Close() 3389 verifyOneResponse(rsub) 3390 verifyRequestTotal(1) 3391 3392 // Do a solicit across GW, so shut this one down. 3393 nc.Close() 3394 shutdownCluster(sc) 3395 3396 // Soliciting cluster, connect to different clusters across a GW. 3397 sc = runSolicitLeafCluster(t, "SC", ca, cb) 3398 defer shutdownCluster(sc) 3399 3400 nc, rsub = createClientAndRequest(sc) 3401 defer nc.Close() 3402 verifyOneResponse(rsub) 3403 verifyRequestTotal(2) // This is total since use same responders. 3404 } 3405 3406 func TestLeafNodeNoRaceGeneratingNonce(t *testing.T) { 3407 opts := testDefaultOptionsForLeafNodes() 3408 opts.Cluster.Port = -1 3409 opts.Cluster.Name = "xyz" 3410 s := RunServer(opts) 3411 defer s.Shutdown() 3412 3413 quitCh := make(chan struct{}) 3414 wg := sync.WaitGroup{} 3415 wg.Add(2) 3416 3417 go func() { 3418 defer wg.Done() 3419 for { 3420 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 3421 checkInfoMsg(t, lc) 3422 lc.Close() 3423 select { 3424 case <-quitCh: 3425 return 3426 case <-time.After(time.Millisecond): 3427 } 3428 } 3429 }() 3430 3431 go func() { 3432 defer wg.Done() 3433 for { 3434 rc := createRouteConn(t, opts.Cluster.Host, opts.Cluster.Port) 3435 checkInfoMsg(t, rc) 3436 rc.Close() 3437 select { 3438 case <-quitCh: 3439 return 3440 case <-time.After(time.Millisecond): 3441 } 3442 } 3443 }() 3444 3445 // Let this run for a bit to see if we get data race 3446 time.Sleep(100 * time.Millisecond) 3447 close(quitCh) 3448 wg.Wait() 3449 } 3450 3451 func runSolicitAndAcceptLeafServer(lso *server.Options) (*server.Server, *server.Options) { 3452 surl := fmt.Sprintf("nats-leaf://%s:%d", lso.LeafNode.Host, lso.LeafNode.Port) 3453 o := testDefaultOptionsForLeafNodes() 3454 o.Port = -1 3455 rurl, _ := url.Parse(surl) 3456 o.LeafNode.Remotes = []*server.RemoteLeafOpts{{URLs: []*url.URL{rurl}}} 3457 o.LeafNode.ReconnectInterval = 100 * time.Millisecond 3458 return RunServer(o), o 3459 } 3460 3461 func TestLeafNodeDaisyChain(t *testing.T) { 3462 // To quickly enable trace and debug logging 3463 // doLog, doTrace, doDebug = true, true, true 3464 s1, opts1 := runLeafServer() 3465 defer s1.Shutdown() 3466 3467 s2, opts2 := runSolicitAndAcceptLeafServer(opts1) 3468 defer s2.Shutdown() 3469 checkLeafNodeConnected(t, s1) 3470 3471 s3, _ := runSolicitLeafServer(opts2) 3472 defer s3.Shutdown() 3473 checkLeafNodeConnections(t, s2, 2) 3474 3475 // Make so we can tell the two apart since in same PID. 3476 if doLog { 3477 s1.SetLogger(logger.NewTestLogger("[S-1] - ", false), true, true) 3478 s2.SetLogger(logger.NewTestLogger("[S-2] - ", false), true, true) 3479 s3.SetLogger(logger.NewTestLogger("[S-3] - ", false), true, true) 3480 } 3481 3482 nc1, err := nats.Connect(s1.ClientURL()) 3483 if err != nil { 3484 t.Fatalf("Error creating client: %v", err) 3485 } 3486 defer nc1.Close() 3487 3488 nc1.Subscribe("ngs.usage", func(msg *nats.Msg) { 3489 msg.Respond([]byte("22 msgs")) 3490 }) 3491 nc1.Flush() 3492 3493 checkSubInterest(t, s3, "$G", "ngs.usage", time.Second) 3494 3495 nc2, err := nats.Connect(s3.ClientURL()) 3496 if err != nil { 3497 t.Fatalf("Error creating client: %v", err) 3498 } 3499 defer nc2.Close() 3500 3501 if _, err = nc2.Request("ngs.usage", []byte("1h"), time.Second); err != nil { 3502 t.Fatalf("Expected a response") 3503 } 3504 } 3505 3506 // This will test failover to a server with a cert with only an IP after successfully connecting 3507 // to a server with a cert with both. 3508 func TestClusterTLSMixedIPAndDNS(t *testing.T) { 3509 confA := createConfFile(t, []byte(` 3510 listen: 127.0.0.1:-1 3511 leafnodes { 3512 listen: "127.0.0.1:-1" 3513 tls { 3514 cert_file: "./configs/certs/server-iponly.pem" 3515 key_file: "./configs/certs/server-key-iponly.pem" 3516 ca_file: "./configs/certs/ca.pem" 3517 timeout: 2 3518 } 3519 } 3520 cluster { 3521 listen: "127.0.0.1:-1" 3522 name: xyz 3523 } 3524 `)) 3525 srvA, optsA := RunServerWithConfig(confA) 3526 defer srvA.Shutdown() 3527 3528 bConfigTemplate := ` 3529 listen: 127.0.0.1:-1 3530 leafnodes { 3531 listen: "127.0.0.1:-1" 3532 tls { 3533 cert_file: "./configs/certs/server-cert.pem" 3534 key_file: "./configs/certs/server-key.pem" 3535 ca_file: "./configs/certs/ca.pem" 3536 timeout: 2 3537 } 3538 } 3539 cluster { 3540 listen: "127.0.0.1:-1" 3541 name: xyz 3542 routes [ 3543 "nats://%s:%d" 3544 ] 3545 } 3546 ` 3547 confB := createConfFile(t, []byte(fmt.Sprintf(bConfigTemplate, 3548 optsA.Cluster.Host, optsA.Cluster.Port))) 3549 srvB, optsB := RunServerWithConfig(confB) 3550 defer srvB.Shutdown() 3551 3552 checkClusterFormed(t, srvA, srvB) 3553 3554 // Solicit a leafnode server here. Don't use the helper since we need verification etc. 3555 o := DefaultTestOptions 3556 o.Port = -1 3557 rurl, _ := url.Parse(fmt.Sprintf("nats-leaf://%s:%d", optsB.LeafNode.Host, optsB.LeafNode.Port)) 3558 o.LeafNode.ReconnectInterval = 10 * time.Millisecond 3559 remote := &server.RemoteLeafOpts{URLs: []*url.URL{rurl}} 3560 remote.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12} 3561 pool := x509.NewCertPool() 3562 rootPEM, err := os.ReadFile("./configs/certs/ca.pem") 3563 if err != nil || rootPEM == nil { 3564 t.Fatalf("Error loading or parsing rootCA file: %v", err) 3565 } 3566 ok := pool.AppendCertsFromPEM(rootPEM) 3567 if !ok { 3568 t.Fatalf("Failed to parse root certificate from %q", "./configs/certs/ca.pem") 3569 } 3570 remote.TLSConfig.RootCAs = pool 3571 o.LeafNode.Remotes = []*server.RemoteLeafOpts{remote} 3572 sl, _ := RunServer(&o), &o 3573 defer sl.Shutdown() 3574 3575 checkLeafNodeConnected(t, srvB) 3576 3577 // Now kill off srvB and force client to connect to srvA. 3578 srvB.Shutdown() 3579 3580 // Make sure this works. 3581 checkLeafNodeConnected(t, srvA) 3582 } 3583 3584 // This will test for a bug in stream export/import with leafnodes. 3585 // https://github.com/nats-io/nats-server/issues/1332 3586 func TestStreamExportWithMultipleAccounts(t *testing.T) { 3587 confA := createConfFile(t, []byte(` 3588 listen: 127.0.0.1:-1 3589 leafnodes { 3590 listen: "127.0.0.1:-1" 3591 } 3592 `)) 3593 srvA, optsA := RunServerWithConfig(confA) 3594 defer srvA.Shutdown() 3595 3596 bConfigTemplate := ` 3597 listen: 127.0.0.1:-1 3598 leafnodes { 3599 listen: "127.0.0.1:-1" 3600 remotes = [ 3601 { 3602 url:"nats://127.0.0.1:%d" 3603 account:"EXTERNAL" 3604 } 3605 ] 3606 } 3607 accounts: { 3608 INTERNAL: { 3609 users: [ 3610 {user: good, password: pwd} 3611 ] 3612 imports: [ 3613 { 3614 stream: { account: EXTERNAL, subject: "foo"}, prefix: "bar" 3615 } 3616 ] 3617 }, 3618 EXTERNAL: { 3619 users: [ 3620 {user: bad, password: pwd} 3621 ] 3622 exports: [{stream: "foo"}] 3623 }, 3624 } 3625 ` 3626 3627 confB := createConfFile(t, []byte(fmt.Sprintf(bConfigTemplate, optsA.LeafNode.Port))) 3628 srvB, optsB := RunServerWithConfig(confB) 3629 defer srvB.Shutdown() 3630 3631 nc, err := nats.Connect(fmt.Sprintf("nats://good:pwd@%s:%d", optsB.Host, optsB.Port)) 3632 if err != nil { 3633 t.Fatalf("Error on connect: %v", err) 3634 } 3635 defer nc.Close() 3636 3637 wcsub, err := nc.SubscribeSync(">") 3638 if err != nil { 3639 t.Fatalf("Unexpected error: %v", err) 3640 } 3641 defer wcsub.Unsubscribe() 3642 nc.Flush() 3643 3644 nc2, err := nats.Connect(fmt.Sprintf("nats://%s:%d", optsA.Host, optsA.Port)) 3645 if err != nil { 3646 t.Fatalf("Error on connect: %v", err) 3647 } 3648 defer nc2.Close() 3649 3650 nc2.Publish("foo", nil) 3651 3652 msg, err := wcsub.NextMsg(1 * time.Second) 3653 if err != nil { 3654 t.Fatalf("Did not receive the message: %v", err) 3655 } 3656 if msg.Subject != "bar.foo" { 3657 t.Fatalf("Received on wrong subject: %q", msg.Subject) 3658 } 3659 } 3660 3661 // This will test for a bug in service export/import with leafnodes. 3662 // https://github.com/nats-io/nats-server/issues/1336 3663 func TestServiceExportWithMultipleAccounts(t *testing.T) { 3664 confA := createConfFile(t, []byte(` 3665 server_name: A 3666 listen: 127.0.0.1:-1 3667 leafnodes { 3668 listen: "127.0.0.1:-1" 3669 } 3670 `)) 3671 3672 srvA, optsA := RunServerWithConfig(confA) 3673 defer srvA.Shutdown() 3674 3675 bConfigTemplate := ` 3676 server_name: B 3677 listen: 127.0.0.1:-1 3678 leafnodes { 3679 listen: "127.0.0.1:-1" 3680 remotes = [ 3681 { 3682 url:"nats://127.0.0.1:%d" 3683 account:"EXTERNAL" 3684 } 3685 ] 3686 } 3687 accounts: { 3688 INTERNAL: { 3689 users: [ 3690 {user: good, password: pwd} 3691 ] 3692 imports: [ 3693 { 3694 service: { 3695 account: EXTERNAL 3696 subject: "foo" 3697 } 3698 } 3699 ] 3700 }, 3701 EXTERNAL: { 3702 users: [ 3703 {user: evil, password: pwd} 3704 ] 3705 exports: [{service: "foo"}] 3706 }, 3707 } 3708 ` 3709 3710 confB := createConfFile(t, []byte(fmt.Sprintf(bConfigTemplate, optsA.LeafNode.Port))) 3711 3712 srvB, optsB := RunServerWithConfig(confB) 3713 defer srvB.Shutdown() 3714 3715 checkLeafNodeConnected(t, srvB) 3716 3717 // connect to confA, and offer a service 3718 nc2, err := nats.Connect(fmt.Sprintf("nats://%s:%d", optsA.Host, optsA.Port)) 3719 if err != nil { 3720 t.Fatalf("Error on connect: %v", err) 3721 } 3722 defer nc2.Close() 3723 3724 nc2.Subscribe("foo", func(msg *nats.Msg) { 3725 if err := msg.Respond([]byte("world")); err != nil { 3726 t.Fatalf("Error on respond: %v", err) 3727 } 3728 }) 3729 nc2.Flush() 3730 3731 checkSubInterest(t, srvB, "INTERNAL", "foo", time.Second) 3732 3733 nc, err := nats.Connect(fmt.Sprintf("nats://good:pwd@%s:%d", optsB.Host, optsB.Port)) 3734 if err != nil { 3735 t.Fatalf("Error on connect: %v", err) 3736 } 3737 defer nc.Close() 3738 3739 resp, err := nc.Request("foo", []byte("hello"), 2*time.Second) 3740 if err != nil { 3741 t.Fatalf("Unexpected error: %v", err) 3742 } 3743 if resp == nil || strings.Compare("world", string(resp.Data)) != 0 { 3744 t.Fatal("Did not receive the correct message") 3745 } 3746 } 3747 3748 // This will test for a bug in service export/import with leafnode restart. 3749 // https://github.com/nats-io/nats-server/issues/1344 3750 func TestServiceExportWithLeafnodeRestart(t *testing.T) { 3751 confG := createConfFile(t, []byte(` 3752 server_name: G 3753 listen: 127.0.0.1:-1 3754 leafnodes { 3755 listen: "127.0.0.1:-1" 3756 authorization { account:"EXTERNAL" } 3757 } 3758 3759 accounts: { 3760 INTERNAL: { 3761 users: [ 3762 {user: good, password: pwd} 3763 ] 3764 exports: [{service: "foo", response: singleton}] 3765 imports: [ 3766 { 3767 service: { 3768 account: EXTERNAL 3769 subject: "evilfoo" 3770 }, to: from_evilfoo 3771 } 3772 ] 3773 }, 3774 EXTERNAL: { 3775 users: [ 3776 {user: evil, password: pwd} 3777 ] 3778 exports: [{service: "evilfoo", response: singleton}] 3779 imports: [ 3780 { 3781 service: { 3782 account: INTERNAL 3783 subject: "foo" 3784 }, to: goodfoo 3785 } 3786 ] 3787 } 3788 } 3789 `)) 3790 3791 srvG, optsG := RunServerWithConfig(confG) 3792 defer srvG.Shutdown() 3793 3794 eConfigTemplate := ` 3795 server_name: E 3796 listen: 127.0.0.1:-1 3797 leafnodes { 3798 listen: "127.0.0.1:-1" 3799 remotes = [ 3800 { 3801 url:"nats://127.0.0.1:%d" 3802 account:"EXTERNAL_GOOD" 3803 } 3804 ] 3805 } 3806 3807 accounts: { 3808 INTERNAL_EVILINC: { 3809 users: [ 3810 {user: evil, password: pwd} 3811 ] 3812 exports: [{service: "foo", response: singleton}] 3813 imports: [ 3814 { 3815 service: { 3816 account: EXTERNAL_GOOD 3817 subject: "goodfoo" 3818 }, to: from_goodfoo 3819 } 3820 ] 3821 }, 3822 EXTERNAL_GOOD: { 3823 users: [ 3824 {user: good, password: pwd} 3825 ] 3826 exports: [{service: "goodfoo", response: singleton}] 3827 imports: [ 3828 { 3829 service: { 3830 account: INTERNAL_EVILINC 3831 subject: "foo" 3832 }, to: evilfoo 3833 } 3834 ] 3835 }, 3836 } 3837 ` 3838 3839 confE := createConfFile(t, []byte(fmt.Sprintf(eConfigTemplate, optsG.LeafNode.Port))) 3840 3841 srvE, optsE := RunServerWithConfig(confE) 3842 defer srvE.Shutdown() 3843 3844 // connect to confE, and offer a service 3845 nc2, err := nats.Connect(fmt.Sprintf("nats://evil:pwd@%s:%d", optsE.Host, optsE.Port)) 3846 if err != nil { 3847 t.Fatalf("Error on connect: %v", err) 3848 } 3849 defer nc2.Close() 3850 3851 nc2.Subscribe("foo", func(msg *nats.Msg) { 3852 if err := msg.Respond([]byte("world")); err != nil { 3853 t.Fatalf("Error on respond: %v", err) 3854 } 3855 }) 3856 nc2.Flush() 3857 3858 nc, err := nats.Connect(fmt.Sprintf("nats://good:pwd@%s:%d", optsG.Host, optsG.Port)) 3859 if err != nil { 3860 t.Fatalf("Error on connect: %v", err) 3861 } 3862 defer nc.Close() 3863 3864 resp, err := nc.Request("from_evilfoo", []byte("hello"), 2*time.Second) 3865 if err != nil { 3866 t.Fatalf("Unexpected error: %v", err) 3867 } 3868 if resp == nil || strings.Compare("world", string(resp.Data)) != 0 { 3869 t.Fatal("Did not receive the correct message") 3870 } 3871 3872 // Now restart server E and requestor and replier. 3873 nc.Close() 3874 nc2.Close() 3875 srvE.Shutdown() 3876 3877 srvE, optsE = RunServerWithConfig(confE) 3878 defer srvE.Shutdown() 3879 3880 nc2, err = nats.Connect(fmt.Sprintf("nats://evil:pwd@%s:%d", optsE.Host, optsE.Port)) 3881 if err != nil { 3882 t.Fatalf("Error on connect: %v", err) 3883 } 3884 defer nc2.Close() 3885 3886 nc2.Subscribe("foo", func(msg *nats.Msg) { 3887 if err := msg.Respond([]byte("world")); err != nil { 3888 t.Fatalf("Error on respond: %v", err) 3889 } 3890 }) 3891 nc2.Flush() 3892 3893 nc, err = nats.Connect(fmt.Sprintf("nats://good:pwd@%s:%d", optsG.Host, optsG.Port)) 3894 if err != nil { 3895 t.Fatalf("Error on connect: %v", err) 3896 } 3897 defer nc.Close() 3898 3899 resp, err = nc.Request("from_evilfoo", []byte("hello"), 2*time.Second) 3900 if err != nil { 3901 t.Fatalf("Unexpected error: %v", err) 3902 } 3903 if resp == nil || strings.Compare("world", string(resp.Data)) != 0 { 3904 t.Fatal("Did not receive the correct message") 3905 } 3906 } 3907 3908 func TestLeafNodeQueueSubscriberUnsubscribe(t *testing.T) { 3909 s, opts := runLeafServer() 3910 defer s.Shutdown() 3911 3912 lc := createLeafConn(t, opts.LeafNode.Host, opts.LeafNode.Port) 3913 defer lc.Close() 3914 3915 leafSend, leafExpect := setupLeaf(t, lc, 1) 3916 leafSend("PING\r\n") 3917 leafExpect(pongRe) 3918 3919 // Create a client on leaf server and create a queue sub 3920 c1 := createClientConn(t, opts.Host, opts.Port) 3921 defer c1.Close() 3922 3923 send1, expect1 := setupConn(t, c1) 3924 send1("SUB foo bar 1\r\nPING\r\n") 3925 expect1(pongRe) 3926 3927 // Leaf should receive an LS+ foo bar 1 3928 leafExpect(lsubRe) 3929 3930 // Create a second client on leaf server and create queue sub on same group. 3931 c2 := createClientConn(t, opts.Host, opts.Port) 3932 defer c2.Close() 3933 3934 send2, expect2 := setupConn(t, c2) 3935 send2("SUB foo bar 1\r\nPING\r\n") 3936 expect2(pongRe) 3937 3938 // Leaf should receive an LS+ foo bar 2 3939 leafExpect(lsubRe) 3940 3941 // Now close c1 3942 c1.Close() 3943 3944 // Leaf should receive an indication that the queue group went to 1. 3945 // Which means LS+ foo bar 1. 3946 buf := leafExpect(lsubRe) 3947 if matches := lsubRe.FindAllSubmatch(buf, -1); len(matches) != 1 { 3948 t.Fatalf("Expected only 1 LS+, got %v", len(matches)) 3949 } 3950 // Make sure that we did not get a LS- at the same time. 3951 if bytes.Contains(buf, []byte("LS-")) { 3952 t.Fatalf("Unexpected LS- in response: %q", buf) 3953 } 3954 // Make sure we receive nothing... 3955 expectNothing(t, lc) 3956 } 3957 3958 func TestLeafNodeOriginClusterSingleHub(t *testing.T) { 3959 s, opts := runLeafServer() 3960 defer s.Shutdown() 3961 3962 c1 := ` 3963 listen: 127.0.0.1:-1 3964 cluster { name: ln22, listen: 127.0.0.1:-1 } 3965 leafnodes { remotes = [{ url: nats-leaf://127.0.0.1:%d }] } 3966 ` 3967 lconf1 := createConfFile(t, []byte(fmt.Sprintf(c1, opts.LeafNode.Port))) 3968 3969 ln1, lopts1 := RunServerWithConfig(lconf1) 3970 defer ln1.Shutdown() 3971 3972 c2 := ` 3973 listen: 127.0.0.1:-1 3974 cluster { name: ln22, listen: 127.0.0.1:-1, routes = [ nats-route://127.0.0.1:%d] } 3975 leafnodes { remotes = [{ url: nats-leaf://127.0.0.1:%d }] } 3976 ` 3977 lconf2 := createConfFile(t, []byte(fmt.Sprintf(c2, lopts1.Cluster.Port, opts.LeafNode.Port))) 3978 3979 ln2, _ := RunServerWithConfig(lconf2) 3980 defer ln2.Shutdown() 3981 3982 ln3, _ := RunServerWithConfig(lconf2) 3983 defer ln3.Shutdown() 3984 3985 checkClusterFormed(t, ln1, ln2, ln3) 3986 checkLeafNodeConnections(t, s, 3) 3987 3988 // So now we are setup with 3 solicited leafnodes all connected to a hub. 3989 // We will create two clients, one on each leafnode server. 3990 nc1, err := nats.Connect(ln1.ClientURL()) 3991 if err != nil { 3992 t.Fatalf("Error on connect: %v", err) 3993 } 3994 defer nc1.Close() 3995 3996 nc2, err := nats.Connect(ln2.ClientURL()) 3997 if err != nil { 3998 t.Fatalf("Error on connect: %v", err) 3999 } 4000 defer nc2.Close() 4001 4002 checkInterest := func(s *server.Server, subject string) bool { 4003 t.Helper() 4004 acc, _ := s.LookupAccount("$G") 4005 return acc.SubscriptionInterest(subject) 4006 } 4007 4008 waitForInterest := func(subject string, servers ...*server.Server) { 4009 t.Helper() 4010 checkFor(t, time.Second, 10*time.Millisecond, func() error { 4011 for _, s := range servers { 4012 if !checkInterest(s, subject) { 4013 return fmt.Errorf("No interest") 4014 } 4015 } 4016 return nil 4017 }) 4018 } 4019 4020 subj := "foo.bar" 4021 4022 sub, _ := nc2.SubscribeSync(subj) 4023 waitForInterest(subj, ln1, ln2, ln3, s) 4024 4025 // Make sure we truncated the subscription bouncing through the hub and back to other leafnodes. 4026 for _, s := range []*server.Server{ln1, ln3} { 4027 acc, _ := s.LookupAccount("$G") 4028 if nms := acc.Interest(subj); nms != 1 { 4029 t.Fatalf("Expected only one active subscription, got %d", nms) 4030 } 4031 } 4032 4033 // Send a message. 4034 nc1.Publish(subj, nil) 4035 nc1.Flush() 4036 // Wait to propagate 4037 time.Sleep(25 * time.Millisecond) 4038 4039 // Make sure we only get it once. 4040 if n, _, _ := sub.Pending(); n != 1 { 4041 t.Fatalf("Expected only one message, got %d", n) 4042 } 4043 } 4044 4045 func TestLeafNodeOriginCluster(t *testing.T) { 4046 ca := createClusterWithName(t, "A", 3) 4047 defer shutdownCluster(ca) 4048 4049 c1 := ` 4050 server_name: L1 4051 listen: 127.0.0.1:-1 4052 cluster { name: ln22, listen: 127.0.0.1:-1 } 4053 leafnodes { remotes = [{ url: nats-leaf://127.0.0.1:%d }] } 4054 ` 4055 lconf1 := createConfFile(t, []byte(fmt.Sprintf(c1, ca.opts[0].LeafNode.Port))) 4056 4057 ln1, lopts1 := RunServerWithConfig(lconf1) 4058 defer ln1.Shutdown() 4059 4060 c2 := ` 4061 server_name: L2 4062 listen: 127.0.0.1:-1 4063 cluster { name: ln22, listen: 127.0.0.1:-1, routes = [ nats-route://127.0.0.1:%d] } 4064 leafnodes { remotes = [{ url: nats-leaf://127.0.0.1:%d }] } 4065 ` 4066 lconf2 := createConfFile(t, []byte(fmt.Sprintf(c2, lopts1.Cluster.Port, ca.opts[1].LeafNode.Port))) 4067 4068 ln2, _ := RunServerWithConfig(lconf2) 4069 defer ln2.Shutdown() 4070 4071 c3 := ` 4072 server_name: L3 4073 listen: 127.0.0.1:-1 4074 cluster { name: ln22, listen: 127.0.0.1:-1, routes = [ nats-route://127.0.0.1:%d] } 4075 leafnodes { remotes = [{ url: nats-leaf://127.0.0.1:%d }] } 4076 ` 4077 lconf3 := createConfFile(t, []byte(fmt.Sprintf(c3, lopts1.Cluster.Port, ca.opts[2].LeafNode.Port))) 4078 4079 ln3, _ := RunServerWithConfig(lconf3) 4080 defer ln3.Shutdown() 4081 4082 checkClusterFormed(t, ln1, ln2, ln3) 4083 checkLeafNodeConnections(t, ca.servers[0], 1) 4084 checkLeafNodeConnections(t, ca.servers[1], 1) 4085 checkLeafNodeConnections(t, ca.servers[2], 1) 4086 4087 // So now we are setup with 3 solicited leafnodes connected to different servers in the hub cluster. 4088 // We will create two clients, one on each leafnode server. 4089 nc1, err := nats.Connect(ln1.ClientURL()) 4090 if err != nil { 4091 t.Fatalf("Error on connect: %v", err) 4092 } 4093 defer nc1.Close() 4094 4095 nc2, err := nats.Connect(ln2.ClientURL()) 4096 if err != nil { 4097 t.Fatalf("Error on connect: %v", err) 4098 } 4099 defer nc2.Close() 4100 4101 checkInterest := func(s *server.Server, subject string) bool { 4102 t.Helper() 4103 acc, _ := s.LookupAccount("$G") 4104 return acc.SubscriptionInterest(subject) 4105 } 4106 4107 waitForInterest := func(subject string, servers ...*server.Server) { 4108 t.Helper() 4109 checkFor(t, time.Second, 10*time.Millisecond, func() error { 4110 for _, s := range servers { 4111 if !checkInterest(s, subject) { 4112 return fmt.Errorf("No interest") 4113 } 4114 } 4115 return nil 4116 }) 4117 } 4118 4119 subj := "foo.bar" 4120 4121 sub, _ := nc2.SubscribeSync(subj) 4122 waitForInterest(subj, ln1, ln2, ln3, ca.servers[0], ca.servers[1], ca.servers[2]) 4123 4124 // Make sure we truncated the subscription bouncing through the hub and back to other leafnodes. 4125 for _, s := range []*server.Server{ln1, ln3} { 4126 acc, _ := s.LookupAccount("$G") 4127 if nms := acc.Interest(subj); nms != 1 { 4128 t.Fatalf("Expected only one active subscription, got %d", nms) 4129 } 4130 } 4131 4132 // Send a message. 4133 nc1.Publish(subj, nil) 4134 nc1.Flush() 4135 // Wait to propagate 4136 time.Sleep(25 * time.Millisecond) 4137 4138 // Make sure we only get it once. 4139 if n, _, _ := sub.Pending(); n != 1 { 4140 t.Fatalf("Expected only one message, got %d", n) 4141 } 4142 // eat the msg 4143 sub.NextMsg(time.Second) 4144 4145 // Now create interest on the hub side. This will draw the message from a leafnode 4146 // to the hub. We want to make sure that message does not bounce back to other leafnodes. 4147 nc3, err := nats.Connect(ca.servers[0].ClientURL()) 4148 if err != nil { 4149 t.Fatalf("Error on connect: %v", err) 4150 } 4151 defer nc3.Close() 4152 4153 wcSubj := "foo.*" 4154 wcsub, _ := nc3.SubscribeSync(wcSubj) 4155 // This is a placeholder that we can use to check all interest has propagated. 4156 nc3.SubscribeSync("bar") 4157 waitForInterest("bar", ln1, ln2, ln3, ca.servers[0], ca.servers[1], ca.servers[2]) 4158 4159 // Send another message. 4160 m := nats.NewMsg(subj) 4161 m.Header.Add("Accept-Encoding", "json") 4162 m.Header.Add("Authorization", "s3cr3t") 4163 m.Data = []byte("Hello Headers!") 4164 4165 nc1.PublishMsg(m) 4166 nc1.Flush() 4167 // Wait to propagate 4168 time.Sleep(25 * time.Millisecond) 4169 4170 // Make sure we only get it once. 4171 if n, _, _ := sub.Pending(); n != 1 { 4172 t.Fatalf("Expected only one message, got %d", n) 4173 } 4174 // Also for wc 4175 if n, _, _ := wcsub.Pending(); n != 1 { 4176 t.Fatalf("Expected only one message, got %d", n) 4177 } 4178 4179 // grab the msg 4180 msg, _ := sub.NextMsg(time.Second) 4181 if !bytes.Equal(m.Data, msg.Data) { 4182 t.Fatalf("Expected the payloads to match, wanted %q, got %q", m.Data, msg.Data) 4183 } 4184 if len(msg.Header) != 2 { 4185 t.Fatalf("Expected 2 header entries, got %d", len(msg.Header)) 4186 } 4187 if msg.Header.Get("Authorization") != "s3cr3t" { 4188 t.Fatalf("Expected auth header to match, wanted %q, got %q", "s3cr3t", msg.Header.Get("Authorization")) 4189 } 4190 } 4191 4192 func TestLeafNodeAdvertiseInCluster(t *testing.T) { 4193 o1 := testDefaultOptionsForLeafNodes() 4194 o1.Cluster.Name = "abc" 4195 o1.Cluster.Host = "127.0.0.1" 4196 o1.Cluster.Port = -1 4197 s1 := runGatewayServer(o1) 4198 defer s1.Shutdown() 4199 4200 lc := createLeafConn(t, o1.LeafNode.Host, o1.LeafNode.Port) 4201 defer lc.Close() 4202 4203 leafSend, leafExpect := setupLeaf(t, lc, 1) 4204 leafSend("PING\r\n") 4205 leafExpect(pongRe) 4206 4207 o2 := testDefaultOptionsForLeafNodes() 4208 o2.Cluster.Name = "abc" 4209 o2.Cluster.Host = "127.0.0.1" 4210 o2.Cluster.Port = -1 4211 o2.Routes = server.RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", o1.Cluster.Port)) 4212 o2.LeafNode.Advertise = "srvB:7222" 4213 s2 := runGatewayServer(o2) 4214 defer s2.Shutdown() 4215 4216 checkClusterFormed(t, s1, s2) 4217 4218 buf := leafExpect(infoRe) 4219 si := &server.Info{} 4220 json.Unmarshal(buf[5:], si) 4221 var ok bool 4222 for _, u := range si.LeafNodeURLs { 4223 if u == "srvB:7222" { 4224 ok = true 4225 break 4226 } 4227 } 4228 if !ok { 4229 t.Fatalf("Url srvB:7222 was not found: %q", si.GatewayURLs) 4230 } 4231 4232 o3 := testDefaultOptionsForLeafNodes() 4233 o3.Cluster.Name = "abc" 4234 o3.Cluster.Host = "127.0.0.1" 4235 o3.Cluster.Port = -1 4236 o3.Routes = server.RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", o1.Cluster.Port)) 4237 o3.LeafNode.Advertise = "srvB:7222" 4238 s3 := runGatewayServer(o3) 4239 defer s3.Shutdown() 4240 4241 checkClusterFormed(t, s1, s2, s3) 4242 4243 // Since it is the save srvB:7222 url, we should not get an update. 4244 expectNothing(t, lc) 4245 4246 // Now shutdown s2 and make sure that we are not getting an update 4247 // with srvB:7222 missing. 4248 s2.Shutdown() 4249 expectNothing(t, lc) 4250 } 4251 4252 func TestLeafNodeAndGatewaysStreamAndShadowSubs(t *testing.T) { 4253 server.SetGatewaysSolicitDelay(10 * time.Millisecond) 4254 defer server.ResetGatewaysSolicitDelay() 4255 conf1 := createConfFile(t, []byte(` 4256 port: -1 4257 system_account: SYS 4258 accounts { 4259 SYS {} 4260 A: { 4261 users: [{ user: a, password: pwd, permissions: {publish: [A.b.>]} }] 4262 exports: [{ stream: A.b.>, accounts: [B] }] 4263 }, 4264 B: { 4265 users: [{ user: b, password: pwd, permissions: {subscribe: [ A.b.> ]}}] 4266 imports: [{ stream: { account: A, subject: A.b.> } }] 4267 } 4268 } 4269 gateway { 4270 name: "A" 4271 port: -1 4272 } 4273 leafnodes { 4274 port: -1 4275 authorization: { 4276 users: [ 4277 {user: a, password: pwd, account: A} 4278 ] 4279 } 4280 } 4281 `)) 4282 s1, o1 := RunServerWithConfig(conf1) 4283 defer s1.Shutdown() 4284 4285 conf2 := createConfFile(t, []byte(fmt.Sprintf(` 4286 port: -1 4287 system_account: SYS 4288 accounts { 4289 SYS {} 4290 A: { 4291 users: [{ user: a, password: pwd, permissions: {publish: [A.b.>]} }] 4292 exports: [{ stream: A.b.>, accounts: [B] }] 4293 }, 4294 B: { 4295 users: [{ user: b, password: pwd, permissions: {subscribe: [ A.b.> ]}}] 4296 imports: [{ stream: { account: A, subject: A.b.> } }] 4297 } 4298 } 4299 gateway { 4300 name: "B" 4301 port: -1 4302 gateways [ 4303 { 4304 name: "A" 4305 urls: ["nats://127.0.0.1:%d"] 4306 } 4307 ] 4308 } 4309 `, o1.Gateway.Port))) 4310 s2, o2 := RunServerWithConfig(conf2) 4311 defer s2.Shutdown() 4312 4313 waitForOutboundGateways(t, s1, 1, 2*time.Second) 4314 waitForOutboundGateways(t, s2, 1, 2*time.Second) 4315 4316 nc, err := nats.Connect(fmt.Sprintf("nats://b:pwd@127.0.0.1:%d", o2.Port)) 4317 if err != nil { 4318 t.Fatalf("Error on connect: %v", err) 4319 } 4320 defer nc.Close() 4321 4322 sub, err := nc.SubscribeSync("A.b.>") 4323 if err != nil { 4324 t.Fatalf("Error on subscibe: %v", err) 4325 } 4326 defer sub.Unsubscribe() 4327 4328 conf3 := createConfFile(t, []byte(fmt.Sprintf(` 4329 port: -1 4330 system_account: SYS 4331 accounts: { 4332 SYS {} 4333 C: { 4334 imports: [{ stream: { account: D, subject: b.> }, prefix: A }] 4335 } 4336 D: { 4337 users: [{ user: d, password: pwd, permissions: {publish: [ b.> ]} }] 4338 exports: [{ stream: b.>, accounts: [C] }] 4339 } 4340 } 4341 leafnodes { 4342 remotes [ 4343 { 4344 url: "nats://a:pwd@127.0.0.1:%d" 4345 account: C 4346 } 4347 ] 4348 } 4349 `, o1.LeafNode.Port))) 4350 s3, o3 := RunServerWithConfig(conf3) 4351 defer s3.Shutdown() 4352 4353 checkLeafNodeConnected(t, s1) 4354 checkLeafNodeConnected(t, s3) 4355 4356 ncl, err := nats.Connect(fmt.Sprintf("nats://d:pwd@127.0.0.1:%d", o3.Port)) 4357 if err != nil { 4358 t.Fatalf("Error connecting: %v", err) 4359 } 4360 defer ncl.Close() 4361 4362 ncl.Publish("b.c", []byte("test")) 4363 if _, err := sub.NextMsg(time.Second); err != nil { 4364 t.Fatalf("Did not receive message: %v", err) 4365 } 4366 } 4367 4368 func TestLeafnodeHeaders(t *testing.T) { 4369 srv, opts := runLeafServer() 4370 defer srv.Shutdown() 4371 leaf, _ := runSolicitLeafServer(opts) 4372 defer leaf.Shutdown() 4373 4374 checkLeafNodeConnected(t, srv) 4375 checkLeafNodeConnected(t, leaf) 4376 4377 snc, err := nats.Connect(srv.ClientURL()) 4378 if err != nil { 4379 t.Fatalf(err.Error()) 4380 } 4381 defer snc.Close() 4382 4383 lnc, err := nats.Connect(leaf.ClientURL()) 4384 if err != nil { 4385 t.Fatalf(err.Error()) 4386 } 4387 defer lnc.Close() 4388 4389 // Start with subscription on leaf so that we check that srv has the interest 4390 // (since we are going to publish from srv) 4391 lsub, err := lnc.SubscribeSync("test") 4392 if err != nil { 4393 t.Fatalf("subscribe failed: %s", err) 4394 } 4395 lnc.Flush() 4396 checkSubInterest(t, srv, "$G", "test", time.Second) 4397 4398 ssub, err := snc.SubscribeSync("test") 4399 if err != nil { 4400 t.Fatalf("subscribe failed: %s", err) 4401 } 4402 4403 msg := nats.NewMsg("test") 4404 msg.Header.Add("Test", "Header") 4405 if len(msg.Header) == 0 { 4406 t.Fatalf("msg header is empty") 4407 } 4408 err = snc.PublishMsg(msg) 4409 if err != nil { 4410 t.Fatalf(err.Error()) 4411 } 4412 4413 smsg, err := ssub.NextMsg(time.Second) 4414 if err != nil { 4415 t.Fatalf("next failed: %s", err) 4416 } 4417 if len(smsg.Header) == 0 { 4418 t.Fatalf("server msgs header is empty") 4419 } 4420 4421 lmsg, err := lsub.NextMsg(time.Second) 4422 if err != nil { 4423 t.Fatalf("next failed: %s", err) 4424 } 4425 if len(lmsg.Header) == 0 { 4426 t.Fatalf("leaf msg header is empty") 4427 } 4428 }