Skip to content

Commit eb895e2

Browse files
authored
fix(store): automatically remove offlined store (#6497)
1 parent 50d95cd commit eb895e2

4 files changed

Lines changed: 92 additions & 0 deletions

File tree

pkg/controllers/common/cond.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ package common
1717
import (
1818
"slices"
1919

20+
"k8s.io/apimachinery/pkg/api/meta"
21+
22+
"github.com/pingcap/tidb-operator/api/v2/core/v1alpha1"
2023
coreutil "github.com/pingcap/tidb-operator/pkg/apiutil/core/v1alpha1"
2124
"github.com/pingcap/tidb-operator/pkg/client"
2225
"github.com/pingcap/tidb-operator/pkg/runtime"
@@ -89,3 +92,17 @@ func CondFeatureGatesIsNotSynced[
8992
return !slices.Equal(coreutil.Features[S](obj), coreutil.EnabledFeatures(cluster))
9093
})
9194
}
95+
96+
func CondObjectIsNotDeletingButOfflined[
97+
S scope.Instance[F, T],
98+
F client.Object,
99+
T runtime.Instance,
100+
](state ObjectState[F]) task.Condition {
101+
return task.CondFunc(func() bool {
102+
if !state.Object().GetDeletionTimestamp().IsZero() {
103+
return false
104+
}
105+
conds := coreutil.StatusConditions[S](state.Object())
106+
return meta.IsStatusConditionTrue(conds, v1alpha1.StoreOfflinedConditionType)
107+
})
108+
}

pkg/controllers/common/cond_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"testing"
1919

2020
"github.com/stretchr/testify/assert"
21+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2122

2223
"github.com/pingcap/tidb-operator/api/v2/core/v1alpha1"
2324
metav1alpha1 "github.com/pingcap/tidb-operator/api/v2/meta/v1alpha1"
@@ -300,3 +301,49 @@ func TestCondFeatureGatesIsNotSynced(t *testing.T) {
300301
})
301302
}
302303
}
304+
305+
func TestCondObjectIsNotDeletingButOfflined(t *testing.T) {
306+
cases := []struct {
307+
desc string
308+
state ObjectState[*v1alpha1.TiKV]
309+
expectedCond bool
310+
}{
311+
{
312+
desc: "cond is false, not offlined",
313+
state: newFakeObjectState(
314+
fake.FakeObj[v1alpha1.TiKV]("test"),
315+
),
316+
},
317+
{
318+
desc: "cond is false, deleting",
319+
state: newFakeObjectState(
320+
fake.FakeObj("test", fake.DeleteNow[v1alpha1.TiKV]()),
321+
),
322+
},
323+
{
324+
desc: "cond is true",
325+
state: newFakeObjectState(
326+
fake.FakeObj("test", func(obj *v1alpha1.TiKV) *v1alpha1.TiKV {
327+
obj.Status.Conditions = []metav1.Condition{
328+
{
329+
Type: v1alpha1.StoreOfflinedConditionType,
330+
Status: metav1.ConditionTrue,
331+
},
332+
}
333+
return obj
334+
}),
335+
),
336+
expectedCond: true,
337+
},
338+
}
339+
340+
for i := range cases {
341+
c := &cases[i]
342+
t.Run(c.desc, func(tt *testing.T) {
343+
tt.Parallel()
344+
345+
cond := CondObjectIsNotDeletingButOfflined[scope.TiKV](c.state)
346+
assert.Equal(tt, c.expectedCond, cond.Satisfy(), c.desc)
347+
})
348+
}
349+
}

pkg/controllers/common/task.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
corev1 "k8s.io/api/core/v1"
2323
"k8s.io/apimachinery/pkg/api/errors"
24+
"k8s.io/apimachinery/pkg/api/meta"
2425
"k8s.io/apimachinery/pkg/types"
2526

2627
"github.com/pingcap/tidb-operator/api/v2/core/v1alpha1"
@@ -318,3 +319,25 @@ func TaskTrack[
318319
return task.Complete().With("track instance %s with group %v", state.Key(), group)
319320
})
320321
}
322+
323+
func TaskDeleteOfflinedStore[
324+
S scope.Instance[F, T],
325+
F client.Object,
326+
T runtime.Instance,
327+
](state ObjectState[F], c client.Client) task.Task {
328+
return task.NameTaskFunc("DeleteOfflinedStore", func(ctx context.Context) task.Result {
329+
obj := state.Object()
330+
if !obj.GetDeletionTimestamp().IsZero() {
331+
return task.Complete().With("store is deleting")
332+
}
333+
conds := coreutil.StatusConditions[S](state.Object())
334+
if !meta.IsStatusConditionTrue(conds, v1alpha1.StoreOfflinedConditionType) {
335+
return task.Complete().With("store is not offlined")
336+
}
337+
if err := c.Delete(ctx, obj); err != nil {
338+
return task.Fail().With("cannot delete store: %v", err)
339+
}
340+
341+
return task.Wait().With("wait until store deletion is watched")
342+
})
343+
}

pkg/controllers/tikv/builder.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ func (r *Reconciler) NewRunner(state *tasks.ReconcileContext, reporter task.Task
4343
tasks.TaskFinalizerDel(state, r.Client),
4444
),
4545

46+
// if instance is deleting and store is removed
47+
task.IfBreak(common.CondObjectIsNotDeletingButOfflined[scope.TiKV](state),
48+
common.TaskDeleteOfflinedStore[scope.TiKV](state, r.Client),
49+
),
50+
4651
// get pod and check whether the cluster is suspending
4752
common.TaskContextPod[scope.TiKV](state, r.Client),
4853
// get info from pd

0 commit comments

Comments
 (0)