Skip to content

Commit 7c21633

Browse files
authored
fix(instance): fix and refactor ready condition (#6153)
1 parent 7fe1319 commit 7c21633

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+911
-757
lines changed

api/core/v1alpha1/common_types.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,19 @@ const (
3131
const (
3232
// Ready means all managed resources are ready.
3333
// NOTE: It does not mean all managed resources are up to date.
34+
//
35+
// condition
3436
CondReady = "Ready"
37+
// reason for both
38+
ReasonReady = "Ready"
39+
ReasonUnready = "Unready"
40+
// reason for group
41+
ReasonNotAllInstancesReady = "NotAllInstancesReady"
42+
// reason for instance
43+
ReasonPodNotCreated = "PodNotCreated"
44+
ReasonPodNotReady = "PodNotReady"
45+
ReasonPodTerminating = "PodTerminating"
46+
ReasonInstanceNotHealthy = "InstanceNotHealthy"
3547

3648
// Synced means all specs of managed resources are as expected and
3749
// nothing need to do in controller but only status updation.

pkg/apicall/instance.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ func GetPod[
4141
return nil, err
4242
}
4343

44+
if len(pl.Items) == 0 {
45+
return nil, nil
46+
}
47+
4448
if len(pl.Items) != 1 {
4549
return nil, fmt.Errorf("expected only 1 pod, but now %d", len(pl.Items))
4650
}

pkg/apiutil/core/v1alpha1/condition.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
package coreutil
1616

1717
import (
18+
"fmt"
19+
1820
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1921

2022
"github.com/pingcap/tidb-operator/api/v2/core/v1alpha1"
@@ -51,17 +53,34 @@ func Ready() *metav1.Condition {
5153
return &metav1.Condition{
5254
Type: v1alpha1.CondReady,
5355
Status: metav1.ConditionTrue,
54-
Reason: "Ready",
56+
Reason: v1alpha1.CondReady,
5557
Message: "all subreources are ready",
5658
}
5759
}
5860

59-
func Unready() *metav1.Condition {
61+
func Unready(reason string) *metav1.Condition {
62+
var msg string
63+
switch reason {
64+
case v1alpha1.ReasonNotAllInstancesReady:
65+
msg = "not all instances are ready"
66+
case v1alpha1.ReasonPodNotCreated:
67+
msg = "pod of the instance does not exist"
68+
case v1alpha1.ReasonPodNotReady:
69+
msg = "pod of the instance is not ready"
70+
case v1alpha1.ReasonPodTerminating:
71+
msg = "pod of the instance is terminating"
72+
case v1alpha1.ReasonInstanceNotHealthy:
73+
msg = "instance is not probed as healthy"
74+
default:
75+
msg = fmt.Sprintf("unready because of unknown reason: %s", reason)
76+
reason = v1alpha1.ReasonUnready
77+
}
78+
6079
return &metav1.Condition{
6180
Type: v1alpha1.CondReady,
6281
Status: metav1.ConditionFalse,
63-
Reason: "Unready",
64-
Message: "not all instances are ready",
82+
Reason: reason,
83+
Message: msg,
6584
}
6685
}
6786

pkg/controllers/common/interfaces.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,38 @@ type (
246246
}
247247
PodState interface {
248248
Pod() *corev1.Pod
249+
IsPodTerminating() bool
250+
}
251+
PodStateUpdater interface {
252+
// It will be called after get or update api calls to k8s
253+
SetPod(pod *corev1.Pod)
254+
// Pod cannot be updated when call DELETE API, so we have to mark pod is deleting after calling DELETE api
255+
DeletePod(pod *corev1.Pod)
249256
}
250257
)
251258

252259
type StoreState interface {
253260
GetStoreState() string
254-
SetStoreState(string)
255261
// IsStoreUp returns true if the store state is `Preparing` or `Serving`,
256262
// which means the store is in the state of providing services.
257263
IsStoreUp() bool
258264
}
265+
266+
type StoreStateUpdater interface {
267+
SetStoreState(string)
268+
}
269+
270+
type HealthyState interface {
271+
// It means the instance is healthy to serve.
272+
// Normally, it's from PD or api exposed by the instance.
273+
// Now the operator checks it just like a liveness/readiness prober.
274+
// It may be removed if all components support /ready api in the future.
275+
// And then we can use pod's ready condition directly to check whether the instance
276+
// is ready.
277+
// But now, we still probe health from the operator.
278+
IsHealthy() bool
279+
}
280+
281+
type HealthyStateUpdater interface {
282+
SetHealthy()
283+
}

pkg/controllers/common/interfaces_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ func (f *fakePodState) PodInitializer() PodInitializer {
9191
return f.s.Initializer()
9292
}
9393

94+
func (f *fakePodState) IsPodTerminating() bool {
95+
return false
96+
}
97+
9498
type fakePDSliceState struct {
9599
s *fakeSliceState[v1alpha1.PD]
96100
}

pkg/controllers/common/mock_generated.go

Lines changed: 107 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/controllers/common/task.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"slices"
2222
"strings"
2323

24+
corev1 "k8s.io/api/core/v1"
2425
"k8s.io/apimachinery/pkg/api/errors"
2526
"k8s.io/apimachinery/pkg/api/meta"
2627
kuberuntime "k8s.io/apimachinery/pkg/runtime"
@@ -126,11 +127,6 @@ func TaskContextTiCDC(state TiCDCStateInitializer, c client.Client) task.Task {
126127
return taskContextResource("TiCDC", w, c, false)
127128
}
128129

129-
func TaskContextPod(state PodStateInitializer, c client.Client) task.Task {
130-
w := state.PodInitializer()
131-
return taskContextResource("Pod", w, c, false)
132-
}
133-
134130
func TaskContextPDGroup(state PDGroupStateInitializer, c client.Client) task.Task {
135131
w := state.PDGroupInitializer()
136132
return taskContextResource("PDGroup", w, c, false)
@@ -232,3 +228,29 @@ func TaskContextCluster[
232228
return task.Complete().With("cluster is set")
233229
})
234230
}
231+
232+
type ContextPodNewer[
233+
F client.Object,
234+
] interface {
235+
Object() F
236+
SetPod(pod *corev1.Pod)
237+
}
238+
239+
func TaskContextPod[
240+
S scope.Instance[F, T],
241+
F client.Object,
242+
T runtime.Instance,
243+
](state ContextPodNewer[F], c client.Client) task.Task {
244+
return task.NameTaskFunc("ContextPod", func(ctx context.Context) task.Result {
245+
pod, err := apicall.GetPod[S](ctx, c, state.Object())
246+
if err != nil {
247+
return task.Fail().With("cannot get pod: %v", err)
248+
}
249+
if pod == nil {
250+
return task.Complete().With("pod doesn't exist")
251+
}
252+
253+
state.SetPod(pod)
254+
return task.Complete().With("pod is set")
255+
})
256+
}

0 commit comments

Comments
 (0)