feat(lineage-webhook): inject schedulerName for tenant scheduling

When a namespace carries the scheduling.cozystack.io/class label,
the webhook injects schedulerName=cozystack-scheduler and the
scheduler.cozystack.io/scheduling-class annotation into every Pod.
This covers all workloads in the tenant namespace regardless of
whether the operator CRD supports schedulerName natively.

Assisted-By: Claude AI
Signed-off-by: Kirill Ilin <stitch14@yandex.ru>
This commit is contained in:
Kirill Ilin 2026-03-15 22:27:35 +05:00
parent 6046a31e8c
commit 1024ee7607
No known key found for this signature in database
GPG key ID: E902D8B383F7675E

View file

@ -8,11 +8,13 @@ import (
"strings"
"github.com/cozystack/cozystack/pkg/lineage"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
@ -31,6 +33,11 @@ const (
ManagerGroupKey = "apps.cozystack.io/application.group"
ManagerKindKey = "apps.cozystack.io/application.kind"
ManagerNameKey = "apps.cozystack.io/application.name"
// Scheduling constants
SchedulingClassLabel = "scheduling.cozystack.io/class"
SchedulingClassAnnotation = "scheduler.cozystack.io/scheduling-class"
CozystackSchedulerName = "cozystack-scheduler"
)
// getResourceSelectors returns the appropriate ApplicationDefinitionResources for a given GroupKind
@ -115,6 +122,11 @@ func (h *LineageControllerWebhook) Handle(ctx context.Context, req admission.Req
h.applyLabels(obj, labels)
if err := h.applySchedulingClass(ctx, obj, req.Namespace); err != nil {
logger.Error(err, "error applying scheduling class")
return admission.Errored(500, fmt.Errorf("error applying scheduling class: %w", err))
}
mutated, err := json.Marshal(obj)
if err != nil {
return admission.Errored(500, fmt.Errorf("marshal mutated pod: %w", err))
@ -185,6 +197,37 @@ func (h *LineageControllerWebhook) applyLabels(o *unstructured.Unstructured, lab
o.SetLabels(existing)
}
// applySchedulingClass injects schedulerName and scheduling-class annotation
// into Pods whose namespace carries the scheduling.cozystack.io/class label.
func (h *LineageControllerWebhook) applySchedulingClass(ctx context.Context, obj *unstructured.Unstructured, namespace string) error {
if obj.GetKind() != "Pod" {
return nil
}
ns := &corev1.Namespace{}
if err := h.Get(ctx, client.ObjectKey{Name: namespace}, ns); err != nil {
return fmt.Errorf("getting namespace %s: %w", namespace, err)
}
schedulingClass, ok := ns.Labels[SchedulingClassLabel]
if !ok || schedulingClass == "" {
return nil
}
if err := unstructured.SetNestedField(obj.Object, CozystackSchedulerName, "spec", "schedulerName"); err != nil {
return fmt.Errorf("setting schedulerName: %w", err)
}
annotations := obj.GetAnnotations()
if annotations == nil {
annotations = make(map[string]string)
}
annotations[SchedulingClassAnnotation] = schedulingClass
obj.SetAnnotations(annotations)
return nil
}
func (h *LineageControllerWebhook) decodeUnstructured(req admission.Request, out *unstructured.Unstructured) error {
if h.decoder != nil {
if err := h.decoder.Decode(req, out); err == nil {