From 0ed063560f8ae1898e24298a795dab6934023786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=8A=92=E6=83=85=E7=86=8A?= <2669184984@qq.com> Date: Thu, 5 Sep 2024 16:49:38 +0800 Subject: [PATCH] add devbox phase and controller (#5042) * fix ssh volume bug * add devbox phase and controller * add devbox phase and controller * add devbox phase and controller * add devbox phase and controller * add devbox phase and controller * add devbox phase and controller * add devbox phase and controller * add devbox phase and controller * add devbox phase and controller * add devbox phase and controller --- .../devbox/api/v1alpha1/devbox_types.go | 18 ++++++++ .../crd/bases/devbox.sealos.io_devboxes.yaml | 5 ++ .../devbox/deploy/manifests/deploy.yaml.tmpl | 5 ++ .../internal/controller/devbox_controller.go | 46 +++++++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/controllers/devbox/api/v1alpha1/devbox_types.go b/controllers/devbox/api/v1alpha1/devbox_types.go index 062de496a3e..636a2974a19 100644 --- a/controllers/devbox/api/v1alpha1/devbox_types.go +++ b/controllers/devbox/api/v1alpha1/devbox_types.go @@ -141,6 +141,21 @@ type CommitHistory struct { Status CommitStatus `json:"status"` } +type DevboxPhase string + +const ( + // DevboxPhaseRunning means Devbox is run and run success + DevboxPhaseRunning DevboxPhase = "Running" + // DevboxPhasePending means Devbox is run but not run success + DevboxPhasePending DevboxPhase = "Pending" + //DevboxPhaseStopped means Devbox is stop and stopped success + DevboxPhaseStopped DevboxPhase = "Stopped" + //DevboxPhaseStopping means Devbox is stop and not stopped success + DevboxPhaseStopping DevboxPhase = "Stopping" + //DevboxPhaseError means Devbox is error + DevboxPhaseError DevboxPhase = "Error" +) + // DevboxStatus defines the observed state of Devbox type DevboxStatus struct { // +kubebuilder:validation:Optional @@ -149,6 +164,8 @@ type DevboxStatus struct { Network NetworkStatus `json:"network"` // +kubebuilder:validation:Optional CommitHistory []*CommitHistory `json:"commitHistory"` + // +kubebuilder:validation:Optional + Phase DevboxPhase `json:"phase"` } // +kubebuilder:object:root=true @@ -158,6 +175,7 @@ type DevboxStatus struct { // +kubebuilder:printcolumn:name="PodPhase",type="string",JSONPath=".status.podPhase" // +kubebuilder:printcolumn:name="NetworkType",type="string",JSONPath=".status.network.type" // +kubebuilder:printcolumn:name="NodePort",type="integer",JSONPath=".status.network.nodePort" +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase" // Devbox is the Schema for the devboxes API type Devbox struct { diff --git a/controllers/devbox/config/crd/bases/devbox.sealos.io_devboxes.yaml b/controllers/devbox/config/crd/bases/devbox.sealos.io_devboxes.yaml index 8244b5e8b8d..26ff39819b5 100644 --- a/controllers/devbox/config/crd/bases/devbox.sealos.io_devboxes.yaml +++ b/controllers/devbox/config/crd/bases/devbox.sealos.io_devboxes.yaml @@ -44,6 +44,9 @@ spec: - jsonPath: .status.network.nodePort name: NodePort type: integer + - jsonPath: .status.phase + name: Phase + type: string name: v1alpha1 schema: openAPIV3Schema: @@ -2762,6 +2765,8 @@ spec: required: - type type: object + phase: + type: string podPhase: description: PodPhase is a label for the condition of a pod at the current time. diff --git a/controllers/devbox/deploy/manifests/deploy.yaml.tmpl b/controllers/devbox/deploy/manifests/deploy.yaml.tmpl index 3bb02f4ae30..827483b0e65 100644 --- a/controllers/devbox/deploy/manifests/deploy.yaml.tmpl +++ b/controllers/devbox/deploy/manifests/deploy.yaml.tmpl @@ -52,6 +52,9 @@ spec: - jsonPath: .status.network.nodePort name: NodePort type: integer + - jsonPath: .status.phase + name: Phase + type: string name: v1alpha1 schema: openAPIV3Schema: @@ -2770,6 +2773,8 @@ spec: required: - type type: object + phase: + type: string podPhase: description: PodPhase is a label for the condition of a pod at the current time. diff --git a/controllers/devbox/internal/controller/devbox_controller.go b/controllers/devbox/internal/controller/devbox_controller.go index c79f2fa7cc6..d180b50f803 100644 --- a/controllers/devbox/internal/controller/devbox_controller.go +++ b/controllers/devbox/internal/controller/devbox_controller.go @@ -195,6 +195,12 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D // only one pod is allowed, if more than one pod found, return error if len(podList.Items) > 1 { logger.Error(fmt.Errorf("more than one pod found"), "more than one pod found") + devbox.Status.Phase = devboxv1alpha1.DevboxPhaseError + err := r.Status().Update(ctx, devbox) + if err != nil { + logger.Error(err, "update devbox phase failed") + return err + } return fmt.Errorf("more than one pod found") } @@ -231,6 +237,12 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D if len(podList.Items) == 0 { if err := r.Create(ctx, expectPod); err != nil { logger.Error(err, "create pod failed") + devbox.Status.Phase = devboxv1alpha1.DevboxPhaseError + err := r.Status().Update(ctx, devbox) + if err != nil { + logger.Error(err, "update devbox phase failed") + return err + } return err } // add next commit history to status @@ -268,6 +280,12 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D logger.Info("expect pod", "pod", expectPod.Name, "pod spec", expectPod.Spec) _ = r.Delete(ctx, &podList.Items[0]) } + devbox.Status.Phase = devboxv1alpha1.DevboxPhasePending + err := r.Status().Update(ctx, devbox) + if err != nil { + logger.Error(err, "update devbox phase failed") + return err + } case corev1.PodRunning: //if pod is running,check pod need restart if !helper.CheckPodConsistency(expectPod, &podList.Items[0]) { @@ -276,6 +294,12 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D logger.Info("expect pod", "pod", expectPod.Name, "pod spec", expectPod.Spec) _ = r.Delete(ctx, &podList.Items[0]) } + devbox.Status.Phase = devboxv1alpha1.DevboxPhaseRunning + err = r.Status().Update(ctx, devbox) + if err != nil { + logger.Error(err, "update devbox phase failed") + return err + } return r.updateDevboxCommitHistory(ctx, devbox, &podList.Items[0]) case corev1.PodSucceeded: if controllerutil.RemoveFinalizer(&podList.Items[0], FinalizerName) { @@ -290,16 +314,33 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D case corev1.PodFailed: // we can't find the reason of failure, we assume the commit status is failed // todo maybe use pod condition to get the reason of failure and update commit history status to failed by pod name + devbox.Status.Phase = devboxv1alpha1.DevboxPhaseError + err = r.Status().Update(ctx, devbox) + if err != nil { + logger.Error(err, "update devbox phase failed") + return err + } return r.updateDevboxCommitHistory(ctx, devbox, &podList.Items[0]) } } case devboxv1alpha1.DevboxStateStopped: // check pod status, if no pod found, do nothing if len(podList.Items) == 0 { + devbox.Status.Phase = devboxv1alpha1.DevboxPhaseStopped + err = r.Status().Update(ctx, devbox) + if err != nil { + logger.Error(err, "update devbox phase failed") + } return nil } // if pod found, remove finalizer and delete pod if len(podList.Items) == 1 { + devbox.Status.Phase = devboxv1alpha1.DevboxPhaseStopping + err := r.Status().Update(ctx, devbox) + if err != nil { + logger.Error(err, "update devbox phase failed") + return err + } // remove finalizer and delete pod if controllerutil.RemoveFinalizer(&podList.Items[0], FinalizerName) { if err := r.Update(ctx, &podList.Items[0]); err != nil { @@ -308,6 +349,11 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D } } _ = r.Delete(ctx, &podList.Items[0]) + devbox.Status.Phase = devboxv1alpha1.DevboxPhaseStopped + err = r.Status().Update(ctx, devbox) + if err != nil { + logger.Error(err, "update devbox phase failed") + } return r.updateDevboxCommitHistory(ctx, devbox, &podList.Items[0]) } }