From 5a95c20a91a868ebf7ddc1350ec918d65780f70c Mon Sep 17 00:00:00 2001 From: Timo Tietavainen Date: Fri, 26 Nov 2021 00:57:59 +0200 Subject: [PATCH] SDL CLI 'get namespaces' -command key count Change existing -g,--group flag to -w,--wide flag. When the flag has been set, command shows DB namespaces per SDL cluster group address and how many DB keys there are per namespace. New command syntax is: sdlcli get namespaces [flags] Where supported flags are: -w, --wide, -h and --help. Issue-Id: RIC-113 Signed-off-by: Timo Tietavainen Change-Id: Iae0b044257a5e26e6cfaa48e2a5dca8441c23d5c --- internal/cli/namespaces.go | 60 ++++++++++++++++++++++++++--------------- internal/cli/namespaces_test.go | 26 +++++++++++------- internal/cli/types.go | 6 +++++ 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/internal/cli/namespaces.go b/internal/cli/namespaces.go index 9cf5ee8..d8c73ee 100644 --- a/internal/cli/namespaces.go +++ b/internal/cli/namespaces.go @@ -28,6 +28,7 @@ import ( "os" "sort" "strings" + "text/tabwriter" ) func init() { @@ -41,14 +42,14 @@ func newNamespacesCmd(dbCreateCb DbCreateCb) *cobra.Command { Long: "List all the namespaces in database", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { - showPerDb, _ := cmd.Flags().GetBool("group") + showWide, _ := cmd.Flags().GetBool("wide") nsMap, err := runNamespaces(dbCreateCb) if err != nil { cmd.PrintErrf("%s\n", buf.String()) return err } - if showPerDb { - printNamespacesPerDb(cmd, nsMap) + if showWide { + printNamespacesWide(cmd, nsMap) } else { printNamespaces(cmd, nsMap) } @@ -56,12 +57,12 @@ func newNamespacesCmd(dbCreateCb DbCreateCb) *cobra.Command { }, } cmd.SetOut(os.Stdout) - cmd.Flags().BoolP("group", "g", false, "Show namespaces per SDL DB cluster group") + cmd.Flags().BoolP("wide", "w", false, "Show SDL DB cluster address, namespace name and its keys count") return cmd } -func runNamespaces(dbCreateCb DbCreateCb) (map[string][]string, error) { - nsMap := make(map[string][]string) +func runNamespaces(dbCreateCb DbCreateCb) (nsMap, error) { + nsMap := make(nsMap) for _, dbInst := range dbCreateCb().Instances { keys, err := dbInst.Keys("*") if err != nil { @@ -71,13 +72,20 @@ func runNamespaces(dbCreateCb DbCreateCb) (map[string][]string, error) { if err != nil { return nil, err } + + if _, ok := nsMap[id]; !ok { + nsMap[id] = make(nsKeyMap) + } + for _, key := range keys { namespace, err := parseKeyNamespace(key) if err != nil { return nil, err } if isUniqueNamespace(nsMap[id], namespace) { - nsMap[id] = append(nsMap[id], namespace) + nsMap[id][namespace] = 1 + } else { + nsMap[id][namespace]++ } } } @@ -105,36 +113,44 @@ func parseKeyNamespace(key string) (string, error) { return str[:eIndex], nil } -func isUniqueNamespace(namespaces []string, newNs string) bool { - for _, n := range namespaces { - if n == newNs { - return false - } +func isUniqueNamespace(namespaces nsKeyMap, newNs string) bool { + if _, ok := namespaces[newNs]; ok { + return false } return true } -func printNamespaces(cmd *cobra.Command, nsMap map[string][]string) { - var namespaces []string - for _, nsList := range nsMap { - namespaces = append(namespaces, nsList...) +func printNamespaces(cmd *cobra.Command, nsMap nsMap) { + var nsList []string + for _, nsKeyMap := range nsMap { + for ns, _ := range nsKeyMap { + nsList = append(nsList, ns) + } } - sort.Strings(namespaces) - for _, ns := range namespaces { + sort.Strings(nsList) + for _, ns := range nsList { cmd.Println(ns) } } -func printNamespacesPerDb(cmd *cobra.Command, nsMap map[string][]string) { - for addr, nsList := range nsMap { +func printNamespacesWide(cmd *cobra.Command, nsMap nsMap) { + var nsList []string + w := tabwriter.NewWriter(cmd.OutOrStdout(), 6, 4, 3, ' ', 0) + fmt.Fprintln(w, "ADDRESS\tNAMESPACE\tKEYS\t") + for addr, nsKeyMap := range nsMap { + for ns, _ := range nsKeyMap { + nsList = append(nsList, ns) + } sort.Strings(nsList) for _, ns := range nsList { if addr == "" { - cmd.Printf("%s\n", ns) + fmt.Fprintf(w, "\t%s\t%d\t\n", ns, nsKeyMap[ns]) } else { - cmd.Printf("%s: %s\n", addr, ns) + fmt.Fprintf(w, "%s\t%s\t%d\t\n", addr, ns, nsKeyMap[ns]) } } + nsList = nil } + w.Flush() } diff --git a/internal/cli/namespaces_test.go b/internal/cli/namespaces_test.go index 28b6343..65bec5f 100644 --- a/internal/cli/namespaces_test.go +++ b/internal/cli/namespaces_test.go @@ -112,8 +112,12 @@ func TestNamespacesCmdSuccess(t *testing.T) { mNs.dbIface.AssertExpectations(t) } -func TestNamespacesCmdWithPerDbFlagSuccess(t *testing.T) { - expOut := "1.2.3.4:6379: ns1\n" + "1.2.3.4:6379: ns2\n" + "1.2.3.4:6379: ns3\n" +func TestNamespacesCmdWithWideFlagSuccess(t *testing.T) { + expOut := + "ADDRESS NAMESPACE KEYS \n" + + "1.2.3.4:6379 ns1 2 \n" + + "1.2.3.4:6379 ns2 1 \n" + + "1.2.3.4:6379 ns3 1 \n" buf := new(bytes.Buffer) setupNamespacesCliMock([]string{ "{ns1},key1", @@ -124,7 +128,7 @@ func TestNamespacesCmdWithPerDbFlagSuccess(t *testing.T) { cmd := cli.NewNamespacesCmdForTest(newNsMockDatabase) cmd.SetOut(buf) cmd.SetErr(buf) - cmd.SetArgs([]string{"--group"}) + cmd.SetArgs([]string{"--wide"}) err := cmd.Execute() result := buf.String() @@ -150,14 +154,14 @@ func TestNamespacesCmdNoKeysInDbSuccess(t *testing.T) { mNs.dbIface.AssertExpectations(t) } -func TestNamespacesCmdWithPerDbFlagNoKeysInDbSuccess(t *testing.T) { - expOut := "" +func TestNamespacesCmdWithWideFlagNoKeysInDbSuccess(t *testing.T) { + expOut := "ADDRESS NAMESPACE KEYS \n" buf := new(bytes.Buffer) setupNamespacesCliMock([]string{}, "1.2.3.4", nil, nil) cmd := cli.NewNamespacesCmdForTest(newNsMockDatabase) cmd.SetOut(buf) cmd.SetErr(buf) - cmd.SetArgs([]string{"--group"}) + cmd.SetArgs([]string{"-w"}) err := cmd.Execute() result := buf.String() @@ -167,8 +171,12 @@ func TestNamespacesCmdWithPerDbFlagNoKeysInDbSuccess(t *testing.T) { mNs.dbIface.AssertExpectations(t) } -func TestNamespacesCmdWithPerDbFlagStandaloneRedisAddressMissingSuccess(t *testing.T) { - expOut := "ns1\n" + "ns2\n" + "ns3\n" +func TestNamespacesCmdWithWideFlagStandaloneRedisAddressMissingSuccess(t *testing.T) { + expOut := + "ADDRESS NAMESPACE KEYS \n" + + " ns1 2 \n" + + " ns2 1 \n" + + " ns3 1 \n" buf := new(bytes.Buffer) setupNamespacesCliMock([]string{ "{ns1},key1", @@ -179,7 +187,7 @@ func TestNamespacesCmdWithPerDbFlagStandaloneRedisAddressMissingSuccess(t *testi cmd := cli.NewNamespacesCmdForTest(newNsMockDatabase) cmd.SetOut(buf) cmd.SetErr(buf) - cmd.SetArgs([]string{"--group"}) + cmd.SetArgs([]string{"--wide"}) err := cmd.Execute() result := buf.String() diff --git a/internal/cli/types.go b/internal/cli/types.go index f5c4439..eb86905 100644 --- a/internal/cli/types.go +++ b/internal/cli/types.go @@ -65,5 +65,11 @@ func newKeysArgs(ns string, pattern string) keysArgs { } } +//nsMap is a map having SDL DB cluster address as a key and namespace map of type nsKeyMap as a value +type nsMap map[string]nsKeyMap + +//nsKeyMap is a map having namespace as a key and DB key count as a value +type nsKeyMap map[string]uint32 + //SdlCliApp constant defines the name of the SDL CLI application const SdlCliApp = "sdlcli" -- 2.16.6