package controller import ( "context" policyv1 "k8s.io/api/policy/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" terdutv1alpha1 "git.ryuvia.com/niklas/terdut-operator/api/v1alpha1" ) // reconcilePodDisruptionBudget creates/updates the PodDisruptionBudget // spec.pod.disruptionBudget asks for, or deletes a previously-created one // when the field has been cleared -- the one conditionally-created child // object in this controller (Deployment/Service are unconditional). Owned // by srv, same plain-OwnerReference shape as Deployment/Service (DESIGN.md // ยง7): same namespace, GC handles it, no finalizer needed. func (r *TerdutServerReconciler) reconcilePodDisruptionBudget(ctx context.Context, srv *terdutv1alpha1.TerdutServer) error { pdb := &policyv1.PodDisruptionBudget{ObjectMeta: metav1.ObjectMeta{Name: srv.Name, Namespace: srv.Namespace}} spec := srv.Spec.Pod.DisruptionBudget if spec == nil { if err := r.Delete(ctx, pdb); err != nil && !apierrors.IsNotFound(err) { return err } return nil } _, err := controllerutil.CreateOrUpdate(ctx, r.Client, pdb, func() error { pdb.Spec.Selector = &metav1.LabelSelector{MatchLabels: labelsFor(srv)} pdb.Spec.MinAvailable = spec.MinAvailable pdb.Spec.MaxUnavailable = spec.MaxUnavailable return controllerutil.SetControllerReference(srv, pdb, r.Scheme) }) return err }