Skip to content

Commit

Permalink
only check relevant tidb clusters
Browse files Browse the repository at this point in the history
  • Loading branch information
cofyc committed Mar 16, 2020
1 parent 4de6f7d commit fe29ffa
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 21 deletions.
46 changes: 26 additions & 20 deletions pkg/upgrader/upgrader.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"github.com/pingcap/tidb-operator/pkg/label"
utildiscovery "github.com/pingcap/tidb-operator/pkg/util/discovery"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/api/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes"
Expand Down Expand Up @@ -58,47 +58,53 @@ var _ Interface = &upgrader{}

// isOwnedByTidbCluster checks if the given object is owned by TidbCluster.
// Schema Kind and Group are checked, Version is ignored.
func isOwnedByTidbCluster(obj metav1.Object) bool {
func isOwnedByTidbCluster(obj metav1.Object) (bool, *metav1.OwnerReference) {
ref := metav1.GetControllerOf(obj)
if ref == nil {
return false
return false, nil
}
gv, err := schema.ParseGroupVersion(ref.APIVersion)
if err != nil {
return false
return false, nil
}
return ref.Kind == v1alpha1.TiDBClusterKind && gv.Group == v1alpha1.SchemeGroupVersion.Group
return ref.Kind == v1alpha1.TiDBClusterKind && gv.Group == v1alpha1.SchemeGroupVersion.Group, ref
}

func (u *upgrader) Upgrade() error {
if features.DefaultFeatureGate.Enabled(features.AdvancedStatefulSet) {
klog.Infof("Upgrader: migrating Kubernetes StatefulSets to Advanced StatefulSets")
tcList, err := u.cli.PingcapV1alpha1().TidbClusters(u.ns).List(metav1.ListOptions{})
if err != nil {
return err
}
for _, tc := range tcList.Items {
// Existing delete slots annotations must be removed first. This is
// a safety check to ensure no pods are affected in upgrading
// process.
if anns := deleteSlotAnns(&tc); len(anns) > 0 {
return fmt.Errorf("Upgrader: TidbCluster %s/%s has delete slot annotations %v, please remove them before enabling AdvancedStatefulSet feature", tc.Namespace, tc.Name, anns)
}
}
stsList, err := u.kubeCli.AppsV1().StatefulSets(u.ns).List(metav1.ListOptions{})
if err != nil {
return err
}
stsToMigrate := make([]appsv1.StatefulSet, 0)
tidbClusters := make([]*v1alpha1.TidbCluster, 0)
for _, sts := range stsList.Items {
if isOwnedByTidbCluster(&sts) {
if ok, tcRef := isOwnedByTidbCluster(&sts); ok {
stsToMigrate = append(stsToMigrate, sts)
tc, err := u.cli.PingcapV1alpha1().TidbClusters(sts.Namespace).Get(tcRef.Name, metav1.GetOptions{})
if err != nil && !apierrors.IsNotFound(err) {
return err
}
if tc != nil {
tidbClusters = append(tidbClusters, tc)
}
}
}
if len(stsToMigrate) <= 0 {
klog.Infof("Upgrader: found 0 Kubernetes StatefulSets owned by TidbCluster, nothing need to do")
return nil
}
klog.Infof("Upgrader: %d Kubernetes Statfulsets owned by TidbCluster should be migrated to Advanced Statefulsets", len(stsToMigrate))
// Check if relavant TidbClusters have delete slots annotations set.
for _, tc := range tidbClusters {
// Existing delete slots annotations must be removed first. This is
// a safety check to ensure no pods are affected in upgrading
// process.
if anns := deleteSlotAnns(tc); len(anns) > 0 {
return fmt.Errorf("Upgrader: TidbCluster %s/%s has delete slot annotations %v, please remove them before enabling AdvancedStatefulSet feature", tc.Namespace, tc.Name, anns)
}
}
klog.Infof("Upgrader: found %d Kubernetes StatefulSets owned by TidbCluster, trying to migrate one by one", len(stsToMigrate))
for _, sts := range stsToMigrate {
_, err := helper.Upgrade(u.kubeCli, u.asCli, &sts)
Expand All @@ -116,15 +122,15 @@ func (u *upgrader) Upgrade() error {
}
stsList, err := u.asCli.AppsV1().StatefulSets(u.ns).List(metav1.ListOptions{})
if err != nil {
if errors.IsNotFound(err) {
if apierrors.IsNotFound(err) {
klog.Infof("Upgrader: Kubernetes server does't have Advanced StatefulSets resources, skip to revert")
return nil
}
return err
}
stsToMigrate := make([]asappsv1.StatefulSet, 0)
for _, sts := range stsList.Items {
if isOwnedByTidbCluster(&sts) {
if ok, _ := isOwnedByTidbCluster(&sts); ok {
stsToMigrate = append(stsToMigrate, sts)
}
}
Expand Down
78 changes: 77 additions & 1 deletion pkg/upgrader/upgrader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func TestIsOwnedByTidbCluster(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ok := isOwnedByTidbCluster(&tt.sts)
ok, _ := isOwnedByTidbCluster(&tt.sts)
if tt.wantOK != ok {
t.Errorf("got %v, want %v", ok, tt.wantOK)
}
Expand Down Expand Up @@ -160,10 +160,12 @@ func TestDeleteSlotAnns(t *testing.T) {
}

var (
ownerTCName = "foo"
validOwnerRefs = []metav1.OwnerReference{
{
APIVersion: "pingcap.com/v1alpha1",
Kind: "TidbCluster",
Name: ownerTCName,
Controller: pointer.BoolPtr(true),
},
}
Expand Down Expand Up @@ -319,6 +321,8 @@ func TestUpgrade(t *testing.T) {
tidbClusters: []v1alpha1.TidbCluster{
{
ObjectMeta: metav1.ObjectMeta{
Name: ownerTCName,
Namespace: "sts",
Annotations: map[string]string{
label.AnnTiDBDeleteSlots: "[1,2]",
},
Expand Down Expand Up @@ -378,6 +382,78 @@ func TestUpgrade(t *testing.T) {
},
},
},
{
name: "should upgrade if tc has delete slot annotations but does not own Kubernetes StatefulSets",
tidbClusters: []v1alpha1.TidbCluster{
{
ObjectMeta: metav1.ObjectMeta{
Name: ownerTCName,
Namespace: "sts",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: "sts",
Annotations: map[string]string{
label.AnnTiDBDeleteSlots: "[1,2]",
},
},
},
},
statefulsets: []appsv1.StatefulSet{
{
TypeMeta: metav1.TypeMeta{
Kind: "StatefulSet",
APIVersion: "apps/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "sts1",
Namespace: "sts",
OwnerReferences: validOwnerRefs,
},
},
{
TypeMeta: metav1.TypeMeta{
Kind: "StatefulSet",
APIVersion: "apps/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "sts2",
Namespace: "sts",
OwnerReferences: validOwnerRefs,
},
},
},
feature: "AdvancedStatefulSet=true",
ns: metav1.NamespaceAll,
wantErr: false,
wantAdvancedStatefulsets: []asappsv1.StatefulSet{
{
TypeMeta: metav1.TypeMeta{
Kind: "StatefulSet",
APIVersion: "apps.pingcap.com/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "sts1",
Namespace: "sts",
OwnerReferences: validOwnerRefs,
},
},
{
TypeMeta: metav1.TypeMeta{
Kind: "StatefulSet",
APIVersion: "apps.pingcap.com/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "sts2",
Namespace: "sts",
OwnerReferences: validOwnerRefs,
},
},
},
wantStatefulsets: nil,
},
{
name: "should ignore if sts is not owned by TidbCluster",
tidbClusters: nil,
Expand Down

0 comments on commit fe29ffa

Please sign in to comment.