mirror of
https://github.com/stakater/Reloader.git
synced 2026-08-20 12:36:26 +00:00
93 lines
2.9 KiB
Go
93 lines
2.9 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/go-logr/logr"
|
|
"github.com/stakater/Reloader/internal/pkg/config"
|
|
"github.com/stakater/Reloader/internal/pkg/reload"
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
|
ctrl "sigs.k8s.io/controller-runtime"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/predicate"
|
|
)
|
|
|
|
// DeploymentReconciler reconciles Deployment objects to handle pause expiration.
|
|
// This reconciler watches for deployments that were paused by Reloader and
|
|
// unpauses them when the pause period expires.
|
|
type DeploymentReconciler struct {
|
|
client.Client
|
|
Log logr.Logger
|
|
Config *config.Config
|
|
PauseHandler *reload.PauseHandler
|
|
}
|
|
|
|
// Reconcile handles Deployment pause expiration.
|
|
func (r *DeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
|
log := r.Log.WithValues("deployment", req.NamespacedName)
|
|
log.V(1).Info("reconciling deployment", "namespace", req.Namespace, "name", req.Name)
|
|
|
|
var deploy appsv1.Deployment
|
|
if err := r.Get(ctx, req.NamespacedName, &deploy); err != nil {
|
|
if errors.IsNotFound(err) {
|
|
return ctrl.Result{}, nil
|
|
}
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
// Check if this deployment was paused by Reloader
|
|
if !r.PauseHandler.IsPausedByReloader(&deploy) {
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
// Check if pause period has expired
|
|
expired, remainingTime, err := r.PauseHandler.CheckPauseExpired(&deploy)
|
|
if err != nil {
|
|
log.Error(err, "Failed to check pause expiration")
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
if !expired {
|
|
// Still within pause period - requeue to check again
|
|
log.V(1).Info("Deployment pause not yet expired", "remaining", remainingTime)
|
|
return ctrl.Result{RequeueAfter: remainingTime}, nil
|
|
}
|
|
|
|
// Pause period has expired - unpause the deployment
|
|
log.Info("Unpausing deployment after pause period expired")
|
|
r.PauseHandler.ClearPause(&deploy)
|
|
|
|
if err := r.Update(ctx, &deploy, client.FieldOwner(FieldManager)); err != nil {
|
|
log.Error(err, "Failed to unpause deployment")
|
|
return ctrl.Result{}, err
|
|
}
|
|
|
|
return ctrl.Result{}, nil
|
|
}
|
|
|
|
// SetupWithManager sets up the DeploymentReconciler with the manager.
|
|
func (r *DeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|
return ctrl.NewControllerManagedBy(mgr).
|
|
For(&appsv1.Deployment{}).
|
|
WithEventFilter(r.pausedByReloaderPredicate()).
|
|
Complete(r)
|
|
}
|
|
|
|
// pausedByReloaderPredicate returns a predicate that only selects deployments
|
|
// that have been paused by Reloader (have the paused-at annotation).
|
|
func (r *DeploymentReconciler) pausedByReloaderPredicate() predicate.Predicate {
|
|
return predicate.NewPredicateFuncs(
|
|
func(obj client.Object) bool {
|
|
annotations := obj.GetAnnotations()
|
|
if annotations == nil {
|
|
return false
|
|
}
|
|
|
|
// Only process if deployment has our paused-at annotation
|
|
_, hasPausedAt := annotations[r.Config.Annotations.PausedAt]
|
|
return hasPausedAt
|
|
},
|
|
)
|
|
}
|