From 6ffe956f918e3fac2e939847268b2ae94684a738 Mon Sep 17 00:00:00 2001 From: Timo Tietavainen Date: Mon, 14 Mar 2022 07:19:47 +0200 Subject: [PATCH] Read list type of environment variables DBAAS Helm Charts appconfig has been changed to have individual ports and master names for each SDL cluster due to problems seen with DBAAS upgrade and rollback caused by re-allocation of the same address/port of Redis to some other SDL cluster. Implement support for new list type environment variables reading in SDL: * DBAAS_SERVICE_PORT * DBAAS_SERVICE_SENTINEL_PORT * DBAAS_MASTER_NAME Issue-Id: RIC-698 Signed-off-by: Timo Tietavainen Change-Id: I9a9d94e536e0e4e2a174ef0b6fb2beb4c73ef4f5 --- docs/release-notes.rst | 4 + example/example.go | 27 +++++- internal/sdlgoredis/sdlgoredis.go | 135 +++++++++++++++++----------- internal/sdlgoredis/sdlgoredis_test.go | 155 ++++++++++++++++++++++++++------- internal/sdlgoredis/sdlgosentinel.go | 26 +++--- 5 files changed, 246 insertions(+), 101 deletions(-) diff --git a/docs/release-notes.rst b/docs/release-notes.rst index d792912..bb7fdc4 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -30,6 +30,10 @@ This document provides the release notes of the sdlgo. Version history --------------- +[0.10.0] - 2022-03-14 + +* Enable redis/sentinel port and sentinel master name configuration + [0.9.6] - 2022-02-07 * Fix multi-namespace SDL event subscribe diff --git a/example/example.go b/example/example.go index aee1c19..33a9194 100644 --- a/example/example.go +++ b/example/example.go @@ -26,6 +26,7 @@ import ( "fmt" "gerrit.o-ran-sc.org/r/ric-plt/sdlgo" + "time" ) var sdl *sdlgo.SyncStorage @@ -59,8 +60,28 @@ func exampleClose() { sdl.Close() } +func sdlNotify(ch string, events ...string) { + fmt.Printf("CB1 channel=%+v, events=%+v\n", ch, events[0]) +} + +func sdlNotify2(ch string, events ...string) { + fmt.Printf("CB2 channel=%+v, events=%+v\n", ch, events[0]) +} + func main() { - exampleSet() - exampleGet() - exampleClose() + sdl.SubscribeChannel("dcapterm_subsRTPM-localhost:55566", sdlNotify, "my-ch") + sdl.SubscribeChannel("dcapterm_subsRTPM-localhost:55565", sdlNotify2, "my-ch") + time.Sleep(3 * time.Second) + sdl.SetAndPublish("dcapterm_subsRTPM-localhost:55566", []string{"my-ch", "my-event1"}, "my-key", "my-data") + sdl.SetAndPublish("dcapterm_subsRTPM-localhost:55565", []string{"my-ch", "my-event2"}, "my-key", "my-data") + + time.Sleep(2 * time.Second) + //sdl.UnsubscribeChannel("dcapterm_subsRTPM-localhost:55565", "my-ch") + //time.Sleep(2 * time.Second) + //sdl.SetAndPublish("dcapterm_subsRTPM-localhost:55565", []string{"my-ch", "my-event2"}, "my-key", "my-data") + time.Sleep(2 * time.Second) + + //exampleSet() + //exampleGet() + //exampleClose() } diff --git a/internal/sdlgoredis/sdlgoredis.go b/internal/sdlgoredis/sdlgoredis.go index 9162f39..20ed0bf 100644 --- a/internal/sdlgoredis/sdlgoredis.go +++ b/internal/sdlgoredis/sdlgoredis.go @@ -1,6 +1,6 @@ /* Copyright (c) 2019 AT&T Intellectual Property. - Copyright (c) 2018-2019 Nokia. + Copyright (c) 2018-2022 Nokia. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -56,12 +56,12 @@ type sharedCbMap struct { } type Config struct { - hostname string - port string - masterName string - sentinelPort string - clusterAddrList string - nodeCnt string + hostname string + ports []string + masterNames []string + sentinelPorts []string + clusterAddrs []string + nodeCnt string } type DB struct { @@ -72,8 +72,11 @@ type DB struct { redisModules bool sCbMap *sharedCbMap ch intChannels - cfg Config addr string + port string + sentinelPort string + masterName string + nodeCnt string } type Subscriber interface { @@ -154,7 +157,8 @@ func subscribeNotifications(ctx context.Context, client RedisClient, channels .. return client.Subscribe(ctx, channels...) } -func CreateDB(client RedisClient, subscribe SubscribeFn, sentinelCreateCb RedisSentinelCreateCb, cfg Config, sentinelAddr string) *DB { +func CreateDB(client RedisClient, subscribe SubscribeFn, sentinelCreateCb RedisSentinelCreateCb, + addr, port, sentinelPort, masterName, nodeCnt string) *DB { db := DB{ ctx: context.Background(), client: client, @@ -167,8 +171,11 @@ func CreateDB(client RedisClient, subscribe SubscribeFn, sentinelCreateCb RedisS removeChannel: make(chan string), exit: make(chan bool), }, - cfg: cfg, - addr: sentinelAddr, + addr: addr, + sentinelPort: sentinelPort, + port: port, + masterName: masterName, + nodeCnt: nodeCnt, } return &db @@ -181,13 +188,23 @@ func Create() []*DB { func readConfig(osI OS) Config { cfg := Config{ - hostname: osI.Getenv("DBAAS_SERVICE_HOST", "localhost"), - port: osI.Getenv("DBAAS_SERVICE_PORT", "6379"), - masterName: osI.Getenv("DBAAS_MASTER_NAME", ""), - sentinelPort: osI.Getenv("DBAAS_SERVICE_SENTINEL_PORT", ""), - clusterAddrList: osI.Getenv("DBAAS_CLUSTER_ADDR_LIST", ""), - nodeCnt: osI.Getenv("DBAAS_NODE_COUNT", "1"), + hostname: osI.Getenv("DBAAS_SERVICE_HOST", "localhost"), + ports: strings.Split(osI.Getenv("DBAAS_SERVICE_PORT", "6379"), ","), + nodeCnt: osI.Getenv("DBAAS_NODE_COUNT", "1"), } + + if addrStr := osI.Getenv("DBAAS_CLUSTER_ADDR_LIST", ""); addrStr != "" { + cfg.clusterAddrs = strings.Split(addrStr, ",") + } else if cfg.hostname != "" { + cfg.clusterAddrs = append(cfg.clusterAddrs, cfg.hostname) + } + if sntPortStr := osI.Getenv("DBAAS_SERVICE_SENTINEL_PORT", ""); sntPortStr != "" { + cfg.sentinelPorts = strings.Split(sntPortStr, ",") + } + if nameStr := osI.Getenv("DBAAS_MASTER_NAME", ""); nameStr != "" { + cfg.masterNames = strings.Split(nameStr, ",") + } + completeConfig(&cfg) return cfg } @@ -205,47 +222,61 @@ func (osImpl) Getenv(key string, defValue string) string { return val } -func ReadConfigAndCreateDbClients(osI OS, clientCreator RedisClientCreator, - subscribe SubscribeFn, - sentinelCreateCb RedisSentinelCreateCb) []*DB { - cfg := readConfig(osI) - return createDbClients(cfg, clientCreator, subscribe, sentinelCreateCb) +func completeConfig(cfg *Config) { + if len(cfg.sentinelPorts) == 0 { + if len(cfg.clusterAddrs) > len(cfg.ports) && len(cfg.ports) > 0 { + for i := len(cfg.ports); i < len(cfg.clusterAddrs); i++ { + cfg.ports = append(cfg.ports, cfg.ports[i-1]) + } + } + } else { + if len(cfg.clusterAddrs) > len(cfg.sentinelPorts) { + for i := len(cfg.sentinelPorts); i < len(cfg.clusterAddrs); i++ { + cfg.sentinelPorts = append(cfg.sentinelPorts, cfg.sentinelPorts[i-1]) + } + } + if len(cfg.clusterAddrs) > len(cfg.masterNames) && len(cfg.masterNames) > 0 { + for i := len(cfg.masterNames); i < len(cfg.clusterAddrs); i++ { + cfg.masterNames = append(cfg.masterNames, cfg.masterNames[i-1]) + } + } + } } -func createDbClients(cfg Config, clientCreator RedisClientCreator, +func ReadConfigAndCreateDbClients(osI OS, clientCreator RedisClientCreator, subscribe SubscribeFn, sentinelCreateCb RedisSentinelCreateCb) []*DB { - if cfg.clusterAddrList == "" { - return []*DB{createLegacyDbClient(cfg, clientCreator, subscribe, sentinelCreateCb)} - } - dbs := []*DB{} - - addrList := strings.Split(cfg.clusterAddrList, ",") - for _, addr := range addrList { - db := createDbClient(cfg, addr, clientCreator, subscribe, sentinelCreateCb) + cfg := readConfig(osI) + for i, addr := range cfg.clusterAddrs { + port := getListItem(cfg.ports, i) + sntPort := getListItem(cfg.sentinelPorts, i) + name := getListItem(cfg.masterNames, i) + db := createDbClient(addr, port, sntPort, name, cfg.nodeCnt, + clientCreator, subscribe, sentinelCreateCb) dbs = append(dbs, db) } return dbs } -func createLegacyDbClient(cfg Config, clientCreator RedisClientCreator, - subscribe SubscribeFn, - sentinelCreateCb RedisSentinelCreateCb) *DB { - return createDbClient(cfg, cfg.hostname, clientCreator, subscribe, sentinelCreateCb) +func getListItem(list []string, index int) string { + if index < len(list) { + return list[index] + } + return "" } -func createDbClient(cfg Config, hostName string, clientCreator RedisClientCreator, +func createDbClient(addr, port, sentinelPort, masterName, nodeCnt string, clientCreator RedisClientCreator, subscribe SubscribeFn, sentinelCreateCb RedisSentinelCreateCb) *DB { var client RedisClient var db *DB - if cfg.sentinelPort == "" { - client = clientCreator(hostName, cfg.port, "", false) - db = CreateDB(client, subscribe, nil, cfg, hostName) + if sentinelPort == "" { + client = clientCreator(addr, port, "", false) + db = CreateDB(client, subscribe, nil, addr, port, sentinelPort, masterName, nodeCnt) } else { - client = clientCreator(hostName, cfg.sentinelPort, cfg.masterName, true) - db = CreateDB(client, subscribe, sentinelCreateCb, cfg, hostName) + client = clientCreator(addr, sentinelPort, masterName, true) + db = CreateDB(client, subscribe, sentinelCreateCb, addr, port, sentinelPort, masterName, nodeCnt) } db.CheckCommands() return db @@ -765,14 +796,14 @@ func readRedisInfoReplyFields(input []string, info *DbInfo) { func (db *DB) State() (*DbState, error) { dbState := new(DbState) - if db.cfg.sentinelPort != "" { + if db.sentinelPort != "" { //Establish connection to Redis sentinel. The reason why connection is done //here instead of time of the SDL instance creation is that for the time being //sentinel connection is needed only here to get state information and //state information is needed only by 'sdlcli' hence it is not time critical //and also we want to avoid opening unnecessary TCP connections towards Redis //sentinel for every SDL instance. Now it is done only when 'sdlcli' is used. - sentinelClient := db.sentinel(&db.cfg, db.addr) + sentinelClient := db.sentinel(db.addr, db.sentinelPort, db.masterName, db.nodeCnt) return sentinelClient.GetDbState() } else { info, err := db.Info() @@ -791,17 +822,17 @@ func (db *DB) fillDbStateFromDbInfo(info *DbInfo) (*DbState, error) { PrimaryDbState: PrimaryDbState{ Fields: PrimaryDbStateFields{ Role: "master", - Ip: db.cfg.hostname, - Port: db.cfg.port, + Ip: db.addr, + Port: db.port, Flags: "master", }, }, } } - cnt, err := strconv.Atoi(db.cfg.nodeCnt) + cnt, err := strconv.Atoi(db.nodeCnt) if err != nil { - dbState.Err = fmt.Errorf("DBAAS_NODE_COUNT configuration value '%s' conversion to integer failed", db.cfg.nodeCnt) + dbState.Err = fmt.Errorf("DBAAS_NODE_COUNT configuration value '%s' conversion to integer failed", db.nodeCnt) } else { dbState.ConfigNodeCnt = cnt } @@ -810,10 +841,8 @@ func (db *DB) fillDbStateFromDbInfo(info *DbInfo) (*DbState, error) { } func createReplicaDbClient(host string) *DB { - cfg := readConfig(osImpl{}) - cfg.sentinelPort = "" - cfg.clusterAddrList, cfg.port, _ = net.SplitHostPort(host) - return createDbClient(cfg, cfg.clusterAddrList, newRedisClient, subscribeNotifications, nil) + addr, port, _ := net.SplitHostPort(host) + return createDbClient(addr, port, "", "", "", newRedisClient, subscribeNotifications, nil) } func getStatisticsInfo(db *DB, host string) (*DbStatisticsInfo, error) { @@ -861,14 +890,14 @@ func sentinelStatistics(db *DB) (*DbStatistics, error) { func standaloneStatistics(db *DB) (*DbStatistics, error) { dbStatistics := new(DbStatistics) - dbStatisticsInfo, err := getStatisticsInfo(db, net.JoinHostPort(db.cfg.hostname, db.cfg.port)) + dbStatisticsInfo, err := getStatisticsInfo(db, net.JoinHostPort(db.addr, db.port)) dbStatistics.Stats = append(dbStatistics.Stats, dbStatisticsInfo) return dbStatistics, err } func (db *DB) Statistics() (*DbStatistics, error) { - if db.cfg.sentinelPort != "" { + if db.sentinelPort != "" { return sentinelStatistics(db) } diff --git a/internal/sdlgoredis/sdlgoredis_test.go b/internal/sdlgoredis/sdlgoredis_test.go index c95b8af..106ba6c 100644 --- a/internal/sdlgoredis/sdlgoredis_test.go +++ b/internal/sdlgoredis/sdlgoredis_test.go @@ -1,6 +1,6 @@ /* Copyright (c) 2019 AT&T Intellectual Property. - Copyright (c) 2018-2019 Nokia. + Copyright (c) 2018-2022 Nokia. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -189,9 +189,9 @@ func setupHaEnvWithSentinels(commandsExists bool, nodeCnt string) (*pubSubMock, setupVals := setupEnv( commandsExists, "service-ricplt-dbaas-tcp-cluster-0.ricplt", - "6376", - "dbaasmaster", - "26376", + "6379", + "dbaasmaster-cluster-0", + "26379", "", nodeCnt, ) @@ -202,7 +202,7 @@ func setupSingleEnv(commandsExists bool, nodeCnt string) (*pubSubMock, *clientMo setupVals := setupEnv( commandsExists, "service-ricplt-dbaas-tcp-cluster-0.ricplt", - "6376", "", "", "", nodeCnt, + "6379", "", "", "", nodeCnt, ) return setupVals.pubSubMock[0], setupVals.rClient[0], setupVals.db[0] } @@ -251,10 +251,11 @@ func setupEnv(commandsExists bool, host, port, msname, sntport, clsaddrlist, nod return clm }, subscribeNotifications, - func(cfg *sdlgoredis.Config, addr string) *sdlgoredis.Sentinel { + func(addr, sentinelPort, masterName, nodeCnt string) *sdlgoredis.Sentinel { s := &sdlgoredis.Sentinel{ IredisSentinelClient: smock, - Cfg: cfg, + MasterName: masterName, + NodeCnt: nodeCnt, } return s }, @@ -1139,7 +1140,7 @@ func TestPExpireIELockNotHeld(t *testing.T) { func TestClientStandaloneRedisLegacyEnv(t *testing.T) { setupVals := setupEnv( true, - "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "", "", "", "", + "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "", "", "", "", ) assert.Equal(t, 1, len(setupVals.rClient)) assert.Equal(t, 1, len(setupVals.db)) @@ -1154,7 +1155,7 @@ func TestClientStandaloneRedisLegacyEnv(t *testing.T) { func TestClientSentinelRedisLegacyEnv(t *testing.T) { setupVals := setupEnv( true, - "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "dbaasmaster", "26376", "", "3", + "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "dbaasmaster-cluster-0", "26379", "", "3", ) assert.Equal(t, 1, len(setupVals.rClient)) assert.Equal(t, 1, len(setupVals.db)) @@ -1169,7 +1170,7 @@ func TestClientSentinelRedisLegacyEnv(t *testing.T) { func TestClientTwoStandaloneRedisEnvs(t *testing.T) { setupVals := setupEnv( true, - "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "", "", + "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "", "", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "", ) assert.Equal(t, 2, len(setupVals.rClient)) @@ -1192,8 +1193,8 @@ func TestClientTwoStandaloneRedisEnvs(t *testing.T) { func TestClientTwoSentinelRedisEnvs(t *testing.T) { setupVals := setupEnv( true, - "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6376", "dbaasmaster", "26376", - "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3", + "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1", + "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3", ) assert.Equal(t, 2, len(setupVals.rClient)) assert.Equal(t, 2, len(setupVals.db)) @@ -1212,6 +1213,36 @@ func TestClientTwoSentinelRedisEnvs(t *testing.T) { setupVals.rClient[1].AssertExpectations(t) } +func TestCompleteConfigIfLessPortsThanAddresses(t *testing.T) { + setupVals := setupEnv( + true, + "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379", "dbaasmaster-cluster-0,dbaasmaster-cluster-1", + "", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3", + ) + assert.Equal(t, 2, len(setupVals.rClient)) + assert.Equal(t, 2, len(setupVals.db)) +} + +func TestCompleteConfigIfLessSentinelPortsThanAddresses(t *testing.T) { + setupVals := setupEnv( + true, + "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1", + "26379", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3", + ) + assert.Equal(t, 2, len(setupVals.rClient)) + assert.Equal(t, 2, len(setupVals.db)) +} + +func TestCompleteConfigIfLessSentinelNamesThanAddresses(t *testing.T) { + setupVals := setupEnv( + true, + "service-ricplt-dbaas-tcp-cluster-0.ricplt", "6379,6380", "dbaasmaster-cluster-0", + "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3", + ) + assert.Equal(t, 2, len(setupVals.rClient)) + assert.Equal(t, 2, len(setupVals.db)) +} + func TestInfoOfPrimaryRedisWithTwoReplicasSuccessfully(t *testing.T) { _, r, db := setupHaEnv(true) redisInfo := "# Replication\r\n" + @@ -1407,15 +1438,73 @@ func TestStateWithPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) { expState.addSentinel("10.20.30.40", "26379", "sentinel", nil) expState.addSentinel("10.20.30.50", "30001", "sentinel", nil) - s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) - s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) - s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) + s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) + s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) + s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) ret, err := db.State() assert.Nil(t, err) assert.Equal(t, expState.s, *ret) r.AssertExpectations(t) } +func TestStateWithTwoSdlClustersContainingPrimaryAndTwoReplicaRedisSuccessfully(t *testing.T) { + setupVals := setupEnv( + true, + "", "6379,6380", "dbaasmaster-cluster-0,dbaasmaster-cluster-1", + "26379,26380", "service-ricplt-dbaas-tcp-cluster-0.ricplt,service-ricplt-dbaas-tcp-cluster-1.ricplt", "3", + ) + r := setupVals.rClient + s := setupVals.rSentinel + db := setupVals.db + + FstRedisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.30", "6379", "master") + FstRedisReplicasState := newMockRedisSlavesCall() + FstRedisReplicasState.add("slave", "10.20.30.40", "6379", "up", "slave") + FstRedisReplicasState.add("slave", "10.20.30.50", "6379", "up", "slave") + FstRedisSentinelsState := newMockRedisSentinelsCall() + FstRedisSentinelsState.add("10.20.30.40", "26379", "sentinel") + FstRedisSentinelsState.add("10.20.30.50", "26379", "sentinel") + + SndRedisPrimaryState := newMockRedisMasterCallResp("master", "10.20.30.60", "6380", "master") + SndRedisReplicasState := newMockRedisSlavesCall() + SndRedisReplicasState.add("slave", "10.20.30.70", "6380", "up", "slave") + SndRedisReplicasState.add("slave", "10.20.30.80", "6380", "up", "slave") + SndRedisSentinelsState := newMockRedisSentinelsCall() + SndRedisSentinelsState.add("10.20.30.70", "26380", "sentinel") + SndRedisSentinelsState.add("10.20.30.80", "26380", "sentinel") + + FstExpState := newExpDbState(3, nil) + FstExpState.addPrimary("master", "10.20.30.30", "6379", "master", nil) + FstExpState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil) + FstExpState.addReplica("slave", "10.20.30.50", "6379", "up", "slave", nil) + FstExpState.addSentinel("10.20.30.40", "26379", "sentinel", nil) + FstExpState.addSentinel("10.20.30.50", "26379", "sentinel", nil) + + SndExpState := newExpDbState(3, nil) + SndExpState.addPrimary("master", "10.20.30.60", "6380", "master", nil) + SndExpState.addReplica("slave", "10.20.30.70", "6380", "up", "slave", nil) + SndExpState.addReplica("slave", "10.20.30.80", "6380", "up", "slave", nil) + SndExpState.addSentinel("10.20.30.70", "26380", "sentinel", nil) + SndExpState.addSentinel("10.20.30.80", "26380", "sentinel", nil) + + s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(FstRedisPrimaryState, nil)) + s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(FstRedisReplicasState.resp, nil)) + s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(FstRedisSentinelsState.resp, nil)) + + s[0].On("Master", "dbaasmaster-cluster-1").Return(redis.NewStringStringMapResult(SndRedisPrimaryState, nil)) + s[0].On("Slaves", "dbaasmaster-cluster-1").Return(redis.NewSliceResult(SndRedisReplicasState.resp, nil)) + s[0].On("Sentinels", "dbaasmaster-cluster-1").Return(redis.NewSliceResult(SndRedisSentinelsState.resp, nil)) + + ret, err := db[0].State() + assert.Nil(t, err) + assert.Equal(t, FstExpState.s, *ret) + + ret, err = db[1].State() + assert.Nil(t, err) + assert.Equal(t, SndExpState.s, *ret) + r[0].AssertExpectations(t) +} + func TestStateWithPrimaryAndTwoReplicaRedisFailureInPrimaryRedisCall(t *testing.T) { expErr := errors.New("Some error") _, r, s, db := setupHaEnvWithSentinels(true, "3") @@ -1435,9 +1524,9 @@ func TestStateWithPrimaryAndTwoReplicaRedisFailureInPrimaryRedisCall(t *testing. expState.addSentinel("10.20.30.40", "26379", "sentinel", nil) expState.addSentinel("10.20.30.50", "30001", "sentinel", nil) - s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, expErr)) - s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) - s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) + s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, expErr)) + s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) + s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) ret, err := db.State() assert.NotNil(t, err) assert.Equal(t, expState.s, *ret) @@ -1463,9 +1552,9 @@ func TestStateWithPrimaryAndTwoReplicaRedisFailureInReplicasRedisCall(t *testing expState.addSentinel("10.20.30.40", "26379", "sentinel", nil) expState.addSentinel("10.20.30.50", "30001", "sentinel", nil) - s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) - s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, errors.New("Some error"))) - s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) + s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) + s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, errors.New("Some error"))) + s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) ret, err := db.State() assert.NotNil(t, err) assert.Equal(t, expState.s, *ret) @@ -1487,9 +1576,9 @@ func TestStateWithPrimaryAndOneReplicaRedisFailureInSentinelsRedisCall(t *testin expState.addReplica("slave", "10.20.30.40", "6379", "up", "slave", nil) expState.addSentinel("", "", "", expErr) - s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) - s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) - s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, expErr)) + s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) + s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) + s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, expErr)) ret, err := db.State() assert.NotNil(t, err) assert.Equal(t, expState.s, *ret) @@ -1515,9 +1604,9 @@ func TestStateWithPrimaryAndTwoReplicaRedisFailureWhenIntConversionFails(t *test expState.addSentinel("10.20.30.40", "26379", "sentinel", nil) expState.addSentinel("10.20.30.50", "30001", "sentinel", nil) - s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) - s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) - s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) + s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) + s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) + s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) ret, err := db.State() assert.Equal(t, expErr, err) assert.Equal(t, expState.s, *ret) @@ -1543,9 +1632,9 @@ func TestStateWithPrimaryAndTwoReplicaFirstSentinelStateIgnoredBecauseZeroPortBu expState.addReplica("slave", "10.20.30.50", "30000", "up", "slave", nil) expState.addSentinel("10.20.30.50", "26379", "sentinel", nil) - s[0].On("Master", "dbaasmaster").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) - s[0].On("Slaves", "dbaasmaster").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) - s[0].On("Sentinels", "dbaasmaster").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) + s[0].On("Master", "dbaasmaster-cluster-0").Return(redis.NewStringStringMapResult(redisPrimaryState, nil)) + s[0].On("Slaves", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisReplicasState.resp, nil)) + s[0].On("Sentinels", "dbaasmaster-cluster-0").Return(redis.NewSliceResult(redisSentinelsState.resp, nil)) ret, err := db.State() assert.Nil(t, err) assert.Equal(t, expState.s, *ret) @@ -1565,7 +1654,7 @@ func TestStateWithSinglePrimaryRedisSuccessfully(t *testing.T) { Fields: sdlgoredis.PrimaryDbStateFields{ Role: "master", Ip: "service-ricplt-dbaas-tcp-cluster-0.ricplt", - Port: "6376", + Port: "6379", Flags: "master", }, }, @@ -1593,7 +1682,7 @@ func TestStateWithSinglePrimaryRedisFailureWhenIntConversionFails(t *testing.T) Fields: sdlgoredis.PrimaryDbStateFields{ Role: "master", Ip: "service-ricplt-dbaas-tcp-cluster-0.ricplt", - Port: "6376", + Port: "6379", Flags: "master", }, }, @@ -1636,7 +1725,7 @@ func TestStatisticsWithSinglePrimaryRedisSuccessfully(t *testing.T) { Stats: []*sdlgoredis.DbStatisticsInfo{ { IPAddr: "service-ricplt-dbaas-tcp-cluster-0.ricplt", - Port: "6376", + Port: "6379", Info: &sdlgoredis.DbInfo{ Fields: sdlgoredis.DbInfoFields{ PrimaryRole: true, diff --git a/internal/sdlgoredis/sdlgosentinel.go b/internal/sdlgoredis/sdlgosentinel.go index 8a1b331..a06722b 100644 --- a/internal/sdlgoredis/sdlgosentinel.go +++ b/internal/sdlgoredis/sdlgosentinel.go @@ -1,6 +1,6 @@ /* Copyright (c) 2021 AT&T Intellectual Property. - Copyright (c) 2018-2021 Nokia. + Copyright (c) 2018-2022 Nokia. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,9 +30,10 @@ import ( ) type Sentinel struct { - ctx context.Context + ctx context.Context + MasterName string + NodeCnt string IredisSentinelClient - Cfg *Config } type IredisSentinelClient interface { @@ -41,10 +42,10 @@ type IredisSentinelClient interface { Sentinels(ctx context.Context, name string) *redis.SliceCmd } -type RedisSentinelCreateCb func(cfg *Config, addr string) *Sentinel +type RedisSentinelCreateCb func(addr, sentinelPort, masterName, nodeCnt string) *Sentinel -func newRedisSentinel(cfg *Config, addr string) *Sentinel { - redisAddress := addr + ":" + cfg.sentinelPort +func newRedisSentinel(addr, sentinelPort, masterName, nodeCnt string) *Sentinel { + redisAddress := addr + ":" + sentinelPort return &Sentinel{ ctx: context.Background(), IredisSentinelClient: redis.NewSentinelClient(&redis.Options{ @@ -54,7 +55,8 @@ func newRedisSentinel(cfg *Config, addr string) *Sentinel { PoolSize: 20, MaxRetries: 2, }), - Cfg: cfg, + MasterName: masterName, + NodeCnt: nodeCnt, } } @@ -67,9 +69,9 @@ func (s *Sentinel) GetDbState() (*DbState, error) { state.ReplicasDbState = rState state.SentinelsDbState = sState - cnt, err := strconv.Atoi(s.Cfg.nodeCnt) + cnt, err := strconv.Atoi(s.NodeCnt) if err != nil { - state.Err = fmt.Errorf("Sentinel DBAAS_NODE_COUNT configuration value '%s' conversion to integer failed", s.Cfg.nodeCnt) + state.Err = fmt.Errorf("Sentinel DBAAS_NODE_COUNT configuration value '%s' conversion to integer failed", s.NodeCnt) return state, state.Err } state.ConfigNodeCnt = cnt @@ -85,7 +87,7 @@ func (s *Sentinel) GetDbState() (*DbState, error) { func (s *Sentinel) getPrimaryDbState() (*PrimaryDbState, error) { state := new(PrimaryDbState) - redisVal, redisErr := s.Master(s.ctx, s.Cfg.masterName).Result() + redisVal, redisErr := s.Master(s.ctx, s.MasterName).Result() if redisErr == nil { state.Fields.Ip = redisVal["ip"] state.Fields.Port = redisVal["port"] @@ -100,7 +102,7 @@ func (s *Sentinel) getReplicasState() (*ReplicasDbState, error) { states := new(ReplicasDbState) states.States = make([]*ReplicaDbState, 0) - redisVal, redisErr := s.Slaves(s.ctx, s.Cfg.masterName).Result() + redisVal, redisErr := s.Slaves(s.ctx, s.MasterName).Result() if redisErr == nil { for _, redisReplica := range redisVal { replicaState := readReplicaState(redisReplica.([]interface{})) @@ -133,7 +135,7 @@ func (s *Sentinel) getSentinelsState() (*SentinelsDbState, error) { states := new(SentinelsDbState) states.States = make([]*SentinelDbState, 0) - redisVal, redisErr := s.Sentinels(s.ctx, s.Cfg.masterName).Result() + redisVal, redisErr := s.Sentinels(s.ctx, s.MasterName).Result() if redisErr == nil { for _, redisSentinel := range redisVal { sentinelState := readSentinelState(redisSentinel.([]interface{})) -- 2.16.6