From 9dc633fd6ed6b69e6636e79b94b890b01196c576 Mon Sep 17 00:00:00 2001 From: Derek Collison Date: Tue, 22 Nov 2022 15:47:56 -0800 Subject: [PATCH] Add a system account responder for IDZ along with STATSZ etc. This will avoid write locks and any non-static data. Signed-off-by: Derek Collison --- server/events.go | 21 +++++++++++++++++++++ server/events_test.go | 2 +- server/monitor_test.go | 35 +++++++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/server/events.go b/server/events.go index cdad49c197..6c61442f40 100644 --- a/server/events.go +++ b/server/events.go @@ -163,6 +163,13 @@ type accNumConnsReq struct { Account string `json:"acc"` } +// ServerID is basic static info for a server. +type ServerID struct { + Name string `json:"name"` + Host string `json:"host"` + ID string `json:"id"` +} + // ServerInfo identifies remote servers. type ServerInfo struct { Name string `json:"name"` @@ -881,6 +888,7 @@ func (s *Server) initEventTracking() { s.Errorf("Error setting up internal tracking: %v", err) } monSrvc := map[string]msgHandler{ + "IDZ": s.idzReq, "STATSZ": s.statszReq, "VARZ": func(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) { optz := &VarzEventOptions{} @@ -1574,6 +1582,19 @@ func (s *Server) statszReq(sub *subscription, c *client, _ *Account, subject, re s.mu.Unlock() } +// idzReq is for a request for basic static server info. +// Try to not hold the write lock or dynamically create data. +func (s *Server) idzReq(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) { + s.mu.RLock() + defer s.mu.RUnlock() + id := &ServerID{ + Name: s.info.Name, + Host: s.info.Host, + ID: s.info.ID, + } + s.sendInternalMsg(reply, _EMPTY_, nil, &id) +} + var errSkipZreq = errors.New("filtered response") const ( diff --git a/server/events_test.go b/server/events_test.go index 605e687f1a..61ce61b202 100644 --- a/server/events_test.go +++ b/server/events_test.go @@ -1664,7 +1664,7 @@ func TestSystemAccountWithGateways(t *testing.T) { // If this tests fails with wrong number after 10 seconds we may have // added a new inititial subscription for the eventing system. - checkExpectedSubs(t, 45, sa) + checkExpectedSubs(t, 47, sa) // Create a client on B and see if we receive the event urlb := fmt.Sprintf("nats://%s:%d", ob.Host, ob.Port) diff --git a/server/monitor_test.go b/server/monitor_test.go index b3cfac6d38..0e666bb605 100644 --- a/server/monitor_test.go +++ b/server/monitor_test.go @@ -2250,15 +2250,15 @@ func TestServerIDs(t *testing.T) { for mode := 0; mode < 2; mode++ { v := pollVarz(t, s, mode, murl+"varz", nil) - if v.ID == "" { + if v.ID == _EMPTY_ { t.Fatal("Varz ID is empty") } c := pollConz(t, s, mode, murl+"connz", nil) - if c.ID == "" { + if c.ID == _EMPTY_ { t.Fatal("Connz ID is empty") } r := pollRoutez(t, s, mode, murl+"routez", nil) - if r.ID == "" { + if r.ID == _EMPTY_ { t.Fatal("Routez ID is empty") } if v.ID != c.ID || v.ID != r.ID { @@ -3933,7 +3933,7 @@ func TestMonitorAccountz(t *testing.T) { body = string(readBody(t, fmt.Sprintf("http://127.0.0.1:%d%s?acc=$SYS", s.MonitorAddr().Port, AccountzPath))) require_Contains(t, body, `"account_detail": {`) require_Contains(t, body, `"account_name": "$SYS",`) - require_Contains(t, body, `"subscriptions": 40,`) + require_Contains(t, body, `"subscriptions": 42,`) require_Contains(t, body, `"is_system": true,`) require_Contains(t, body, `"system_account": "$SYS"`) @@ -4569,3 +4569,30 @@ func TestMonitorWebsocket(t *testing.T) { } } } + +func TestServerIDZRequest(t *testing.T) { + conf := createConfFile(t, []byte(` + listen: 127.0.0.1:-1 + server_name: TEST22 + # For access to system account. + accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } } + `)) + defer removeFile(t, conf) + + s, _ := RunServerWithConfig(conf) + defer s.Shutdown() + + nc, err := nats.Connect(s.ClientURL(), nats.UserInfo("admin", "s3cr3t!")) + require_NoError(t, err) + + subject := fmt.Sprintf(serverPingReqSubj, "IDZ") + resp, err := nc.Request(subject, nil, time.Second) + require_NoError(t, err) + + var sid ServerID + err = json.Unmarshal(resp.Data, &sid) + require_NoError(t, err) + + require_True(t, sid.Name == "TEST22") + require_True(t, strings.HasPrefix(sid.ID, "N")) +}