controller

package
v0.16.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 4, 2026 License: Apache-2.0 Imports: 35 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ScheduleState tracks the current state of each schedule (0=Down, 1=Up, 2=WarmingUp)
	ScheduleState = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "lightsout_schedule_state",
			Help: "Current state of schedule (0=Down, 1=Up, 2=WarmingUp)",
		},
		[]string{"schedule"},
	)

	// NextTransitionSeconds tracks seconds until next state transition
	NextTransitionSeconds = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "lightsout_next_transition_seconds",
			Help: "Seconds until next state transition",
		},
		[]string{"schedule", "transition_type"},
	)

	// ScalingOperationsTotal counts scaling operations performed
	ScalingOperationsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "lightsout_scaling_operations_total",
			Help: "Total number of scaling operations performed",
		},
		[]string{"schedule", "namespace", "workload_type", "operation"},
	)

	// ScalingErrorsTotal counts scaling errors
	ScalingErrorsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "lightsout_scaling_errors_total",
			Help: "Total number of scaling errors",
		},
		[]string{"schedule", "namespace", "workload_type"},
	)

	// ManagedWorkloads tracks the number of workloads being managed
	ManagedWorkloads = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "lightsout_managed_workloads",
			Help: "Number of workloads being managed",
		},
		[]string{"schedule", "workload_type"},
	)

	// ScalingBatchesTotal counts batches processed during scaling
	ScalingBatchesTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "lightsout_scaling_batches_total",
			Help: "Total number of batches processed during scaling",
		},
		[]string{"schedule", "direction"},
	)

	// ScalingWorkloadsProcessed counts workloads processed during scaling
	ScalingWorkloadsProcessed = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "lightsout_scaling_workloads_processed_total",
			Help: "Total workloads processed during scaling",
		},
		[]string{"schedule", "direction", "result"},
	)

	// ScalingDurationSeconds tracks time taken to complete scaling operations
	ScalingDurationSeconds = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Name:    "lightsout_scaling_duration_seconds",
			Help:    "Time taken to complete all scaling operations",
			Buckets: []float64{1, 5, 10, 30, 60, 120, 300, 600},
		},
		[]string{"schedule", "direction"},
	)

	// LastReconcileTime tracks the unix timestamp of the last successful reconciliation
	LastReconcileTime = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "lightsout_last_reconcile_timestamp_seconds",
			Help: "Unix timestamp of last successful reconciliation",
		},
		[]string{"schedule"},
	)
)
View Source
var SystemNamespaces = map[string]bool{
	"kube-system":     true,
	"kube-public":     true,
	"kube-node-lease": true,
}

SystemNamespaces that should always be excluded

Functions

func CheckWorkloadReadiness added in v0.12.0

func CheckWorkloadReadiness(ctx context.Context, c client.Client, namespace string) (bool, error)

CheckWorkloadReadiness reports whether all active Deployments and StatefulSets in the given namespace have all their desired replicas ready. Workloads with spec.replicas == 0 are skipped (intentionally at zero). All workloads in the namespace are checked so that the warming-up signal accurately reflects the full health of the namespace, not just the subset lightsout scaled up.

func ClearPeriodCache

func ClearPeriodCache()

ClearPeriodCache clears the period calculation cache (useful for testing)

func CompleteArgoCDWarmup added in v0.12.0

func CompleteArgoCDWarmup(ctx context.Context, c client.Client, app *unstructured.Unstructured) error

CompleteArgoCDWarmup removes the lightsout state labels and the warming-up-since annotation from an ArgoCD Application. Workload labels are already cleaned up by the scaler at upscale time, so only the ArgoCD app needs updating here.

func CompleteFluxWarmup added in v0.16.0

func CompleteFluxWarmup(ctx context.Context, c client.Client, obj *unstructured.Unstructured) error

func DiscoverArgoCDApps added in v0.11.0

func DiscoverArgoCDApps(
	ctx context.Context,
	c client.Client,
	cfg *lightsoutv1alpha1.ArgoCDConfig,
	targetNamespaces []string,
) ([]unstructured.Unstructured, error)

DiscoverArgoCDApps lists ArgoCD Application CRDs from the configured namespace and returns those whose spec.destination.namespace matches any of the target namespaces.

func DiscoverFluxResources added in v0.16.0

func DiscoverFluxResources(
	ctx context.Context,
	c client.Client,
	cfg *lightsoutv1alpha1.FluxCDConfig,
	targetNamespaces []string,
) ([]unstructured.Unstructured, error)

func DiscoverNamespaces

func DiscoverNamespaces(ctx context.Context, c client.Client, spec *lightsoutv1alpha1.LightsOutScheduleSpec) ([]string, error)

DiscoverNamespaces returns the list of namespaces to manage based on the schedule spec

func FilterNamespacesWithLocalSchedules added in v0.14.0

func FilterNamespacesWithLocalSchedules(ctx context.Context, c client.Client, namespaces []string) ([]string, error)

FilterNamespacesWithLocalSchedules removes any namespace from the list that contains at least one LightsOutNamespaceSchedule. This implements the "namespace schedule overrides global schedule" precedence rule.

func LabelArgoCDAppDown added in v0.11.0

func LabelArgoCDAppDown(ctx context.Context, c client.Client, app *unstructured.Unstructured, scheduleName string) (bool, error)

LabelArgoCDAppDown adds lightsout labels to an ArgoCD Application to signal downscale state. Returns true if the operation was skipped (already labeled or managed by different schedule).

func LabelArgoCDAppWarmingUp added in v0.12.0

func LabelArgoCDAppWarmingUp(ctx context.Context, c client.Client, app *unstructured.Unstructured, scheduleName string, now time.Time) (bool, error)

LabelArgoCDAppWarmingUp transitions an ArgoCD Application from the down state to the warming-up state. It sets state=warming-up and records the current time in the warming-up-since annotation so the timeout can be enforced on subsequent reconciles. Returns true if the operation was skipped.

func PatchHPAForDownscale added in v0.15.0

func PatchHPAForDownscale(ctx context.Context, c client.Client, hpaList *unstructured.UnstructuredList, namespace, kind, name, scheduleName string) error

PatchHPAForDownscale finds the HPA targeting the given workload in hpaList, stores the original spec.behavior.scaleUp.selectPolicy as an annotation, stamps managed-by, and sets spec.behavior.scaleUp.selectPolicy=Disabled to prevent the HPA from fighting back when the deployment is scaled to 0. hpaList must be fetched with listHPAs before calling, pass nil to skip HPA handling. Call this before the workload's replica write on downscale. Errors are returned to the caller, the caller treats them as non-fatal.

func RemoveArgoCDAppLabels added in v0.11.0

func RemoveArgoCDAppLabels(ctx context.Context, c client.Client, app *unstructured.Unstructured, scheduleName string) (bool, error)

RemoveArgoCDAppLabels removes lightsout labels from an ArgoCD Application on upscale. Returns true if the operation was skipped (not managed or managed by different schedule).

func RestoreHPA added in v0.15.0

func RestoreHPA(ctx context.Context, c client.Client, hpaList *unstructured.UnstructuredList, namespace, kind, name, scheduleName string) error

RestoreHPA finds the HPA targeting the given workload in hpaList, reads the original spec.behavior.scaleUp.selectPolicy from the annotation, restores it, and removes all lightsout annotations. hpaList must be fetched with listHPAs before calling, pass nil to skip HPA handling. Call this after the replica write succeeds on upscale. Errors are returned to the caller, the caller treats them as non-fatal.

func ResumeFluxResource added in v0.16.0

func ResumeFluxResource(
	ctx context.Context,
	c client.Client,
	obj *unstructured.Unstructured,
	scheduleName string,
) (bool, error)

ResumeFluxResource removes lightsout labels/annotations and sets spec.suspend=false. Used during finalizer cleanup. Returns true if skipped (not managed by this schedule).

func ShouldExcludeWorkload

func ShouldExcludeWorkload(workloadLabels map[string]string, excludeSelector *metav1.LabelSelector) (bool, error)

ShouldExcludeWorkload checks if a workload should be excluded based on labels

func SuspendFluxResource added in v0.16.0

func SuspendFluxResource(
	ctx context.Context,
	c client.Client,
	obj *unstructured.Unstructured,
	scheduleName string,
) (bool, error)

func TransitionFluxResourceToWarmingUp added in v0.16.0

func TransitionFluxResourceToWarmingUp(
	ctx context.Context,
	c client.Client,
	obj *unstructured.Unstructured,
	scheduleName string,
	now time.Time,
) (bool, error)

Types

type LightsOutNamespaceScheduleReconciler added in v0.14.0

type LightsOutNamespaceScheduleReconciler struct {
	client.Client
	Scheme   *runtime.Scheme
	Recorder events.EventRecorder
	// TimeFunc returns the current time. If nil, time.Now() is used.
	// This is primarily used for testing to inject a fixed time.
	TimeFunc func() time.Time
}

LightsOutNamespaceScheduleReconciler reconciles a LightsOutNamespaceSchedule object

func (*LightsOutNamespaceScheduleReconciler) Reconcile added in v0.14.0

func (*LightsOutNamespaceScheduleReconciler) SetupWithManager added in v0.14.0

func (r *LightsOutNamespaceScheduleReconciler) SetupWithManager(mgr ctrl.Manager) error

SetupWithManager sets up the controller with the Manager.

type LightsOutScheduleReconciler

type LightsOutScheduleReconciler struct {
	client.Client
	Scheme   *runtime.Scheme
	Recorder events.EventRecorder
	// TimeFunc returns the current time. If nil, time.Now() is used.
	// This is primarily used for testing to inject a fixed time.
	TimeFunc func() time.Time
}

LightsOutScheduleReconciler reconciles a LightsOutSchedule object

func (*LightsOutScheduleReconciler) Reconcile

func (*LightsOutScheduleReconciler) SetupWithManager

func (r *LightsOutScheduleReconciler) SetupWithManager(mgr ctrl.Manager) error

SetupWithManager sets up the controller with the Manager.

type PeriodResult

type PeriodResult struct {
	State         string
	NextUpscale   time.Time
	NextDownscale time.Time
	LastUpscale   time.Time
	LastDownscale time.Time
}

PeriodResult contains the calculated period state and transition times

func CalculatePeriod

func CalculatePeriod(upscaleCron, downscaleCron, timezone string, now time.Time) (*PeriodResult, error)

CalculatePeriod determines if we're in an up or down period based on cron expressions

type ScaleResult

type ScaleResult struct {
	Skipped       bool
	SkipReason    string
	PreviousValue string
	NewValue      string
}

ScaleResult contains the result of a scaling operation

func ScaleCronJob

func ScaleCronJob(ctx context.Context, c client.Client, cj *batchv1.CronJob, scheduleName string, scaleUp bool) (*ScaleResult, error)

ScaleCronJob suspends or resumes a cronjob based on the period

func ScaleDeployment

func ScaleDeployment(ctx context.Context, c client.Client, deploy *appsv1.Deployment, scheduleName string, scaleUp bool, hpaList *unstructured.UnstructuredList) (*ScaleResult, error)

ScaleDeployment scales a deployment up or down based on the period. scaleUp=true means restore to original replicas, scaleUp=false means scale to 0. hpaList is the pre-fetched HPA list for the deployment's namespace; pass nil to skip HPA handling.

func ScaleStatefulSet

func ScaleStatefulSet(ctx context.Context, c client.Client, sts *appsv1.StatefulSet, scheduleName string, scaleUp bool, hpaList *unstructured.UnstructuredList) (*ScaleResult, error)

ScaleStatefulSet scales a statefulset up or down based on the period. scaleUp=true means restore to original replicas, scaleUp=false means scale to 0. hpaList is the pre-fetched HPA list for the statefulset's namespace, pass nil to skip HPA handling.

type Workload

type Workload struct {
	Type        WorkloadType
	Name        string
	Namespace   string
	Deployment  *appsv1.Deployment
	StatefulSet *appsv1.StatefulSet
	CronJob     *batchv1.CronJob
}

Workload represents a single workload to be scaled

func WorkloadFromCronJob

func WorkloadFromCronJob(c *batchv1.CronJob) Workload

WorkloadFromCronJob creates a Workload from a CronJob

func WorkloadFromDeployment

func WorkloadFromDeployment(d *appsv1.Deployment) Workload

WorkloadFromDeployment creates a Workload from a Deployment

func WorkloadFromStatefulSet

func WorkloadFromStatefulSet(s *appsv1.StatefulSet) Workload

WorkloadFromStatefulSet creates a Workload from a StatefulSet

type WorkloadType

type WorkloadType string

WorkloadType identifies the type of Kubernetes workload

const (
	WorkloadTypeDeployment  WorkloadType = "Deployment"
	WorkloadTypeStatefulSet WorkloadType = "StatefulSet"
	WorkloadTypeCronJob     WorkloadType = "CronJob"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL