Skip to content

Commit dcf5184

Browse files
authored
fix(ops): fail invalid switchover instances (#10455)
1 parent 58d79a1 commit dcf5184

5 files changed

Lines changed: 443 additions & 8 deletions

File tree

pkg/operations/ops_manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func (opsMgr *OpsManager) Do(reqCtx intctrlutil.RequestCtx, cli client.Client, o
9898
return &ctrl.Result{}, patchFatalFailErrorCondition(reqCtx.Ctx, cli, opsRes, err)
9999
}
100100
if intctrlutil.IsTargetError(err, intctrlutil.ErrorTypeNeedWaiting) {
101-
return intctrlutil.ResultToP(intctrlutil.Reconciled())
101+
return intctrlutil.ResultToP(intctrlutil.RequeueAfter(time.Second, reqCtx.Log, err.Error()))
102102
}
103103
return nil, err
104104
}

pkg/operations/ops_runtime.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,21 @@ func (r *opsRuntime) doSwitchover(ctx context.Context, cli client.Reader, synthe
228228
break
229229
}
230230
}
231+
if pod.Name == "" {
232+
return intctrlutil.NewFatalError(fmt.Sprintf(`instance "%s" not found`, switchover.InstanceName))
233+
}
234+
if switchover.CandidateName != "" {
235+
candidate, err := r.GetInstance(synthesizedComp.Namespace, synthesizedComp.ClusterName, synthesizedComp.Name, switchover.CandidateName)
236+
if err != nil {
237+
if apierrors.IsNotFound(err) {
238+
return intctrlutil.NewFatalError(fmt.Sprintf(`candidate instance "%s" not found`, switchover.CandidateName))
239+
}
240+
return err
241+
}
242+
if !candidate.HasPod() {
243+
return intctrlutil.NewFatalError(fmt.Sprintf(`candidate instance "%s" not found`, switchover.CandidateName))
244+
}
245+
}
231246

232247
lfa, err := lifecycle.New(synthesizedComp.Namespace, synthesizedComp.ClusterName, synthesizedComp.Name,
233248
synthesizedComp.LifecycleActions.ComponentLifecycleActions, synthesizedComp.TemplateVars, pod, pods)
@@ -377,6 +392,10 @@ func (i *defaultInstance) GetCreationTimestamp() metav1.Time {
377392
return i.pod.CreationTimestamp
378393
}
379394

395+
func (i *defaultInstance) HasPod() bool {
396+
return i.pod != nil
397+
}
398+
380399
func (i *defaultInstance) IsDeleting() bool {
381400
return i.pod != nil && !i.pod.DeletionTimestamp.IsZero()
382401
}

pkg/operations/switchover.go

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
apierrors "k8s.io/apimachinery/pkg/api/errors"
3131
"k8s.io/apimachinery/pkg/api/meta"
3232
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
33+
"k8s.io/apimachinery/pkg/runtime/schema"
3334
"k8s.io/client-go/tools/record"
3435
"sigs.k8s.io/controller-runtime/pkg/client"
3536

@@ -125,17 +126,24 @@ func switchoverPreCheck(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes
125126
if err != nil {
126127
return err
127128
}
128-
instance, err := runtime.GetInstance(synthesizedComp.Namespace, synthesizedComp.ClusterName, synthesizedComp.Name, switchover.InstanceName)
129+
instance, err := getSwitchoverPodBackedInstance(runtime, synthesizedComp.Namespace, synthesizedComp.ClusterName, synthesizedComp.Name, switchover.InstanceName)
129130
if err != nil {
131+
if apierrors.IsNotFound(err) {
132+
return intctrlutil.NewFatalError(fmt.Sprintf(`instance "%s" not found`, switchover.InstanceName))
133+
}
130134
return err
131135
}
132136
roleName := instance.GetRole()
133137
if roleName == "" {
134-
return intctrlutil.NewFatalError(fmt.Sprintf("pod %s cannot perform switchover because it does not have a role label", switchover.InstanceName))
138+
return intctrlutil.NewErrorf(intctrlutil.ErrorTypeNeedWaiting, "waiting for instance %s role label", switchover.InstanceName)
135139
}
136140

137141
if switchover.CandidateName != "" {
138-
if _, err := runtime.GetInstance(synthesizedComp.Namespace, synthesizedComp.ClusterName, synthesizedComp.Name, switchover.CandidateName); err != nil {
142+
_, err := getSwitchoverPodBackedInstance(runtime, synthesizedComp.Namespace, synthesizedComp.ClusterName, synthesizedComp.Name, switchover.CandidateName)
143+
if err != nil {
144+
if apierrors.IsNotFound(err) {
145+
return intctrlutil.NewFatalError(fmt.Sprintf(`candidate instance "%s" not found`, switchover.CandidateName))
146+
}
139147
return err
140148
}
141149
}
@@ -232,13 +240,19 @@ func handleSwitchover(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *
232240
case opsv1alpha1.ProcessingProgressStatus:
233241
targetRole := progressDetail.Group
234242
if switchover.CandidateName != "" {
235-
candidateInstance, err := runtime.GetInstance(synthesizedComp.Namespace, synthesizedComp.ClusterName, synthesizedComp.Name, switchover.CandidateName)
236-
if err != nil {
243+
candidateInstance, err := getSwitchoverPodBackedInstance(runtime, synthesizedComp.Namespace, synthesizedComp.ClusterName, synthesizedComp.Name, switchover.CandidateName)
244+
switch {
245+
case err != nil && !apierrors.IsNotFound(err):
237246
return err
238-
}
239-
if targetRole == candidateInstance.GetRole() {
247+
case err != nil:
248+
progressDetail.Message = fmt.Sprintf(`component %s candidate instance "%s" not found`, compName, switchover.CandidateName)
249+
progressDetail.Status = opsv1alpha1.FailedProgressStatus
250+
case targetRole == candidateInstance.GetRole():
240251
progressDetail.Message = "do switchover succeed"
241252
progressDetail.Status = opsv1alpha1.SucceedProgressStatus
253+
default:
254+
progressDetail.Message = fmt.Sprintf("component %s is waiting for candidate pod %s role change, current role %q, expected role %q",
255+
compName, switchover.CandidateName, candidateInstance.GetRole(), targetRole)
242256
}
243257
} else {
244258
progressDetail.Message = "do switchover succeed"
@@ -249,6 +263,17 @@ func handleSwitchover(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *
249263
return nil
250264
}
251265

266+
func getSwitchoverPodBackedInstance(runtime OpsRuntime, namespace, clusterName, compName, instanceName string) (Instance, error) {
267+
instance, err := runtime.GetInstance(namespace, clusterName, compName, instanceName)
268+
if err != nil {
269+
return nil, err
270+
}
271+
if !instance.HasPod() {
272+
return nil, apierrors.NewNotFound(schema.GroupResource{Resource: "pods"}, instanceName)
273+
}
274+
return instance, nil
275+
}
276+
252277
// setComponentSwitchoverProgressDetails sets component switchover progress details.
253278
func setComponentSwitchoverProgressDetails(recorder record.EventRecorder,
254279
opsRequest *opsv1alpha1.OpsRequest,
@@ -348,6 +373,9 @@ func buildSynthesizedComp(ctx context.Context, cli client.Client, opsRes *OpsRes
348373
func getShardingComponentObjectNameByInstance(ctx context.Context, cli client.Client, cluster *appsv1.Cluster, shardingName, instanceName string) (string, error) {
349374
pod := &corev1.Pod{}
350375
if err := cli.Get(ctx, client.ObjectKey{Namespace: cluster.Namespace, Name: instanceName}, pod); err != nil {
376+
if apierrors.IsNotFound(err) {
377+
return "", intctrlutil.NewFatalError(fmt.Sprintf(`instance "%s" not found`, instanceName))
378+
}
351379
return "", err
352380
}
353381
if pod.Labels[constant.AppInstanceLabelKey] != cluster.Name {

0 commit comments

Comments
 (0)