Skip to content

Commit

Permalink
refine tidb_cluster_control codes (#215)
Browse files Browse the repository at this point in the history
* ennhance code readability
  • Loading branch information
weekface authored Dec 18, 2018
1 parent 1920c35 commit 19a76e1
Show file tree
Hide file tree
Showing 10 changed files with 356 additions and 235 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea // indirect
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/dnephin/govet v0.0.0-20171012192244-4a96d43e39d3 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect
github.com/emicklei/go-restful v2.8.0+incompatible
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dnephin/govet v0.0.0-20171012192244-4a96d43e39d3/go.mod h1:pPTX0MEEoAnfbrAGFj4nSVNhl6YbugRj6eardUZdtGo=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=
Expand Down
48 changes: 48 additions & 0 deletions pkg/apis/pingcap.com/v1alpha1/tidbcluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,51 @@ func (tc *TidbCluster) TiDBAllMembersReady() bool {
func (tc *TidbCluster) TiDBRealReplicas() int32 {
return tc.Spec.TiDB.Replicas + int32(len(tc.Status.TiDB.FailureMembers))
}

func (tc *TidbCluster) PDIsAvailable() bool {
lowerLimit := tc.Spec.PD.Replicas/2 + 1
if int32(len(tc.Status.PD.Members)) < lowerLimit {
return false
}

var availableNum int32
for _, pdMember := range tc.Status.PD.Members {
if pdMember.Health {
availableNum++
}
}

if availableNum < lowerLimit {
return false
}

if tc.Status.PD.StatefulSet == nil || tc.Status.PD.StatefulSet.ReadyReplicas < lowerLimit {
return false
}

return true
}

func (tc *TidbCluster) TiKVIsAvailable() bool {
var lowerLimit int32 = 1
if int32(len(tc.Status.TiKV.Stores)) < lowerLimit {
return false
}

var availableNum int32
for _, store := range tc.Status.TiKV.Stores {
if store.State == TiKVStateUp {
availableNum++
}
}

if availableNum < lowerLimit {
return false
}

if tc.Status.TiKV.StatefulSet == nil || tc.Status.TiKV.StatefulSet.ReadyReplicas < lowerLimit {
return false
}

return true
}
190 changes: 190 additions & 0 deletions pkg/apis/pingcap.com/v1alpha1/tidbcluster_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// Copyright 2018 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package v1alpha1

import (
"testing"

. "github.com/onsi/gomega"
apps "k8s.io/api/apps/v1beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)

func TestPDIsAvailable(t *testing.T) {
g := NewGomegaWithT(t)

type testcase struct {
name string
update func(*TidbCluster)
expectFn func(*GomegaWithT, bool)
}
testFn := func(test *testcase, t *testing.T) {
t.Log(test.name)

tc := newTidbCluster()
test.update(tc)
test.expectFn(g, tc.PDIsAvailable())
}
tests := []testcase{
{
name: "pd members count is 1",
update: func(tc *TidbCluster) {
tc.Status.PD.Members = map[string]PDMember{
"pd-0": {Name: "pd-0", Health: true},
}
},
expectFn: func(g *GomegaWithT, b bool) {
g.Expect(b).To(BeFalse())
},
},
{
name: "pd members count is 2, but health count is 1",
update: func(tc *TidbCluster) {
tc.Status.PD.Members = map[string]PDMember{
"pd-0": {Name: "pd-0", Health: true},
"pd-1": {Name: "pd-1", Health: false},
}
},
expectFn: func(g *GomegaWithT, b bool) {
g.Expect(b).To(BeFalse())
},
},
{
name: "pd members count is 3, health count is 3, but ready replicas is 1",
update: func(tc *TidbCluster) {
tc.Status.PD.Members = map[string]PDMember{
"pd-0": {Name: "pd-0", Health: true},
"pd-1": {Name: "pd-1", Health: true},
"pd-2": {Name: "pd-2", Health: true},
}
tc.Status.PD.StatefulSet = &apps.StatefulSetStatus{ReadyReplicas: 1}
},
expectFn: func(g *GomegaWithT, b bool) {
g.Expect(b).To(BeFalse())
},
},
{
name: "pd is available",
update: func(tc *TidbCluster) {
tc.Status.PD.Members = map[string]PDMember{
"pd-0": {Name: "pd-0", Health: true},
"pd-1": {Name: "pd-1", Health: true},
"pd-2": {Name: "pd-2", Health: true},
}
tc.Status.PD.StatefulSet = &apps.StatefulSetStatus{ReadyReplicas: 3}
},
expectFn: func(g *GomegaWithT, b bool) {
g.Expect(b).To(BeTrue())
},
},
}

for i := range tests {
testFn(&tests[i], t)
}
}

func TestTiKVIsAvailable(t *testing.T) {
g := NewGomegaWithT(t)

type testcase struct {
name string
update func(*TidbCluster)
expectFn func(*GomegaWithT, bool)
}
testFn := func(test *testcase, t *testing.T) {
t.Log(test.name)

tc := newTidbCluster()
test.update(tc)
test.expectFn(g, tc.TiKVIsAvailable())
}
tests := []testcase{
{
name: "tikv stores count is 0",
update: func(tc *TidbCluster) {
tc.Status.TiKV.Stores = map[string]TiKVStore{}
},
expectFn: func(g *GomegaWithT, b bool) {
g.Expect(b).To(BeFalse())
},
},
{
name: "tikv stores count is 1, but available count is 0",
update: func(tc *TidbCluster) {
tc.Status.TiKV.Stores = map[string]TiKVStore{
"tikv-0": {PodName: "tikv-0", State: TiKVStateDown},
}
},
expectFn: func(g *GomegaWithT, b bool) {
g.Expect(b).To(BeFalse())
},
},
{
name: "tikv stores count is 1, available count is 1, ready replicas is 0",
update: func(tc *TidbCluster) {
tc.Status.TiKV.Stores = map[string]TiKVStore{
"tikv-0": {PodName: "tikv-0", State: TiKVStateUp},
}
tc.Status.TiKV.StatefulSet = &apps.StatefulSetStatus{ReadyReplicas: 0}
},
expectFn: func(g *GomegaWithT, b bool) {
g.Expect(b).To(BeFalse())
},
},
{
name: "tikv is available",
update: func(tc *TidbCluster) {
tc.Status.TiKV.Stores = map[string]TiKVStore{
"tikv-0": {PodName: "tikv-0", State: TiKVStateUp},
}
tc.Status.TiKV.StatefulSet = &apps.StatefulSetStatus{ReadyReplicas: 1}
},
expectFn: func(g *GomegaWithT, b bool) {
g.Expect(b).To(BeTrue())
},
},
}

for i := range tests {
testFn(&tests[i], t)
}
}

func newTidbCluster() *TidbCluster {
return &TidbCluster{
TypeMeta: metav1.TypeMeta{
Kind: "TidbCluster",
APIVersion: "pingcap.com/v1alpha1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-pd",
Namespace: corev1.NamespaceDefault,
UID: types.UID("test"),
},
Spec: TidbClusterSpec{
PD: PDSpec{
Replicas: 3,
},
TiKV: TiKVSpec{
Replicas: 3,
},
TiDB: TiDBSpec{
Replicas: 1,
},
},
}
}
Loading

0 comments on commit 19a76e1

Please sign in to comment.