Skip to content

Commit

Permalink
fix devbox phase generate. (#5120)
Browse files Browse the repository at this point in the history
  • Loading branch information
lingdie authored Sep 28, 2024
1 parent d3ba17b commit 22d9a13
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 36 deletions.
3 changes: 3 additions & 0 deletions controllers/devbox/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ go.work
*.swp
*.swo
*~

# ignore deploy.yaml
deploy/manifests/deploy.yaml
6 changes: 3 additions & 3 deletions controllers/devbox/api/v1alpha1/devbox_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,16 @@ const (
DevboxPhasePending DevboxPhase = "Pending"
//DevboxPhaseStopped means Devbox is stop and stopped success
DevboxPhaseStopped DevboxPhase = "Stopped"
//DevboxPhaseStopping means Devbox is stop and not stopped success
//DevboxPhaseStopping means Devbox is stopping
DevboxPhaseStopping DevboxPhase = "Stopping"
//DevboxPhaseError means Devbox is error
DevboxPhaseError DevboxPhase = "Error"
//DevboxPhaseUnknown means Devbox is unknown
DevboxPhaseUnknown DevboxPhase = "Unknown"
)

// DevboxStatus defines the observed state of Devbox
type DevboxStatus struct {
// +kubebuilder:validation:Optional
DevboxPodPhase corev1.PodPhase `json:"podPhase"`
// +kubebuilder:validation:Optional
Network NetworkStatus `json:"network"`
// +kubebuilder:validation:Optional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2848,10 +2848,6 @@ spec:
type: object
phase:
type: string
podPhase:
description: PodPhase is a label for the condition of a pod at the
current time.
type: string
state:
description: |-
ContainerState holds a possible state of container.
Expand Down
6 changes: 1 addition & 5 deletions controllers/devbox/deploy/manifests/deploy.yaml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2856,10 +2856,6 @@ spec:
type: object
phase:
type: string
podPhase:
description: PodPhase is a label for the condition of a pod at the
current time.
type: string
state:
description: |-
ContainerState holds a possible state of container.
Expand Down Expand Up @@ -5639,7 +5635,7 @@ metadata:
name: devbox-controller-manager
namespace: devbox-system
spec:
replicas: 1
replicas: 2
selector:
matchLabels:
control-plane: controller-manager
Expand Down
35 changes: 12 additions & 23 deletions controllers/devbox/internal/controller/devbox_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,17 @@ func (r *DevboxReconciler) syncSecret(ctx context.Context, devbox *devboxv1alpha

func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.Devbox, recLabels map[string]string) error {
logger := log.FromContext(ctx)

var podList corev1.PodList
if err := r.List(ctx, &podList, client.InNamespace(devbox.Namespace), client.MatchingLabels(recLabels)); err != nil {
return err
}
// only one pod is allowed, if more than one pod found, return error
if len(podList.Items) > 1 {
return fmt.Errorf("more than one pod found")
}
logger.Info("pod list", "length", len(podList.Items))

// update devbox status after pod is created or updated
defer func() {
if err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
Expand All @@ -214,6 +225,7 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D
// update devbox status with latestDevbox status
logger.Info("updating devbox status")
logger.Info("merge commit history", "devbox", devbox.Status.CommitHistory, "latestDevbox", latestDevbox.Status.CommitHistory)
devbox.Status.Phase = helper.GenerateDevboxPhase(devbox, podList)
helper.UpdateDevboxStatus(devbox, latestDevbox)
return r.Status().Update(ctx, latestDevbox)
}); err != nil {
Expand All @@ -225,17 +237,6 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D
r.Recorder.Eventf(devbox, corev1.EventTypeNormal, "Sync pod success", "Sync pod success")
}()

var podList corev1.PodList
if err := r.List(ctx, &podList, client.InNamespace(devbox.Namespace), client.MatchingLabels(recLabels)); err != nil {
return err
}
// only one pod is allowed, if more than one pod found, return error
if len(podList.Items) > 1 {
devbox.Status.Phase = devboxv1alpha1.DevboxPhaseError
return fmt.Errorf("more than one pod found")
}
logger.Info("pod list", "length", len(podList.Items))

switch devbox.Spec.State {
case devboxv1alpha1.DevboxStateRunning:
runtimecr, err := r.getRuntime(ctx, devbox)
Expand All @@ -249,14 +250,11 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D
case 0:
logger.Info("create pod")
logger.Info("next commit history", "commit", nextCommitHistory)
devbox.Status.Phase = devboxv1alpha1.DevboxPhasePending
return r.createPod(ctx, devbox, expectPod, nextCommitHistory)
case 1:
pod := &podList.Items[0]
devbox.Status.DevboxPodPhase = pod.Status.Phase
// check pod container size, if it is 0, it means the pod is not running, return an error
if len(pod.Status.ContainerStatuses) == 0 {
devbox.Status.Phase = devboxv1alpha1.DevboxPhasePending
return fmt.Errorf("pod container size is 0")
}
devbox.Status.State = pod.Status.ContainerStatuses[0].State
Expand All @@ -275,32 +273,26 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D
case corev1.PodPending, corev1.PodRunning:
// pod is running or pending, do nothing here
logger.Info("pod is running or pending")
devbox.Status.Phase = devboxv1alpha1.DevboxPhaseRunning
// update commit history status by pod status
helper.UpdateCommitHistory(devbox, pod, false)
return nil
case corev1.PodFailed, corev1.PodSucceeded:
// pod failed or succeeded, we need delete pod and remove finalizer
devbox.Status.Phase = devboxv1alpha1.DevboxPhaseStopped
logger.Info("pod failed or succeeded, recreate pod")
return r.deletePod(ctx, devbox, pod)
}
case false:
// pod not match expectations, delete pod anyway
logger.Info("pod not match expectations, recreate pod")
devbox.Status.Phase = devboxv1alpha1.DevboxPhasePending
return r.deletePod(ctx, devbox, pod)
}
}
case devboxv1alpha1.DevboxStateStopped:
switch len(podList.Items) {
case 0:
// update devbox status to stopped, no pod found, do nothing
devbox.Status.Phase = devboxv1alpha1.DevboxPhaseStopped
return nil
case 1:
pod := &podList.Items[0]
devbox.Status.DevboxPodPhase = pod.Status.Phase
// update state to empty since devbox is stopped
devbox.Status.State = corev1.ContainerState{}
// update commit predicated status by pod status, this should be done once find a pod
Expand All @@ -309,7 +301,6 @@ func (r *DevboxReconciler) syncPod(ctx context.Context, devbox *devboxv1alpha1.D
if !pod.DeletionTimestamp.IsZero() {
return r.handlePodDeleted(ctx, devbox, pod)
}
devbox.Status.Phase = devboxv1alpha1.DevboxPhaseStopped
// we need delete pod because devbox state is stopped
// we don't care about the pod status, just delete it
return r.deletePod(ctx, devbox, pod)
Expand Down Expand Up @@ -422,7 +413,6 @@ func (r *DevboxReconciler) createPod(ctx context.Context, devbox *devboxv1alpha1
nextCommitHistory.PredicatedStatus = devboxv1alpha1.CommitStatusPending
if err := r.Create(ctx, expectPod); err != nil {
logger.Error(err, "create pod failed")
devbox.Status.Phase = devboxv1alpha1.DevboxPhaseError
return err
}
devbox.Status.CommitHistory = append(devbox.Status.CommitHistory, nextCommitHistory)
Expand All @@ -439,7 +429,6 @@ func (r *DevboxReconciler) deletePod(ctx context.Context, devbox *devboxv1alpha1
}
if err := r.Delete(ctx, pod); err != nil {
logger.Error(err, "delete pod failed")
devbox.Status.Phase = devboxv1alpha1.DevboxPhaseError
return err
}
// update commit history status because pod has been deleted
Expand Down
27 changes: 26 additions & 1 deletion controllers/devbox/internal/controller/helper/devbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,32 @@ func GeneratePodAnnotations(devbox *devboxv1alpha1.Devbox, runtime *devboxv1alph
return annotations
}

func GenerateDevboxPhase(devbox *devboxv1alpha1.Devbox, podList corev1.PodList) devboxv1alpha1.DevboxPhase {
if len(podList.Items) > 1 {
return devboxv1alpha1.DevboxPhaseError
}
switch devbox.Spec.State {
case devboxv1alpha1.DevboxStateRunning:
if len(podList.Items) == 0 {
return devboxv1alpha1.DevboxPhasePending
}
switch podList.Items[0].Status.Phase {
case corev1.PodFailed, corev1.PodSucceeded:
return devboxv1alpha1.DevboxPhaseStopped
case corev1.PodPending:
return devboxv1alpha1.DevboxPhasePending
case corev1.PodRunning:
return devboxv1alpha1.DevboxPhaseRunning
}
case devboxv1alpha1.DevboxStateStopped:
if len(podList.Items) == 0 {
return devboxv1alpha1.DevboxPhaseStopped
}
return devboxv1alpha1.DevboxPhaseStopping
}
return devboxv1alpha1.DevboxPhaseUnknown
}

func MergeCommitHistory(devbox *devboxv1alpha1.Devbox, latestDevbox *devboxv1alpha1.Devbox) []*devboxv1alpha1.CommitHistory {
res := make([]*devboxv1alpha1.CommitHistory, 0)
historyMap := make(map[string]*devboxv1alpha1.CommitHistory)
Expand Down Expand Up @@ -127,7 +153,6 @@ func UpdatePredicatedCommitStatus(devbox *devboxv1alpha1.Devbox, pod *corev1.Pod
// TODO: move this function to devbox types.go
func UpdateDevboxStatus(current, latest *devboxv1alpha1.Devbox) {
latest.Status.Phase = current.Status.Phase
latest.Status.DevboxPodPhase = current.Status.DevboxPodPhase
latest.Status.State = current.Status.State
latest.Status.LastTerminationState = current.Status.LastTerminationState
latest.Status.CommitHistory = MergeCommitHistory(current, latest)
Expand Down

0 comments on commit 22d9a13

Please sign in to comment.