From 1bf39684b24f98c5dcc526ffaf9f8e11f80c9748 Mon Sep 17 00:00:00 2001 From: berg Date: Tue, 11 Jul 2023 14:16:12 +0800 Subject: [PATCH] auto patch webhook objectSelector label on workload (#158) Signed-off-by: liheng.zms --- config/webhook/patch_manifests.yaml | 22 +++++++++++ pkg/controller/rollout/rollout_controller.go | 6 ++- pkg/controller/rollout/rollout_status.go | 41 ++++++++++++++++++-- test/e2e/rollout_test.go | 6 ++- 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/config/webhook/patch_manifests.yaml b/config/webhook/patch_manifests.yaml index 84d7959b..5022bcab 100644 --- a/config/webhook/patch_manifests.yaml +++ b/config/webhook/patch_manifests.yaml @@ -8,6 +8,26 @@ webhooks: matchExpressions: - key: rollouts.kruise.io/workload-type operator: Exists + - name: mcloneset.kb.io + objectSelector: + matchExpressions: + - key: rollouts.kruise.io/workload-type + operator: Exists + - name: mdaemonset.kb.io + objectSelector: + matchExpressions: + - key: rollouts.kruise.io/workload-type + operator: Exists + - name: mstatefulset.kb.io + objectSelector: + matchExpressions: + - key: rollouts.kruise.io/workload-type + operator: Exists + - name: madvancedstatefulset.kb.io + objectSelector: + matchExpressions: + - key: rollouts.kruise.io/workload-type + operator: Exists - name: mdeployment.kb.io objectSelector: matchExpressions: @@ -15,3 +35,5 @@ webhooks: operator: NotIn values: - controller-manager + - key: rollouts.kruise.io/workload-type + operator: Exists diff --git a/pkg/controller/rollout/rollout_controller.go b/pkg/controller/rollout/rollout_controller.go index c783697c..cffeb2df 100755 --- a/pkg/controller/rollout/rollout_controller.go +++ b/pkg/controller/rollout/rollout_controller.go @@ -130,7 +130,11 @@ func (r *RolloutReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct if err != nil { return ctrl.Result{}, err } - + // Patch rollout webhook objectSelector in workload labels[rollouts.kruise.io/workload-type], + // then rollout only webhook the workload which contains labels[rollouts.kruise.io/workload-type]. + if err = r.patchWorkloadRolloutWebhookLabel(rollout); err != nil { + return ctrl.Result{}, err + } // sync rollout status retry, newStatus, err := r.calculateRolloutStatus(rollout) if err != nil { diff --git a/pkg/controller/rollout/rollout_status.go b/pkg/controller/rollout/rollout_status.go index 15edbba8..d5a0bbe3 100755 --- a/pkg/controller/rollout/rollout_status.go +++ b/pkg/controller/rollout/rollout_status.go @@ -25,6 +25,7 @@ import ( "github.com/openkruise/rollouts/api/v1alpha1" "github.com/openkruise/rollouts/pkg/util" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/client-go/util/retry" @@ -80,14 +81,12 @@ func (r *RolloutReconciler) calculateRolloutStatus(rollout *v1alpha1.Rollout) (r } return false, newStatus, nil } - klog.V(5).Infof("rollout(%s/%s) workload(%s)", rollout.Namespace, rollout.Name, util.DumpJSON(workload)) - // todo, patch workload webhook labels + klog.V(5).Infof("rollout(%s/%s) fetch workload(%s)", rollout.Namespace, rollout.Name, util.DumpJSON(workload)) // workload status generation is not equal to workload.generation if !workload.IsStatusConsistent { klog.Infof("rollout(%s/%s) workload status is inconsistent, then wait a moment", rollout.Namespace, rollout.Name) return true, nil, nil } - // update workload generation to canaryStatus.ObservedWorkloadGeneration // rollout is a target ref bypass, so there needs to be a field to identify the rollout execution process or results, // which version of deployment is targeted, ObservedWorkloadGeneration that is to compare with the workload generation @@ -249,6 +248,42 @@ func (r *RolloutReconciler) reconcileRolloutDisabling(rollout *v1alpha1.Rollout, return c.RecheckTime, nil } +func (r *RolloutReconciler) patchWorkloadRolloutWebhookLabel(rollout *v1alpha1.Rollout) error { + // get ref workload + workload, err := r.finder.GetWorkloadForRef(rollout) + if err != nil { + klog.Errorf("rollout(%s/%s) get workload failed: %s", rollout.Namespace, rollout.Name, err.Error()) + return err + } else if workload == nil { + return nil + } + + var workloadType util.WorkloadType + switch workload.Kind { + case util.ControllerKruiseKindCS.Kind: + workloadType = util.CloneSetType + case util.ControllerKindDep.Kind: + workloadType = util.DeploymentType + case util.ControllerKindSts.Kind: + workloadType = util.StatefulSetType + case util.ControllerKruiseKindDS.Kind: + workloadType = util.DaemonSetType + } + if workload.Annotations[util.WorkloadTypeLabel] == "" && workloadType != "" { + workloadGVK := schema.FromAPIVersionAndKind(workload.APIVersion, workload.Kind) + obj := util.GetEmptyWorkloadObject(workloadGVK) + obj.SetNamespace(workload.Namespace) + obj.SetName(workload.Name) + body := fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`, util.WorkloadTypeLabel, workloadType) + if err := r.Patch(context.TODO(), obj, client.RawPatch(types.MergePatchType, []byte(body))); err != nil { + klog.Errorf("rollout(%s/%s) patch workload(%s) failed: %s", rollout.Namespace, rollout.Name, workload.Name, err.Error()) + return err + } + klog.Infof("rollout(%s/%s) patch workload(%s) labels[%s] success", rollout.Namespace, rollout.Name, workload.Name, util.WorkloadTypeLabel) + } + return nil +} + // handle adding and handle finalizer logic, it turns if we should continue to reconcile func (r *RolloutReconciler) handleFinalizer(rollout *v1alpha1.Rollout) error { // delete rollout crd, remove finalizer diff --git a/test/e2e/rollout_test.go b/test/e2e/rollout_test.go index e158b688..af065e17 100644 --- a/test/e2e/rollout_test.go +++ b/test/e2e/rollout_test.go @@ -245,8 +245,8 @@ var _ = SIGDescribe("Rollout", func() { Eventually(func() bool { daemon := &appsv1alpha1.DaemonSet{} Expect(GetObject(daemonset.Name, daemon)).NotTo(HaveOccurred()) - klog.Infof("DaemonSet Generation(%d) ObservedGeneration(%d) DesiredNumberScheduled(%d) UpdatedNumberScheduled(%d) NumberReady(%d)", - daemon.Generation, daemon.Status.ObservedGeneration, daemon.Status.DesiredNumberScheduled, daemon.Status.UpdatedNumberScheduled, daemon.Status.NumberReady) + klog.Infof("DaemonSet updateStrategy(%s) Generation(%d) ObservedGeneration(%d) DesiredNumberScheduled(%d) UpdatedNumberScheduled(%d) NumberReady(%d)", + util.DumpJSON(daemon.Spec.UpdateStrategy), daemon.Generation, daemon.Status.ObservedGeneration, daemon.Status.DesiredNumberScheduled, daemon.Status.UpdatedNumberScheduled, daemon.Status.NumberReady) return daemon.Status.ObservedGeneration == daemon.Generation && daemon.Status.DesiredNumberScheduled == daemon.Status.UpdatedNumberScheduled && daemon.Status.DesiredNumberScheduled == daemon.Status.NumberReady }, 5*time.Minute, time.Second).Should(BeTrue()) } @@ -5480,6 +5480,8 @@ var _ = SIGDescribe("Rollout", func() { Expect(k8sClient.DeleteAllOf(context.TODO(), &v1alpha1.Rollout{}, client.InNamespace(namespace), client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed()) WaitRolloutNotFound(rollout.Name) Expect(GetObject(workload.Name, workload)).NotTo(HaveOccurred()) + workload.Spec.UpdateStrategy.RollingUpdate.Partition = utilpointer.Int32(0) + UpdateDaemonSet(workload) WaitDaemonSetAllPodsReady(workload) // check daemonset