Fix sdlcli healthcheck DBAAS status in SEP install
[ric-plt/sdlgo.git] / internal / cli / healthcheck.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         "gerrit.o-ran-sc.org/r/ric-plt/sdlgo/internal/sdlgoredis"
28         "github.com/spf13/cobra"
29         "os"
30         "text/tabwriter"
31 )
32
33 func init() {
34         rootCmd.AddCommand(newHealthCheckCmd(newDatabase))
35 }
36
37 func newHealthCheckCmd(dbCreateCb DbCreateCb) *cobra.Command {
38         cmd := &cobra.Command{
39                 Use:   "healthcheck",
40                 Short: "Validate SDL database healthiness",
41                 Long:  `Validate SDL database healthiness`,
42                 Args:  cobra.ExactArgs(0),
43                 RunE: func(cmd *cobra.Command, args []string) error {
44                         states, err := runHealthCheck(dbCreateCb)
45                         printHealthStatus(cmd, states)
46                         return err
47                 },
48         }
49         cmd.SetOut(os.Stdout)
50         return cmd
51 }
52
53 func runHealthCheck(dbCreateCb DbCreateCb) ([]sdlgoredis.DbState, error) {
54         var anyErr error
55         var states []sdlgoredis.DbState
56         for _, dbInst := range dbCreateCb().Instances {
57                 state, err := dbInst.State()
58                 if err != nil {
59                         anyErr = err
60                 }
61                 states = append(states, *state)
62         }
63         return states, anyErr
64 }
65
66 func printHealthStatus(cmd *cobra.Command, dbStates []sdlgoredis.DbState) {
67         var anyErr error
68         w := tabwriter.NewWriter(cmd.OutOrStdout(), 6, 4, 3, ' ', 0)
69         fmt.Fprintln(w, "CLUSTER\tROLE\tADDRESS\tSTATUS\tERROR\t")
70
71         for i, dbState := range dbStates {
72                 if err := dbState.IsOnline(); err != nil {
73                         anyErr = err
74                 }
75
76                 if err := printPrimaryHealthStatus(w, i, &dbState); err != nil {
77                         anyErr = err
78                 }
79
80                 if err := printReplicasHealthStatus(w, i, &dbState); err != nil {
81                         anyErr = err
82                 }
83
84                 if err := printSentinelsHealthStatus(w, i, &dbState); err != nil {
85                         anyErr = err
86                 }
87         }
88         if anyErr == nil {
89                 cmd.Println("Overall status: OK")
90         } else {
91                 cmd.Println("Overall status: NOK")
92         }
93         cmd.Println("")
94         w.Flush()
95 }
96
97 func printPrimaryHealthStatus(w *tabwriter.Writer, clusterID int, dbState *sdlgoredis.DbState) error {
98         addr := printAddress(dbState.PrimaryDbState.GetAddress())
99         err := dbState.PrimaryDbState.IsOnline()
100         if err != nil {
101                 fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t\n", clusterID, "primary", addr, "NOK", err.Error())
102         } else {
103                 fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t\n", clusterID, "primary", addr, "OK", "<none>")
104         }
105         return err
106 }
107
108 func printReplicasHealthStatus(w *tabwriter.Writer, clusterID int, dbState *sdlgoredis.DbState) error {
109         var anyErr error
110
111         if dbState.ReplicasDbState != nil {
112                 if dbState.ConfigNodeCnt > len(dbState.ReplicasDbState.States)+1 {
113                         err := fmt.Errorf("Configured DBAAS nodes %d but only 1 primary and %d replicas",
114                                 dbState.ConfigNodeCnt, len(dbState.ReplicasDbState.States))
115                         fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t\n", clusterID, "replica", "<none>", "NOK", err.Error())
116                         anyErr = err
117                 }
118                 for _, state := range dbState.ReplicasDbState.States {
119                         if err := printReplicaHealthStatus(w, clusterID, state); err != nil {
120                                 anyErr = err
121                         }
122                 }
123         }
124         return anyErr
125 }
126
127 func printReplicaHealthStatus(w *tabwriter.Writer, clusterID int, dbState *sdlgoredis.ReplicaDbState) error {
128         addr := printAddress(dbState.GetAddress())
129         err := dbState.IsOnline()
130         if err != nil {
131                 fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t\n", clusterID, "replica", addr, "NOK", err.Error())
132         } else {
133                 fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t\n", clusterID, "replica", addr, "OK", "<none>")
134         }
135         return err
136 }
137
138 func printSentinelsHealthStatus(w *tabwriter.Writer, clusterID int, dbState *sdlgoredis.DbState) error {
139         var anyErr error
140         if dbState.SentinelsDbState != nil {
141                 for _, state := range dbState.SentinelsDbState.States {
142                         if err := printSentinelHealthStatus(w, clusterID, state); err != nil {
143                                 anyErr = err
144                         }
145                 }
146         }
147         return anyErr
148 }
149 func printSentinelHealthStatus(w *tabwriter.Writer, clusterID int, dbState *sdlgoredis.SentinelDbState) error {
150         err := dbState.IsOnline()
151         if err != nil {
152                 fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t\n", clusterID, "sentinel", dbState.GetAddress(), "NOK", err.Error())
153         }
154         return err
155 }
156
157 func printAddress(address string) string {
158         if address == "" {
159                 return "<none>"
160         }
161         return address
162 }