From 2b170abcc787e9377851e208ed25b2c59c766820 Mon Sep 17 00:00:00 2001 From: dongming Date: Sun, 8 Jan 2023 20:09:50 +0800 Subject: [PATCH] =?UTF-8?q?l-109=20=E9=87=8D=E6=9E=84=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=9B=B4=E6=96=B002?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/v1/msbdeployment_types.go | 4 + api/v1/zz_generated.deepcopy.go | 5 + .../apps.mashibing.com_msbdeployments.yaml | 8 +- controllers/msbdeployment_controller.go | 159 ++++++++---------- test/e2e/e2e.xml | 130 +++++++------- 5 files changed, 153 insertions(+), 153 deletions(-) diff --git a/api/v1/msbdeployment_types.go b/api/v1/msbdeployment_types.go index 5926a88..c1411a0 100644 --- a/api/v1/msbdeployment_types.go +++ b/api/v1/msbdeployment_types.go @@ -82,6 +82,10 @@ type MsbDeploymentStatus struct { // Conditions 处于这个阶段的原因 // +optional Conditions []Condition `json:"conditions,omitempty"` + + // ObservedGeneration 观测一次reconcile产生的变化,如果有变化自加,最终判断是否变更,如果变更则请求apiserver整整的跟新,否则不做任何更新 + // +optional + ObservedGeneration int32 `json:"observedGeneration,omitempty"` } // defines the observed state of Condition diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 9df43e7..259dfe0 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -119,6 +119,11 @@ func (in *MsbDeploymentList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MsbDeploymentSpec) DeepCopyInto(out *MsbDeploymentSpec) { *out = *in + if in.StartCmd != nil { + in, out := &in.StartCmd, &out.StartCmd + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.Args != nil { in, out := &in.Args, &out.Args *out = make([]string, len(*in)) diff --git a/config/crd/bases/apps.mashibing.com_msbdeployments.yaml b/config/crd/bases/apps.mashibing.com_msbdeployments.yaml index 3b02844..f37e5d1 100644 --- a/config/crd/bases/apps.mashibing.com_msbdeployments.yaml +++ b/config/crd/bases/apps.mashibing.com_msbdeployments.yaml @@ -185,7 +185,9 @@ spec: type: integer startCmd: description: StartCmd 存储启动命令 - type: string + items: + type: string + type: array required: - expose - image @@ -220,6 +222,10 @@ spec: message: description: Message 这个阶段的信息 type: string + observedGeneration: + description: ObservedGeneration 观测一次reconcile产生的变化,如果有变化自加,最终判断是否变更,如果变更则请求apiserver整整的跟新,否则不做任何更新 + format: int32 + type: integer phase: description: Phase 处于什么阶段 type: string diff --git a/controllers/msbdeployment_controller.go b/controllers/msbdeployment_controller.go index d9ae3f0..64d6ed3 100644 --- a/controllers/msbdeployment_controller.go +++ b/controllers/msbdeployment_controller.go @@ -104,6 +104,17 @@ func (r *MsbDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques // 防止污染缓存 mdCopy := md.DeepCopy() + // 处理最终的返回 + defer func() { + if r.Ready(mdCopy) { + _ = r.Client.Status().Update(ctx, mdCopy) + return + } + if mdCopy.Status.ObservedGeneration != md.Status.ObservedGeneration { + _ = r.Client.Status().Update(ctx, mdCopy) + } + }() + // ======= 处理 deployment ====== // 2. 获取deployment资源对象 deploy := new(appsv1.Deployment) @@ -114,23 +125,19 @@ func (r *MsbDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques if errCreate := r.createDeployment(ctx, mdCopy); err != nil { return ctrl.Result{}, errCreate } - if _, errStatus := r.updateStatus(ctx, + r.updateConditions( mdCopy, myAppsv1.ConditionTypeDeployment, fmt.Sprintf(myAppsv1.ConditionMessageDeploymentNotFmt, req.Name), myAppsv1.ConditonStatusFalse, - myAppsv1.ConditionReasonDeploymentNotReady); errStatus != nil { - return ctrl.Result{}, errStatus - } + myAppsv1.ConditionReasonDeploymentNotReady) } else { - if _, errStatus := r.updateStatus(ctx, + r.updateConditions( mdCopy, myAppsv1.ConditionTypeDeployment, fmt.Sprintf("Deployment %s, err: %s", req.Name, err.Error()), myAppsv1.ConditonStatusFalse, - myAppsv1.ConditionReasonDeploymentNotReady); errStatus != nil { - return ctrl.Result{}, errStatus - } + myAppsv1.ConditionReasonDeploymentNotReady) return ctrl.Result{}, err } } else { @@ -140,23 +147,19 @@ func (r *MsbDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, err } if deploy.Status.AvailableReplicas == mdCopy.Spec.Replicas { - if _, errStatus := r.updateStatus(ctx, + r.updateConditions( mdCopy, myAppsv1.ConditionTypeDeployment, fmt.Sprintf(myAppsv1.ConditionMessageDeploymentOKFmt, req.Name), myAppsv1.ConditonStatusTrue, - myAppsv1.ConditionReasonDeploymentReady); errStatus != nil { - return ctrl.Result{}, errStatus - } + myAppsv1.ConditionReasonDeploymentReady) } else { - if _, errStatus := r.updateStatus(ctx, + r.updateConditions( mdCopy, myAppsv1.ConditionTypeDeployment, fmt.Sprintf(myAppsv1.ConditionMessageDeploymentNotFmt, req.Name), myAppsv1.ConditonStatusFalse, - myAppsv1.ConditionReasonDeploymentNotReady); errStatus != nil { - return ctrl.Result{}, errStatus - } + myAppsv1.ConditionReasonDeploymentNotReady) } } @@ -170,14 +173,12 @@ func (r *MsbDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, err } } else { - if _, errStatus := r.updateStatus(ctx, + r.updateConditions( mdCopy, myAppsv1.ConditionTypeService, fmt.Sprintf("Service %s, err: %s", req.Name, err.Error()), myAppsv1.ConditonStatusFalse, - myAppsv1.ConditionReasonServiceNotReady); errStatus != nil { - return ctrl.Result{}, errStatus - } + myAppsv1.ConditionReasonServiceNotReady) return ctrl.Result{}, err } } else { @@ -187,14 +188,12 @@ func (r *MsbDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // 检查 现有状态来更新 status - if _, errStatus := r.updateStatus(ctx, + r.updateConditions( mdCopy, myAppsv1.ConditionTypeService, fmt.Sprintf(myAppsv1.ConditionMessageServiceOKFmt, req.Name), myAppsv1.ConditonStatusTrue, - myAppsv1.ConditionReasonServiceReady); errStatus != nil { - return ctrl.Result{}, errStatus - } + myAppsv1.ConditionReasonServiceReady) } // ======= 处理 ingress ========= @@ -209,14 +208,12 @@ func (r *MsbDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques if err := r.createIngress(ctx, mdCopy); err != nil { return ctrl.Result{}, err } - if _, errStatus := r.updateStatus(ctx, + r.updateConditions( mdCopy, myAppsv1.ConditionTypeIngress, fmt.Sprintf(myAppsv1.ConditionMessageIngressNotFmt, req.Name), myAppsv1.ConditonStatusFalse, - myAppsv1.ConditionReasonIngressNotReady); errStatus != nil { - return ctrl.Result{}, errStatus - } + myAppsv1.ConditionReasonIngressNotReady) if mdCopy.Spec.Expose.Tls { // 创建 issuers if err := r.createIssuer(ctx, mdCopy); err != nil { @@ -234,14 +231,12 @@ func (r *MsbDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, nil } } else { - if _, errStatus := r.updateStatus(ctx, + r.updateConditions( mdCopy, myAppsv1.ConditionTypeIngress, fmt.Sprintf("Ingress %s, err: %s", req.Name, err.Error()), myAppsv1.ConditonStatusFalse, - myAppsv1.ConditionReasonIngressNotReady); errStatus != nil { - return ctrl.Result{}, errStatus - } + myAppsv1.ConditionReasonIngressNotReady) return ctrl.Result{}, err } } else { @@ -252,14 +247,12 @@ func (r *MsbDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques if err := r.updateIngress(ctx, mdCopy, ig); err != nil { return ctrl.Result{}, err } - if _, errStatus := r.updateStatus(ctx, + r.updateConditions( mdCopy, myAppsv1.ConditionTypeIngress, fmt.Sprintf(myAppsv1.ConditionMessageIngressOKFmt, req.Name), myAppsv1.ConditonStatusTrue, - myAppsv1.ConditionReasonIngressReady); errStatus != nil { - return ctrl.Result{}, errStatus - } + myAppsv1.ConditionReasonIngressReady) if mdCopy.Spec.Expose.Tls { // 创建 issuers if err := r.createIssuer(ctx, mdCopy); err != nil { @@ -281,20 +274,10 @@ func (r *MsbDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Reques } } - // 最后检查状态时候最终完成 - if sus, errStatus := r.updateStatus(ctx, - mdCopy, - "", - "", - "", - ""); errStatus != nil { - return ctrl.Result{}, errStatus - } else if !sus { - logger.Info("Reconcile is ended.") + logger.Info("Reconcile is ended.") + if !r.Ready(mdCopy) { return ctrl.Result{RequeueAfter: WaitRequeue}, nil } - - logger.Info("Reconcile is ended.") return ctrl.Result{}, nil } @@ -303,7 +286,7 @@ func (r *MsbDeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&myAppsv1.MsbDeployment{}). Owns(&appsv1.Deployment{}). // 监控 deployment 类型,变更就触发 reconciler - Owns(&corev1.Service{}). // 监控 service 类型,变更就触发 reconciler + Owns(&corev1.Service{}). // 监控 service 类型,变更就触发 reconciler Owns(&networkv1.Ingress{}). // 监控 ingress 类型,变更就触发 reconciler Complete(r) } @@ -410,43 +393,41 @@ func (r *MsbDeploymentReconciler) deleteIngress(ctx context.Context, md *myAppsv return r.Client.Delete(ctx, &ig) } -// 处理status -// return: -// -// bool: 资源是否完成,时候需要等待。如果是 true,表示资源已经完成没不需要再次reconcile -// 如果是 false,表示资源还未完成,需要重新入队 -// error:执行 update 的状态 -func (r *MsbDeploymentReconciler) updateStatus(ctx context.Context, md *myAppsv1.MsbDeployment, conditionType, message, status, reason string) (bool, error) { - if conditionType != "" { - // 1. 获取 status - //status := md.Status - // 2. 获取 conditions 字段 - //conditions := status.Conditions - // 3. 根据当前的需求,获取指定的 condition - var condition *myAppsv1.Condition - for i := range md.Status.Conditions { - // 4. 是否获取到 - if md.Status.Conditions[i].Type == conditionType { - // 4.1 获取到了 - condition = &md.Status.Conditions[i] - } +// 更新Condition,并变更版本 +func (r *MsbDeploymentReconciler) updateConditions(md *myAppsv1.MsbDeployment, conditionType, message, status, reason string) { + // 1. 获取 status + //status := md.Status + // 2. 获取 conditions 字段 + //conditions := status.Conditions + // 3. 根据当前的需求,获取指定的 condition + var condition *myAppsv1.Condition + for i := range md.Status.Conditions { + // 4. 是否获取到 + if md.Status.Conditions[i].Type == conditionType { + // 4.1 获取到了 + condition = &md.Status.Conditions[i] } - if condition != nil { - // 4.1.1 获取当前线上的 conditon 状态,与存储的condition进行比较,如果相同,跳过。不同,替换 - if condition.Status != status || - condition.Message != message || - condition.Reason != reason { - condition.Status = status - condition.Message = message - condition.Reason = reason - } - } else { - // 4.2 没获取到,创建这个conditon,更新到conditons中 - md.Status.Conditions = append(md.Status.Conditions, - createCondition(conditionType, message, status, reason)) + } + if condition != nil { + // 4.1.1 获取当前线上的 conditon 状态,与存储的condition进行比较,如果相同,跳过。不同,替换 + if condition.Status != status || + condition.Message != message || + condition.Reason != reason { + condition.Status = status + condition.Message = message + condition.Reason = reason + md.Status.ObservedGeneration += 1 } + } else { + // 4.2 没获取到,创建这个conditon,更新到conditons中 + md.Status.Conditions = append(md.Status.Conditions, + createCondition(conditionType, message, status, reason)) + md.Status.ObservedGeneration += 1 } +} +// Ready 判断本次 reconcile 是否达到预期 +func (r *MsbDeploymentReconciler) Ready(md *myAppsv1.MsbDeployment) bool { // 5. 继续处理其他的conditions m, re, p, sus := isSuccess(md.Status.Conditions) if sus { @@ -456,12 +437,16 @@ func (r *MsbDeploymentReconciler) updateStatus(ctx context.Context, md *myAppsv1 md.Status.Phase = myAppsv1.StatusPhaseComplete } else { // 6.2 遍历所有的conditons 状态,如果有任意一个condition不是完成的状态,则将这个状态更新到总的 status 中。更待一定时间再次入队。 - md.Status.Message = m - md.Status.Reason = re - md.Status.Phase = p + if md.Status.Message != m || + md.Status.Reason != re || + md.Status.Phase != p { + md.Status.Message = m + md.Status.Reason = re + md.Status.Phase = p + md.Status.ObservedGeneration += 1 + } } - // 7. 执行更新 - return sus, r.Client.Status().Update(ctx, md) + return sus } func isSuccess(conditions []myAppsv1.Condition) (message, reason, phase string, sus bool) { diff --git a/test/e2e/e2e.xml b/test/e2e/e2e.xml index 4e9fb31..8b71da9 100644 --- a/test/e2e/e2e.xml +++ b/test/e2e/e2e.xml @@ -1,67 +1,67 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file