Merge "RIC:1060: Change in PTL"
[ric-plt/sdlgo.git] / internal / cli / namespaces.go
1 /*
2    Copyright (c) 2021 AT&T Intellectual Property.
3    Copyright (c) 2018-2021 Nokia.
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 */
17
18 /*
19  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
20  * platform project (RICP).
21  */
22
23 package cli
24
25 import (
26         "fmt"
27         "github.com/spf13/cobra"
28         "os"
29         "sort"
30         "strings"
31         "text/tabwriter"
32 )
33
34 func init() {
35         getCmd.AddCommand(newNamespacesCmd(newDatabase))
36 }
37
38 func newNamespacesCmd(dbCreateCb DbCreateCb) *cobra.Command {
39         cmd := &cobra.Command{
40                 Use:   "namespaces",
41                 Short: "List all the namespaces in database",
42                 Long:  "List all the namespaces in database",
43                 Args:  cobra.ExactArgs(0),
44                 RunE: func(cmd *cobra.Command, args []string) error {
45                         showWide, _ := cmd.Flags().GetBool("wide")
46                         nsMap, err := runNamespaces(dbCreateCb)
47                         if err != nil {
48                                 cmd.PrintErrf("%s\n", buf.String())
49                                 return err
50                         }
51                         if showWide {
52                                 printNamespacesWide(cmd, nsMap)
53                         } else {
54                                 printNamespaces(cmd, nsMap)
55                         }
56                         return err
57                 },
58         }
59         cmd.SetOut(os.Stdout)
60         cmd.Flags().BoolP("wide", "w", false, "Show SDL DB cluster address, namespace name and its keys count")
61         return cmd
62 }
63
64 func runNamespaces(dbCreateCb DbCreateCb) (nsMap, error) {
65         nsMap := make(nsMap)
66         for _, dbInst := range dbCreateCb().Instances {
67                 keys, err := dbInst.Keys("*")
68                 if err != nil {
69                         return nil, err
70                 }
71                 id, err := getServiceAddress(dbInst)
72                 if err != nil {
73                         return nil, err
74                 }
75
76                 if _, ok := nsMap[id]; !ok {
77                         nsMap[id] = make(nsKeyMap)
78                 }
79
80                 for _, key := range keys {
81                         namespace, err := parseKeyNamespace(key)
82                         if err != nil {
83                                 return nil, err
84                         }
85                         if isUniqueNamespace(nsMap[id], namespace) {
86                                 nsMap[id][namespace] = 1
87                         } else {
88                                 nsMap[id][namespace]++
89                         }
90                 }
91         }
92         return nsMap, nil
93 }
94
95 func getServiceAddress(db iDatabase) (string, error) {
96         state, err := db.State()
97         if err != nil {
98                 return "", err
99         }
100         return state.PrimaryDbState.GetAddress(), nil
101 }
102
103 func parseKeyNamespace(key string) (string, error) {
104         sIndex := strings.Index(key, "{")
105         if sIndex == -1 {
106                 return "", fmt.Errorf("Namespace parsing error, no '{' in key string '%s'", key)
107         }
108         str := key[sIndex+len("{"):]
109         eIndex := strings.Index(str, "}")
110         if eIndex == -1 {
111                 return "", fmt.Errorf("Namespace parsing error, no '}' in key string '%s'", key)
112         }
113         return str[:eIndex], nil
114 }
115
116 func isUniqueNamespace(namespaces nsKeyMap, newNs string) bool {
117         if _, ok := namespaces[newNs]; ok {
118                 return false
119         }
120         return true
121 }
122
123 func printNamespaces(cmd *cobra.Command, nsMap nsMap) {
124         var nsList []string
125         for _, nsKeyMap := range nsMap {
126                 for ns, _ := range nsKeyMap {
127                         nsList = append(nsList, ns)
128                 }
129         }
130
131         sort.Strings(nsList)
132         for _, ns := range nsList {
133                 cmd.Println(ns)
134         }
135 }
136
137 func printNamespacesWide(cmd *cobra.Command, nsMap nsMap) {
138         var nsList []string
139         w := tabwriter.NewWriter(cmd.OutOrStdout(), 6, 4, 3, ' ', 0)
140         fmt.Fprintln(w, "ADDRESS\tNAMESPACE\tKEYS\t")
141         for addr, nsKeyMap := range nsMap {
142                 for ns, _ := range nsKeyMap {
143                         nsList = append(nsList, ns)
144                 }
145                 sort.Strings(nsList)
146                 for _, ns := range nsList {
147                         if addr == "" {
148                                 fmt.Fprintf(w, "\t%s\t%d\t\n", ns, nsKeyMap[ns])
149                         } else {
150                                 fmt.Fprintf(w, "%s\t%s\t%d\t\n", addr, ns, nsKeyMap[ns])
151                         }
152                 }
153                 nsList = nil
154         }
155         w.Flush()
156 }