Implement SDL CLI 'healthcheck' -command
[ric-plt/sdlgo.git] / internal / sdlgoredis / sdlgosentinel.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 sdlgoredis
24
25 import (
26         "github.com/go-redis/redis/v7"
27 )
28
29 type Sentinel struct {
30         IredisSentinelClient
31         Cfg *Config
32 }
33
34 type IredisSentinelClient interface {
35         Master(name string) *redis.StringStringMapCmd
36         Slaves(name string) *redis.SliceCmd
37 }
38
39 type RedisSentinelCreateCb func(cfg *Config, addr string) *Sentinel
40
41 func newRedisSentinel(cfg *Config, addr string) *Sentinel {
42         redisAddress := addr + ":" + cfg.sentinelPort
43         return &Sentinel{
44                 IredisSentinelClient: redis.NewSentinelClient(&redis.Options{
45                         Addr:       redisAddress,
46                         Password:   "", // no password set
47                         DB:         0,  // use default DB
48                         PoolSize:   20,
49                         MaxRetries: 2,
50                 }),
51                 Cfg: cfg,
52         }
53 }
54
55 func (s *Sentinel) GetDbState() (*DbState, error) {
56         state := new(DbState)
57         mState, mErr := s.getMasterDbState()
58         rState, rErr := s.getReplicasState()
59         state.MasterDbState = *mState
60         state.ReplicasDbState = rState
61         if mErr == nil {
62                 return state, rErr
63         }
64         return state, mErr
65 }
66
67 func (s *Sentinel) getMasterDbState() (*MasterDbState, error) {
68         state := new(MasterDbState)
69         redisVal, redisErr := s.Master(s.Cfg.masterName).Result()
70         if redisErr == nil {
71                 state.Fields.Ip = redisVal["ip"]
72                 state.Fields.Port = redisVal["port"]
73                 state.Fields.Flags = redisVal["flags"]
74                 state.Fields.Role = redisVal["role-reported"]
75         }
76         state.Err = redisErr
77         return state, redisErr
78 }
79
80 func (s *Sentinel) getReplicasState() (*ReplicasDbState, error) {
81         states := new(ReplicasDbState)
82         states.States = make([]*ReplicaDbState, 0)
83
84         redisVal, redisErr := s.Slaves(s.Cfg.masterName).Result()
85         if redisErr == nil {
86                 for _, redisSlave := range redisVal {
87                         replicaState := readReplicaState(redisSlave.([]interface{}))
88                         states.States = append(states.States, replicaState)
89                 }
90         }
91         states.Err = redisErr
92         return states, redisErr
93 }
94
95 func readReplicaState(redisSlaves []interface{}) *ReplicaDbState {
96         state := new(ReplicaDbState)
97         for i := 0; i < len(redisSlaves); i += 2 {
98                 if redisSlaves[i].(string) == "ip" {
99                         state.Fields.Ip = redisSlaves[i+1].(string)
100                 } else if redisSlaves[i].(string) == "port" {
101                         state.Fields.Port = redisSlaves[i+1].(string)
102                 } else if redisSlaves[i].(string) == "flags" {
103                         state.Fields.Flags = redisSlaves[i+1].(string)
104                 } else if redisSlaves[i].(string) == "role-reported" {
105                         state.Fields.Role = redisSlaves[i+1].(string)
106                 } else if redisSlaves[i].(string) == "master-link-status" {
107                         state.Fields.MasterLinkStatus = redisSlaves[i+1].(string)
108                 }
109         }
110         return state
111 }