controllerutils

package
v0.2.0-rc11 Latest Latest
Warning

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

Go to latest
Published: Dec 18, 2025 License: MIT Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const (
	EventTypeNormal  = "Normal"
	EventTypeWarning = "Warning"
)

Event type constants

View Source
const (
	// MaxKubernetesNameLength is the maximum length for Kubernetes resource names
	MaxKubernetesNameLength  = 63
	MaxKubernetesLabelLength = 63
	// DefaultHashLength is the default length of the hash suffix
	DefaultHashLength = 8
)
View Source
const (
	ConditionTypeReady       = "Ready"
	ConditionTypeProgressing = "Progressing"
	ConditionTypeFailure     = "Failure"
	ConditionTypeDiscovered  = "Discovered"
	ConditionTypeCacheWarm   = "CacheWarm"
)

Standard condition types for AIM resources

View Source
const (
	ReasonReconciling      = "Reconciling"
	ReasonAvailable        = "Available"
	ReasonFailed           = "Failed"
	ReasonDiscoveryRunning = "DiscoveryRunning"
	ReasonDiscoveryFailed  = "DiscoveryFailed"
	ReasonDiscovered       = "Discovered"
	ReasonJobPending       = "JobPending"
	ReasonJobFailed        = "JobFailed"
	ReasonJobSucceeded     = "JobSucceeded"
)

Standard condition reasons

Variables

View Source
var (
	LabelValueRegex = regexp.MustCompile(`[^a-z0-9._-]+`)
	// InvalidNameChars matches characters invalid for Kubernetes resource names
	InvalidNameChars = regexp.MustCompile(`[^a-z0-9-]+`)
	// MultiDashes matches multiple consecutive dashes
	MultiDashes = regexp.MustCompile(`-+`)
)

Functions

func AddFinalizer

func AddFinalizer(obj client.Object, finalizer string)

AddFinalizer adds the specified finalizer to the object

func ApplyDesiredState

func ApplyDesiredState(
	ctx context.Context,
	k8sClient client.Client,
	scheme *runtime.Scheme,
	desired []client.Object,
	config ApplyConfig,
) error

ApplyDesiredState applies the desired set of objects via Server-Side Apply (SSA). Objects are applied in deterministic order: by GVK, then namespace, then name.

func CleanAMDGPUName added in v0.1.6

func CleanAMDGPUName(gpuID string) string

func CompareClusterQueues

func CompareClusterQueues(a, b kueuev1beta1.ClusterQueue) bool

func ComparePriorityClasses

func ComparePriorityClasses(a, b kueuev1beta1.WorkloadPriorityClass) bool

func CompareResourceFlavors

func CompareResourceFlavors(a, b kueuev1beta1.ResourceFlavor) bool

func CompareTopologies added in v0.1.6

func CompareTopologies(a, b kueuev1alpha1.Topology) bool

func ConvertKaiwoToKueueClusterQueue

func ConvertKaiwoToKueueClusterQueue(kaiwoQueue kaiwo.ClusterQueue) kueuev1beta1.ClusterQueue

func ConvertKaiwoToKueueResourceFlavor

func ConvertKaiwoToKueueResourceFlavor(kaiwoFlavor kaiwo.ResourceFlavorSpec) kueuev1beta1.ResourceFlavor

func ConvertKaiwoToKueueResourceFlavors

func ConvertKaiwoToKueueResourceFlavors(kaiwoFlavors []kaiwo.ResourceFlavorSpec) []kueuev1beta1.ResourceFlavor

func ConvertKaiwoToKueueSpec added in v0.1.6

func ConvertKaiwoToKueueSpec(in kaiwo.ClusterQueueSpec) kueuev1beta1.ClusterQueueSpec

ConvertKaiwoToKueueSpec converts from Kaiwo's simplified ClusterQueueSpec to the actual Kueue version

func ConvertKaiwoToKueueTopologies added in v0.1.6

func ConvertKaiwoToKueueTopologies(kaiwoTopologies []kaiwo.Topology) []kueuev1alpha1.Topology

func ConvertKaiwoToKueueTopology added in v0.1.6

func ConvertKaiwoToKueueTopology(kaiwoTopology kaiwo.Topology) kueuev1alpha1.Topology

func CreateClusterQueue

func CreateClusterQueue(nodePoolResources map[string]kueuev1beta1.FlavorQuotas, name string, cohort string) kaiwo.ClusterQueue

func CreateDefaultResourceFlavors

func CreateDefaultResourceFlavors(ctx context.Context, c client.Client) ([]kaiwo.ResourceFlavorSpec, map[string]kueuev1beta1.FlavorQuotas, error)

CreateDefaultResourceFlavors goes through all nodes divides them into "flavors" based on capacity. It then adds there labels to the nodes, and returns the result.

func CreateDefaultTopology added in v0.1.6

func CreateDefaultTopology(ctx context.Context, c client.Client) ([]kaiwo.Topology, error)

func CreateLocalQueue

func CreateLocalQueue(ctx context.Context, c client.Client, name string, namespace string) error

CreateLocalQueue creates a LocalQueue in the given namespace.

func EmitEvent

func EmitEvent(recorder record.EventRecorder, obj client.Object, eventType, reason, message string)

EmitEvent emits a Kubernetes event if a recorder is available

func EmitNormalEvent

func EmitNormalEvent(recorder record.EventRecorder, obj client.Object, reason, message string)

EmitNormalEvent emits a Normal type event

func EmitWarningEvent

func EmitWarningEvent(recorder record.EventRecorder, obj client.Object, reason, message string)

EmitWarningEvent emits a Warning type event

func EnsureNamespaceKueueManaged

func EnsureNamespaceKueueManaged(ctx context.Context, k8sClient client.Client, namespaceName string) error

func FindFlavor

func FindFlavor(flavors []kueuev1beta1.ResourceFlavor, name string) (kueuev1beta1.ResourceFlavor, bool)

func FindTopology added in v0.1.6

func FindTopology(topologies []kueuev1alpha1.Topology, name string) (kueuev1alpha1.Topology, bool)

func GenerateDerivedName

func GenerateDerivedName(nameParts []string, hashInputs ...any) (string, error)

GenerateDerivedName creates a deterministic name for a derived resource. It combines multiple name parts with an optional hash suffix, ensuring the result is a valid Kubernetes name (max 63 characters, lowercase alphanumeric and hyphens).

Format:

  • With hash inputs: {part1}-{part2}-...-{partN}-{hash}
  • Without hash inputs: {part1}-{part2}-...-{partN}

If the combined name exceeds 63 characters, the longest part is iteratively truncated until the total length fits. The hash (if present) is never truncated beyond the specified length.

Parameters:

  • nameParts: The parts to combine into the name (e.g., ["my-service", "temp", "cache"]). Must not be empty.
  • hashInputs: Optional values to hash. Can be strings, structs, slices, or maps. Slices and maps are sorted recursively for deterministic hashing. If empty, no hash suffix is added.

Returns:

  • A valid Kubernetes resource name and nil error on success
  • Empty string and error if nameParts is empty

Example:

name, err := GenerateDerivedName([]string{"my-service", "temp"}, "metric=latency", "precision=fp16")
// Returns: "my-service-temp-a1b2c3d4", nil

name, err := GenerateDerivedName([]string{"my-service", "temp-cache"})
// Returns: "my-service-temp-cache", nil (no hash)

name, err := GenerateDerivedName([]string{"my-service", "derived"},
    map[string]string{"metric": "latency", "precision": "fp16"})
// Returns: "my-service-derived-b2c3d4e5", nil (map sorted before hashing)

func GenerateDerivedNameWithHashLength

func GenerateDerivedNameWithHashLength(nameParts []string, hashLength int, hashInputs ...any) (string, error)

GenerateDerivedNameWithHashLength is like GenerateDerivedName but allows specifying hash length.

Parameters:

  • nameParts: The parts to combine into the name. Must not be empty.
  • hashLength: The number of characters to use from the hash (recommended: 6-12). Set to 0 to omit the hash suffix.
  • hashInputs: Variable number of values to hash (any type)

Returns:

  • A valid Kubernetes resource name and nil error on success
  • Empty string and error if nameParts is empty

func HasFinalizer

func HasFinalizer(obj client.Object, finalizer string) bool

HasFinalizer checks if the object has the specified finalizer

func IsNamespaceTerminatingError

func IsNamespaceTerminatingError(err error) bool

IsNamespaceTerminatingError checks if an error is caused by attempting to create resources in a namespace that is being deleted. This is a normal part of cleanup and doesn't need error-level logging.

func LabelNode

func LabelNode(ctx context.Context, c client.Client, nodeName, key, value string) error

func MakeRFC1123Compliant

func MakeRFC1123Compliant(s string) string

MakeRFC1123Compliant converts a string to be RFC 1123 compliant (lowercase, alphanumeric, hyphens, max 63 chars)

func NewCondition

func NewCondition(
	conditionType string,
	status metav1.ConditionStatus,
	reason string,
	message string,
) metav1.Condition

NewCondition creates a new condition with the given parameters

func PatchStatus

func PatchStatus[T ObjectWithStatus[S], S any](
	ctx context.Context,
	k8sClient client.Client,
	obj T,
	originalStatus S,
) error

PatchStatus patches the status subresource if it changed from originalStatus. Sets ObservedGeneration to match metadata.generation. Uses retry logic to handle conflicts when the object is modified between read and update.

This function uses generics to provide type-safe status access. The only reflection used is for setting ObservedGeneration, which is unavoidable without adding methods to every status type.

func Reconcile

func Reconcile[T ObjectWithStatus[S], S any](ctx context.Context, spec ReconcileSpec[T, S]) (ctrl.Result, error)

Reconcile implements the observe → plan → apply → status pattern.

High-level flow: 1. Ensure/Remove Finalizer 2. If deleting → finalize → remove finalizer → patch status → exit 3. Observe (read-only) 4. Short-circuit on observation failure → project error status → return 5. Plan (pure function) 6. Apply (SSA with deterministic ordering) 7. Project Status (from observation + errors) 8. Patch Status once 9. Return with appropriate requeue policy

func ReconcileWithoutStatus

func ReconcileWithoutStatus(ctx context.Context, spec ReconcileWithoutStatusSpec) (ctrl.Result, error)

ReconcileWithoutStatus implements the observe → plan → apply pattern for controllers that maintain derived resources but don't need status updates.

High-level flow: 1. Observe (read-only) 2. Short-circuit on observation failure 3. Plan (pure function) 4. Apply (SSA with deterministic ordering) 5. Return with appropriate requeue policy

func RemoveDuplicateResourceFlavors

func RemoveDuplicateResourceFlavors(flavors []kaiwo.ResourceFlavorSpec) []kaiwo.ResourceFlavorSpec

func RemoveFinalizer

func RemoveFinalizer(obj client.Object, finalizer string)

RemoveFinalizer removes the specified finalizer from the object

func SanitizeLabelValue

func SanitizeLabelValue(s string) (string, error)

SanitizeLabelValue converts a string to a valid Kubernetes label value. Valid label values must: - Be empty or consist of alphanumeric characters, '-', '_' or '.' - Start and end with an alphanumeric character - Be at most 63 characters Returns an error if the sanitized value is empty.

func TaintNode

func TaintNode(ctx context.Context, client client.Client, nodeName string, taint corev1.Taint) error

Types

type ApplyConfig

type ApplyConfig struct {
	// FieldOwner for SSA
	FieldOwner string

	// EnablePruning enables deletion of previously-owned objects not in desired set
	EnablePruning bool

	// InventoryLabels are labels used to track owned objects for pruning
	InventoryLabels map[string]string
}

ApplyConfig configures the SSA apply operation

type ImageParts

type ImageParts struct {
	Registry   string // e.g., "ghcr.io" or "docker.io"
	Repository string // e.g., "silogen/llama-3-8b" (full repository path)
	Name       string // e.g., "llama-3-8b" (just the image name, last component)
	Tag        string // e.g., "v1.2.0" or "abc123" (first 6 chars of digest)
}

func ExtractImageParts

func ExtractImageParts(image string) (ImageParts, error)

type NodeResourceInfo

type NodeResourceInfo struct {
	Name          string
	CPU           int
	Memory        int
	Labels        map[string]string
	Unschedulable bool
}

func GetNodeResources

func GetNodeResources(ctx context.Context, c client.Client) []NodeResourceInfo

type ObjectWithStatus

type ObjectWithStatus[S any] interface {
	client.Object
	GetStatus() *S
}

ObjectWithStatus is a generic constraint for objects that have a typed status accessor. This allows type-safe status access without reflection (except for ObservedGeneration).

type ReconcileErrors

type ReconcileErrors struct {
	ObserveErr  error
	PlanErr     error
	ApplyErr    error
	FinalizeErr error
}

ReconcileErrors captures errors from different reconciliation phases

func (ReconcileErrors) HasError

func (e ReconcileErrors) HasError() bool

HasError returns true if any error is set

type ReconcileResult

type ReconcileResult struct {
	Result ctrl.Result
	Error  error
}

ReconcileResult encapsulates the result of a reconciliation

type ReconcileSpec

type ReconcileSpec[T ObjectWithStatus[S], S any] struct {
	// Client is the Kubernetes client for API operations
	Client client.Client

	// Scheme is the runtime scheme for GVK resolution
	Scheme *runtime.Scheme

	// Object is the resource being reconciled (must be fetched and passed in)
	Object T

	// Recorder is the event recorder for emitting Kubernetes events (optional)
	Recorder record.EventRecorder

	// FinalizerName is the finalizer to add/remove (optional)
	FinalizerName string

	// FieldOwner is the field manager name for SSA (required)
	FieldOwner string

	// ObserveFn gathers current cluster state (read-only).
	// Returns typed observation data and any errors encountered.
	ObserveFn func(ctx context.Context) (observation any, err error)

	// PlanFn computes desired state from spec + observation (pure function).
	// Returns slice of objects to apply via SSA.
	PlanFn func(ctx context.Context, obs any) (desired []client.Object, err error)

	// ProjectFn computes status from observation + reconcile errors.
	// Modifies Object.Status directly. Framework patches if changed.
	ProjectFn func(ctx context.Context, obs any, errs ReconcileErrors) error

	// FinalizeFn performs external cleanup during deletion (optional).
	// Should only interact with external systems, not owned children.
	FinalizeFn func(ctx context.Context, obs any) error
}

ReconcileSpec defines the callback-based reconciliation specification. Controllers provide closures that capture their specific types and logic.

Type parameters:

  • T: The object type being reconciled (must implement ObjectWithStatus[S])
  • S: The status type of the object

type ReconcileWithoutStatusSpec

type ReconcileWithoutStatusSpec struct {
	// Client is the Kubernetes client for API operations
	Client client.Client

	// Scheme is the runtime scheme for GVK resolution
	Scheme *runtime.Scheme

	// FieldOwner is the field manager name for SSA (required)
	FieldOwner string

	// ObserveFn gathers current cluster state (read-only).
	// Returns typed observation data and any errors encountered.
	ObserveFn func(ctx context.Context) (observation any, err error)

	// PlanFn computes desired state from observation (pure function).
	// Returns slice of objects to apply via SSA.
	PlanFn func(ctx context.Context, obs any) (desired []client.Object, err error)
}

ReconcileWithoutStatusSpec defines the reconciliation specification for controllers that don't need status updates (e.g., derived resource controllers).

Jump to

Keyboard shortcuts

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