mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
[ADDED] JetStream: ability to remove a server by peer ID instead of name
This can be helpful after a partial cluster restart since in that case the server name may not be known. However "server report jetstream" would report the peer ID that then can be used. For instance here is the output after a cluster restart where server "C" is not restarted. ``` nats -s nats://sys:pwd@localhost:4222 server report jetstream ... ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │ RAFT Meta Group Information │ ├─────────────────────────────────────────────────────┬────────┬─────────┬────────┬────────┬─────┤ │ Name │ Leader │ Current │ Online │ Active │ Lag │ ├─────────────────────────────────────────────────────┼────────┼─────────┼────────┼────────┼─────┤ │ A │ yes │ true │ true │ 0.00s │ 0 │ │ B │ │ true │ true │ 0.53s │ 0 │ │ Server name unknown at this time (peerID: jZ6RvVRH) │ │ false │ false │ 0.00s │ 0 │ ╰─────────────────────────────────────────────────────┴────────┴─────────┴────────┴────────┴─────╯ ``` With a change to the NATS CLI we could have something like: ``` nats -s nats://sys:pwd@localhost:4222 server raft peer-remove jZ6RvVRH --by_id ``` Signed-off-by: Ivan Kozlovic <ivan@synadia.com>
This commit is contained in:
@@ -7259,3 +7259,87 @@ func TestJetStreamClusterCompressedStreamMessages(t *testing.T) {
|
||||
t.Fatalf("Did not receive completion signal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJetStreamClusterRemovePeerByID(t *testing.T) {
|
||||
c := createJetStreamClusterExplicit(t, "R3S", 3)
|
||||
defer c.shutdown()
|
||||
|
||||
s := c.randomNonLeader()
|
||||
nc, js := jsClientConnect(t, s)
|
||||
defer nc.Close()
|
||||
|
||||
_, err := js.AddStream(&nats.StreamConfig{
|
||||
Name: "TEST",
|
||||
Subjects: []string{"foo", "bar"},
|
||||
Replicas: 3,
|
||||
})
|
||||
require_NoError(t, err)
|
||||
|
||||
// Wait for a leader
|
||||
c.waitOnStreamLeader(globalAccountName, "TEST")
|
||||
|
||||
// Get the name of the one that is not restarted
|
||||
srvName := c.opts[2].ServerName
|
||||
// And its node ID
|
||||
peerID := c.servers[2].Node()
|
||||
|
||||
nc.Close()
|
||||
// Now stop the whole cluster
|
||||
c.stopAll()
|
||||
// Restart all but one
|
||||
for i := 0; i < 2; i++ {
|
||||
opts := c.opts[i]
|
||||
s, o := RunServerWithConfig(opts.ConfigFile)
|
||||
c.servers[i] = s
|
||||
c.opts[i] = o
|
||||
}
|
||||
|
||||
c.waitOnClusterReadyWithNumPeers(2)
|
||||
c.waitOnStreamLeader(globalAccountName, "TEST")
|
||||
|
||||
// Now attempt to remove by name, this should fail because the cluster
|
||||
// was restarted and names are not persisted.
|
||||
ml := c.leader()
|
||||
nc, err = nats.Connect(ml.ClientURL(), nats.UserInfo("admin", "s3cr3t!"))
|
||||
require_NoError(t, err)
|
||||
defer nc.Close()
|
||||
|
||||
req := &JSApiMetaServerRemoveRequest{Server: srvName}
|
||||
jsreq, err := json.Marshal(req)
|
||||
require_NoError(t, err)
|
||||
rmsg, err := nc.Request(JSApiRemoveServer, jsreq, 2*time.Second)
|
||||
require_NoError(t, err)
|
||||
|
||||
var resp JSApiMetaServerRemoveResponse
|
||||
err = json.Unmarshal(rmsg.Data, &resp)
|
||||
require_NoError(t, err)
|
||||
require_True(t, resp.Error != nil)
|
||||
require_True(t, IsNatsErr(resp.Error, JSClusterServerNotMemberErr))
|
||||
|
||||
// Now try by ID, but first with an ID that does not match any peerID
|
||||
req.Server = "some_bad_id"
|
||||
req.ByID = true
|
||||
jsreq, err = json.Marshal(req)
|
||||
require_NoError(t, err)
|
||||
rmsg, err = nc.Request(JSApiRemoveServer, jsreq, 2*time.Second)
|
||||
require_NoError(t, err)
|
||||
|
||||
resp = JSApiMetaServerRemoveResponse{}
|
||||
err = json.Unmarshal(rmsg.Data, &resp)
|
||||
require_NoError(t, err)
|
||||
require_True(t, resp.Error != nil)
|
||||
require_True(t, IsNatsErr(resp.Error, JSClusterServerNotMemberErr))
|
||||
|
||||
// Now with the proper peer ID
|
||||
req.Server = peerID
|
||||
jsreq, err = json.Marshal(req)
|
||||
require_NoError(t, err)
|
||||
rmsg, err = nc.Request(JSApiRemoveServer, jsreq, 2*time.Second)
|
||||
require_NoError(t, err)
|
||||
|
||||
resp = JSApiMetaServerRemoveResponse{}
|
||||
err = json.Unmarshal(rmsg.Data, &resp)
|
||||
require_NoError(t, err)
|
||||
require_True(t, resp.Error == nil)
|
||||
require_True(t, resp.Success)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user