Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: ignore slave whose slave-priority = 0 #8

Merged
merged 8 commits into from
Dec 17, 2019
7 changes: 6 additions & 1 deletion pkg/apis/redis/v1beta1/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const (
defaultRedisNumber = 3
defaultSentinelNumber = 3
defaultRedisImage = "redis:5.0.4-alpine"

defaultSlavePriority = "1"
)

var (
Expand All @@ -29,7 +31,7 @@ func (r *RedisCluster) Validate() error {
if r.Spec.Size == 0 {
r.Spec.Size = defaultRedisNumber
} else if r.Spec.Size < defaultRedisNumber {
return errors.New("number of redises in spec is less than the minimum")
return errors.New("number of redis in spec is less than the minimum")
}

if r.Spec.Sentinel.Replicas == 0 {
Expand All @@ -54,6 +56,9 @@ func (r *RedisCluster) Validate() error {
r.Spec.Config = make(map[string]string)
}

// https://github.com/ucloud/redis-operator/issues/6
r.Spec.Config["slave-priority"] = defaultSlavePriority

if !r.Spec.DisablePersistence {
enablePersistence(r.Spec.Config)
} else {
Expand Down
35 changes: 28 additions & 7 deletions pkg/client/redis/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,41 @@ func (c *client) GetNumberSentinelSlavesInMemory(ip string, auth *util.AuthConfi
return 0, err
}

if err2 := isSentinelReady(info); err2 != nil {
return 0, err2
}
match := slaveNumberRE.FindStringSubmatch(info)
if len(match) == 0 {
return 0, errors.New("slaves regex not found")
if err = isSentinelReady(info); err != nil {
return 0, err
}
nSlaves, err := strconv.Atoi(match[1])

cmd := rediscli.NewSliceCmd("sentinel", "slaves", masterName)
rClient.Process(cmd)
slaveInfoBlobs, err := cmd.Result()
if err != nil {
return 0, err
}
nSlaves := len(slaveInfoBlobs)
for _, slaveInfoBlob := range slaveInfoBlobs {
slavePriority := slaveInfoFieldByName("slave-priority", slaveInfoBlob)
if slavePriority == "0" {
nSlaves -= 1
}
}

return int32(nSlaves), nil
}

func slaveInfoFieldByName(name string, slaveInfoBlob interface{}) string {
slaveInfo := slaveInfoBlob.([]interface{})
infoLens := len(slaveInfo)
i := 0
for i+1 < infoLens {
stringValue := slaveInfo[i].(string)
if stringValue == name {
return slaveInfo[i+1].(string)
}
i += 2
}
return ""
}

func isSentinelReady(info string) error {
matchStatus := sentinelStatusRE.FindStringSubmatch(info)
if len(matchStatus) == 0 || matchStatus[1] != "ok" {
Expand Down
64 changes: 60 additions & 4 deletions pkg/client/redis/client_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package redis_test
package redis

import (
rediscli "github.com/go-redis/redis"
"github.com/ucloud/redis-operator/pkg/client/redis"
"strings"
"testing"

rediscli "github.com/go-redis/redis"
)

func newClient() *rediscli.Client {
Expand All @@ -18,7 +18,7 @@ func newClient() *rediscli.Client {
func TestGetAllRedisConfig(t *testing.T) {
cli := newClient()
//var client redis.Client
client := redis.New()
client := New()
result, err := client.GetAllRedisConfig(cli)
if err != nil {
t.Fatal(err)
Expand All @@ -33,3 +33,59 @@ func TestGetAllRedisConfig(t *testing.T) {
}

}

func Test_slaveInfoFieldByName(t *testing.T) {
slaveInfoBlobA := []interface{}{"name", "[xxxxA]:6379", "ip", "xxxxA", "port", "6379", "runid", "6f792839ab551e8dbec58e0eb3b3838d14f19a37", "flags", "slave", "link-pending-commands", "1", "link-refcount", "1", "last-ping-sent", "0", "last-ok-ping-reply", "1055", "last-ping-reply", "1055", "down-after-milliseconds", "5000", "info-refresh", "2074", "role-reported", "slave", "role-reported-time", "2983115", "master-link-down-time", "0", "master-link-status", "ok", "master-host", "xxxxA", "master-port", "6379", "slave-priority", "1", "slave-repl-offset", "124614695"}
slaveInfoBlobB := []interface{}{"name", "[xxxxB]:6371", "ip", "xxxxB", "port", "6371", "runid", "fake_slave_8bb90711-8f37-44e8-b3b2-589af", "flags", "slave", "link-pending-commands", "1", "link-refcount", "1", "last-ping-sent", "0", "last-ok-ping-reply", "1055", "last-ping-reply", "1055", "down-after-milliseconds", "5000", "info-refresh", "2075", "role-reported", "slave", "role-reported-time", "2983114", "master-link-down-time", "0", "master-link-status", "ok", "master-host", "xxxxB", "master-port", "6379", "slave-priority", "0", "slave-repl-offset", "124614695"}
slaveInfoBlobC := []interface{}{"name", "[xxxxB]:6371", "ip", "slave-priority", "slave-priority", "100"}
slaveInfoBlobD := []interface{}{"name", "[xxxxB]:6371", "ip", "xxxxB", "slave-priority"}
type args struct {
name string
slaveInfoBlob interface{}
}
tests := []struct {
name string
args args
want string
}{
{
name: "slaveA",
args: args{
name: "slave-priority",
slaveInfoBlob: slaveInfoBlobA,
},
want: "1",
},
{
name: "slaveB",
args: args{
name: "slave-priority",
slaveInfoBlob: slaveInfoBlobB,
},
want: "0",
},
{
name: "slaveC",
args: args{
name: "slave-priority",
slaveInfoBlob: slaveInfoBlobC,
},
want: "100",
},
{
name: "slaveD",
args: args{
name: "slave-priority",
slaveInfoBlob: slaveInfoBlobD,
},
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := slaveInfoFieldByName(tt.args.name, tt.args.slaveInfoBlob); got != tt.want {
t.Errorf("slaveInfoFieldByName() = %v, want %v", got, tt.want)
}
})
}
}