Skip to content

Commit

Permalink
add cluster node list judge, only accpet role master. see #149
Browse files Browse the repository at this point in the history
  • Loading branch information
vinllen committed Nov 8, 2019
1 parent 4ba0eca commit 70387d4
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 14 deletions.
25 changes: 25 additions & 0 deletions src/redis-shake/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,29 @@ func CompareVersion(a, b string, level int) int {
}

return 0
}

// compare two unordered list. return true means equal.
func CompareUnorderedList(a, b []string) bool {
if len(a) != len(b) {
return false
}

if len(a) == 0 {
return true
}

setA := map[string]struct{}{}

for _, x := range a {
setA[x] = struct{}{}
}

for _, x := range b {
if _, ok := setA[x]; !ok {
return false
}
}

return true
}
49 changes: 35 additions & 14 deletions src/redis-shake/common/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,38 +96,39 @@ func parseAddress(tp, address, redisType string, isSource bool) error {
}
}
case conf.RedisTypeCluster:
//if isSource == false && tp == conf.TypeRump {
// return fmt.Errorf("target type[%v] can't be cluster when type is 'rump' currently", redisType)
//}
// get auth type and password
var auth, password string
if isSource {
auth, password = conf.Options.SourceAuthType, conf.Options.SourcePasswordRaw
} else {
auth, password = conf.Options.TargetAuthType, conf.Options.TargetPasswordRaw
}
tls := isSource && conf.Options.SourceTLSEnable || !isSource && conf.Options.TargetTLSEnable

if strings.Contains(address, AddressSplitter) {
arr := strings.Split(address, AddressSplitter)
if len(arr) != 2 {
return fmt.Errorf("redis type[%v] address[%v] length[%v] != 2", redisType, address, len(arr))
}

if arr[0] == conf.StandAloneRoleSlave {
return fmt.Errorf("redis role should be master")
}
if isSource && arr[0] != conf.StandAloneRoleSlave && arr[0] != conf.StandAloneRoleMaster {
return fmt.Errorf("source redis role must be master or slave, when enable automatic discovery with '@'")
}
if !isSource && arr[0] != "master" && arr[0] != "" {
if !isSource && arr[0] != conf.StandAloneRoleMaster && arr[0] != "" {
return fmt.Errorf("target redis role must be master, when enable automatic discovery with '@'")
}

clusterList := strings.Split(arr[1], AddressClusterSplitter)

// get auth type and password
var auth, password string
if isSource {
auth, password = conf.Options.SourceAuthType, conf.Options.SourcePasswordRaw
} else {
auth, password = conf.Options.TargetAuthType, conf.Options.TargetPasswordRaw
}

role := arr[0]
if role == "" {
role = conf.StandAloneRoleAll
role = conf.StandAloneRoleMaster
}

// create client to fetch
tls := isSource && conf.Options.SourceTLSEnable || !isSource && conf.Options.TargetTLSEnable
client := OpenRedisConn(clusterList, auth, password, false, tls)
if addressList, err := GetAllClusterNode(client, role, "address"); err != nil {
return err
Expand All @@ -139,8 +140,28 @@ func parseAddress(tp, address, redisType string, isSource bool) error {
}
}
} else {
// check source list legality: all master or all slave
addressList := strings.Split(address, AddressClusterSplitter)
client := OpenRedisConn(addressList, auth, password, false, tls)

// fetch master address and slave address, ignore error
masterAddressList, _ := GetAllClusterNode(client, conf.StandAloneRoleMaster, "address")
slaveAddressList, _ := GetAllClusterNode(client, conf.StandAloneRoleSlave, "address")
if masterAddressList != nil && slaveAddressList != nil {
if !CompareUnorderedList(masterAddressList, addressList) && !CompareUnorderedList(slaveAddressList, addressList) {
endpoint := "source"
if !isSource {
endpoint = "target"
}
return fmt.Errorf("[%s] redis address should be all masters or all slaves, master:[%v], slave[%v]",
endpoint, masterAddressList, slaveAddressList)
}
}

// set address
setAddressList(isSource, address)
}

case conf.RedisTypeProxy:
if isSource && addressLen != 1 {
return fmt.Errorf("address[%v] length[%v] must == 1 when type is 'proxy'", address, addressLen)
Expand Down
24 changes: 24 additions & 0 deletions src/redis-shake/common/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,28 @@ func TestCompareVersion(t *testing.T) {
assert.Equal(t, 0, CompareVersion("1.4.x", "1.4", 0), "should be equal")
assert.Equal(t, 2, CompareVersion("2.4", "1.1", 2), "should be equal")
}
}


func TestCompareUnorderedList(t *testing.T) {
var nr int
{
fmt.Printf("TestCompareUnorderedList case %d.\n", nr)
nr++

var a, b []string
assert.Equal(t, true, CompareUnorderedList(a, b), "should be equal")

a = []string{"1", "2", "3"}
b = []string{"1", "2"}
assert.Equal(t, false, CompareUnorderedList(a, b), "should be equal")

a = []string{"1", "2", "3"}
b = []string{"3", "1", "2"}
assert.Equal(t, true, CompareUnorderedList(a, b), "should be equal")

a = []string{"1", "2", "3"}
b = []string{"4", "1", "2"}
assert.Equal(t, false, CompareUnorderedList(a, b), "should be equal")
}
}

0 comments on commit 70387d4

Please sign in to comment.