diff --git a/api/v1alpha1/rolloutscaledown_types.go b/api/v1alpha1/rolloutscaledown_types.go index 883657e..0bfacb6 100755 --- a/api/v1alpha1/rolloutscaledown_types.go +++ b/api/v1alpha1/rolloutscaledown_types.go @@ -23,18 +23,31 @@ import ( // RolloutScaleDownSpec defines the desired state of RolloutScaleDown type RolloutScaleDownSpec struct { // Foo is an example field of RolloutScaleDown. Edit rolloutscaledown_types.go to remove/update - TargetRollout string `json:"targetRollout,omitempty"` - TerminatePerOnce int `json:"terminatePerOnce,1"` - CoolTimeSeconds int `json:"coolTimeSeconds,30"` + TargetRollout string `json:"targetRollout,omitempty"` + // +kubebuilder:default=1 + TerminatePerOnce int `json:"terminatePerOnce"` + // +kubebuilder:default=30 + CoolTimeSeconds int `json:"coolTimeSeconds"` } // RolloutScaleDownStatus defines the observed state of RolloutScaleDown type RolloutScaleDownStatus struct { + // +optional LastScaleDownTime metav1.Time `json:"lastScaleDownTime,omitempty"` + // +kubebuilder:default=Healthy + Phase RolloutScaleDownPhase `json:"phase,omitempty"` } -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status +type RolloutScaleDownPhase string + +const ( + RolloutScaleDownPhaseHealthy RolloutScaleDownPhase = "Healthy" + RolloutScaleDownPhaseScaling RolloutScaleDownPhase = "Scaling" +) + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="RolloutScaleDown deployment phase" // RolloutScaleDown is the Schema for the rolloutscaledowns API type RolloutScaleDown struct { @@ -45,7 +58,7 @@ type RolloutScaleDown struct { Status RolloutScaleDownStatus `json:"status,omitempty"` } -//+kubebuilder:object:root=true +// +kubebuilder:object:root=true // RolloutScaleDownList contains a list of RolloutScaleDown type RolloutScaleDownList struct { diff --git a/config/crd/bases/rollout.ovice.com_rolloutscaledowns.yaml b/config/crd/bases/rollout.ovice.com_rolloutscaledowns.yaml index 60a0942..a5ed4b0 100755 --- a/config/crd/bases/rollout.ovice.com_rolloutscaledowns.yaml +++ b/config/crd/bases/rollout.ovice.com_rolloutscaledowns.yaml @@ -14,7 +14,12 @@ spec: singular: rolloutscaledown scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - description: RolloutScaleDown deployment phase + jsonPath: .status.phase + name: Phase + type: string + name: v1alpha1 schema: openAPIV3Schema: description: RolloutScaleDown is the Schema for the rolloutscaledowns API @@ -40,12 +45,14 @@ spec: description: RolloutScaleDownSpec defines the desired state of RolloutScaleDown properties: coolTimeSeconds: + default: 30 type: integer targetRollout: description: Foo is an example field of RolloutScaleDown. Edit rolloutscaledown_types.go to remove/update type: string terminatePerOnce: + default: 1 type: integer required: - coolTimeSeconds @@ -57,6 +64,9 @@ spec: lastScaleDownTime: format: date-time type: string + phase: + default: Healthy + type: string type: object type: object served: true diff --git a/internal/controller/argorollout_controller.go b/internal/controller/argorollout_controller.go index be40aa8..66427ce 100644 --- a/internal/controller/argorollout_controller.go +++ b/internal/controller/argorollout_controller.go @@ -62,8 +62,25 @@ func (r *ArgoRolloutReconciler) Reconcile(ctx context.Context, req ctrl.Request) } klog.Infof("Target ArgoRollout: %s/%s", argoRollout.Namespace, argoRollout.Name) + if isCompleted(&argoRollout.Status) { klog.V(1).Infof("Rollout is completed: %s/%s", argoRollout.Namespace, argoRollout.Name) + + if argoRollout.Status.Replicas == argoRollout.Status.ReadyReplicas { + if targetScaleDown.Status.Phase != optimizerv1alpha1.RolloutScaleDownPhaseHealthy { + newStatus := targetScaleDown.Status.DeepCopy() + newStatus.Phase = optimizerv1alpha1.RolloutScaleDownPhaseHealthy + targetScaleDown.Status = *newStatus + if err := r.Status().Update(ctx, targetScaleDown); err != nil { + klog.Errorf("Failed to update RolloutScaleDown: %v", err) + return ctrl.Result{}, err + } + klog.Infof("RolloutScaleDown is healthy: %s/%s", targetScaleDown.Namespace, targetScaleDown.Name) + r.Recorder.Eventf(targetScaleDown, corev1.EventTypeNormal, "Healthy", "RolloutScaleDown is healthy") + } + return ctrl.Result{}, nil + } + rsHash := argoRollout.Status.StableRS oldRS := []*appsv1.ReplicaSet{} RSList := &appsv1.ReplicaSetList{} @@ -100,11 +117,20 @@ func (r *ArgoRolloutReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{}, err } if retry > 0 { + if targetScaleDown.Status.Phase != optimizerv1alpha1.RolloutScaleDownPhaseScaling { + newStatus := targetScaleDown.Status.DeepCopy() + newStatus.Phase = optimizerv1alpha1.RolloutScaleDownPhaseScaling + targetScaleDown.Status = *newStatus + if err := r.Status().Update(ctx, targetScaleDown); err != nil { + klog.Errorf("Failed to update RolloutScaleDown: %v", err) + return ctrl.Result{}, err + } + } return ctrl.Result{RequeueAfter: retry, Requeue: true}, nil } - } } + return ctrl.Result{}, nil } @@ -155,6 +181,7 @@ func (r *ArgoRolloutReconciler) scaleDown(ctx context.Context, rs *appsv1.Replic newStatus := scaleDown.Status.DeepCopy() newStatus.LastScaleDownTime = metav1.Now() + newStatus.Phase = optimizerv1alpha1.RolloutScaleDownPhaseScaling scaleDown.Status = *newStatus if err := r.Status().Update(ctx, scaleDown); err != nil { klog.Errorf("Failed to update RolloutScaleDown: %v", err)