From 02b68dc518140608099f4d7f2edccaa98c310ea6 Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Mon, 20 Apr 2026 16:01:42 -0700 Subject: [PATCH] Add PodDisruptionBudgetOverride API type --- api/v1/installation_types.go | 6 ++ api/v1/poddisruptionbudget_types.go | 45 +++++++++++ api/v1/zz_generated.deepcopy.go | 37 ++++++++++ .../operator.tigera.io_installations.yaml | 74 +++++++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 api/v1/poddisruptionbudget_types.go diff --git a/api/v1/installation_types.go b/api/v1/installation_types.go index b64227400d..b4f124b3ce 100644 --- a/api/v1/installation_types.go +++ b/api/v1/installation_types.go @@ -201,6 +201,12 @@ type InstallationSpec struct { // +optional TyphaDeployment *TyphaDeployment `json:"typhaDeployment,omitempty"` + // TyphaPodDisruptionBudget configures the PodDisruptionBudget for the calico-typha + // Deployment. Fields left unset fall back to the operator's defaults. The PDB's + // selector is managed by the operator and cannot be overridden. + // +optional + TyphaPodDisruptionBudget *PodDisruptionBudgetOverride `json:"typhaPodDisruptionBudget,omitempty"` + // Deprecated. The CalicoWindowsUpgradeDaemonSet is deprecated and will be removed from the API in the future. // CalicoWindowsUpgradeDaemonSet configures the calico-windows-upgrade DaemonSet. CalicoWindowsUpgradeDaemonSet *CalicoWindowsUpgradeDaemonSet `json:"calicoWindowsUpgradeDaemonSet,omitempty"` diff --git a/api/v1/poddisruptionbudget_types.go b/api/v1/poddisruptionbudget_types.go new file mode 100644 index 0000000000..f8fcd395b0 --- /dev/null +++ b/api/v1/poddisruptionbudget_types.go @@ -0,0 +1,45 @@ +// Copyright (c) 2026 Tigera, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + policyv1 "k8s.io/api/policy/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// PodDisruptionBudgetOverride allows overriding select fields on an operator-managed +// PodDisruptionBudget. The PDB's selector, name, and namespace are managed by the +// operator and cannot be overridden. +// +kubebuilder:validation:XValidation:rule="!(has(self.minAvailable) && has(self.maxUnavailable))",message="minAvailable and maxUnavailable are mutually exclusive" +type PodDisruptionBudgetOverride struct { + // MinAvailable is the minimum number of pods (as an integer or percentage) that + // must remain available during a disruption. Mutually exclusive with MaxUnavailable. + // +optional + MinAvailable *intstr.IntOrString `json:"minAvailable,omitempty"` + + // MaxUnavailable is the maximum number of pods (as an integer or percentage) that + // can be unavailable during a disruption. Mutually exclusive with MinAvailable. + // If neither MinAvailable nor MaxUnavailable is set, the operator applies its + // default (MaxUnavailable=1 for calico-typha). + // +optional + MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"` + + // UnhealthyPodEvictionPolicy defines when unhealthy pods should be considered + // for eviction. Defaults to IfHealthyBudget (the Kubernetes default) when unset. + // See https://kubernetes.io/docs/tasks/run-application/configure-pdb/#unhealthy-pod-eviction-policy. + // +kubebuilder:validation:Enum=IfHealthyBudget;AlwaysAllow + // +optional + UnhealthyPodEvictionPolicy *policyv1.UnhealthyPodEvictionPolicyType `json:"unhealthyPodEvictionPolicy,omitempty"` +} diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 0bade7102c..90c53b7004 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -25,8 +25,10 @@ import ( "github.com/tigera/api/pkg/lib/numorstring" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + policyv1 "k8s.io/api/policy/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -6015,6 +6017,11 @@ func (in *InstallationSpec) DeepCopyInto(out *InstallationSpec) { *out = new(TyphaDeployment) (*in).DeepCopyInto(*out) } + if in.TyphaPodDisruptionBudget != nil { + in, out := &in.TyphaPodDisruptionBudget, &out.TyphaPodDisruptionBudget + *out = new(PodDisruptionBudgetOverride) + (*in).DeepCopyInto(*out) + } if in.CalicoWindowsUpgradeDaemonSet != nil { in, out := &in.CalicoWindowsUpgradeDaemonSet, &out.CalicoWindowsUpgradeDaemonSet *out = new(CalicoWindowsUpgradeDaemonSet) @@ -8500,6 +8507,36 @@ func (in *PathMatch) DeepCopy() *PathMatch { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodDisruptionBudgetOverride) DeepCopyInto(out *PodDisruptionBudgetOverride) { + *out = *in + if in.MinAvailable != nil { + in, out := &in.MinAvailable, &out.MinAvailable + *out = new(intstr.IntOrString) + **out = **in + } + if in.MaxUnavailable != nil { + in, out := &in.MaxUnavailable, &out.MaxUnavailable + *out = new(intstr.IntOrString) + **out = **in + } + if in.UnhealthyPodEvictionPolicy != nil { + in, out := &in.UnhealthyPodEvictionPolicy, &out.UnhealthyPodEvictionPolicy + *out = new(policyv1.UnhealthyPodEvictionPolicyType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodDisruptionBudgetOverride. +func (in *PodDisruptionBudgetOverride) DeepCopy() *PodDisruptionBudgetOverride { + if in == nil { + return nil + } + out := new(PodDisruptionBudgetOverride) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PolicyRecommendation) DeepCopyInto(out *PolicyRecommendation) { *out = *in diff --git a/pkg/imports/crds/operator/operator.tigera.io_installations.yaml b/pkg/imports/crds/operator/operator.tigera.io_installations.yaml index 3e6fa9d2ea..dd633ef490 100644 --- a/pkg/imports/crds/operator/operator.tigera.io_installations.yaml +++ b/pkg/imports/crds/operator/operator.tigera.io_installations.yaml @@ -9177,6 +9177,43 @@ spec: prometheus metrics on. By default, metrics are not enabled. format: int32 type: integer + typhaPodDisruptionBudget: + description: |- + TyphaPodDisruptionBudget configures the PodDisruptionBudget for the calico-typha + Deployment. Fields left unset fall back to the operator's defaults. The PDB's + selector is managed by the operator and cannot be overridden. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: |- + MaxUnavailable is the maximum number of pods (as an integer or percentage) that + can be unavailable during a disruption. Mutually exclusive with MinAvailable. + If neither MinAvailable nor MaxUnavailable is set, the operator applies its + default (MaxUnavailable=1 for calico-typha). + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: |- + MinAvailable is the minimum number of pods (as an integer or percentage) that + must remain available during a disruption. Mutually exclusive with MaxUnavailable. + x-kubernetes-int-or-string: true + unhealthyPodEvictionPolicy: + description: |- + UnhealthyPodEvictionPolicy defines when unhealthy pods should be considered + for eviction. Defaults to IfHealthyBudget (the Kubernetes default) when unset. + See https://kubernetes.io/docs/tasks/run-application/configure-pdb/#unhealthy-pod-eviction-policy. + enum: + - IfHealthyBudget + - AlwaysAllow + type: string + type: object + x-kubernetes-validations: + - message: minAvailable and maxUnavailable are mutually exclusive + rule: "!(has(self.minAvailable) && has(self.maxUnavailable))" variant: description: |- Variant is the product to install - one of Calico or CalicoEnterprise. @@ -18529,6 +18566,43 @@ spec: serves prometheus metrics on. By default, metrics are not enabled. format: int32 type: integer + typhaPodDisruptionBudget: + description: |- + TyphaPodDisruptionBudget configures the PodDisruptionBudget for the calico-typha + Deployment. Fields left unset fall back to the operator's defaults. The PDB's + selector is managed by the operator and cannot be overridden. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: |- + MaxUnavailable is the maximum number of pods (as an integer or percentage) that + can be unavailable during a disruption. Mutually exclusive with MinAvailable. + If neither MinAvailable nor MaxUnavailable is set, the operator applies its + default (MaxUnavailable=1 for calico-typha). + x-kubernetes-int-or-string: true + minAvailable: + anyOf: + - type: integer + - type: string + description: |- + MinAvailable is the minimum number of pods (as an integer or percentage) that + must remain available during a disruption. Mutually exclusive with MaxUnavailable. + x-kubernetes-int-or-string: true + unhealthyPodEvictionPolicy: + description: |- + UnhealthyPodEvictionPolicy defines when unhealthy pods should be considered + for eviction. Defaults to IfHealthyBudget (the Kubernetes default) when unset. + See https://kubernetes.io/docs/tasks/run-application/configure-pdb/#unhealthy-pod-eviction-policy. + enum: + - IfHealthyBudget + - AlwaysAllow + type: string + type: object + x-kubernetes-validations: + - message: minAvailable and maxUnavailable are mutually exclusive + rule: "!(has(self.minAvailable) && has(self.maxUnavailable))" variant: description: |- Variant is the product to install - one of Calico or CalicoEnterprise.