diff --git a/api/v1alpha1/tenantcontrolplane_types.go b/api/v1alpha1/tenantcontrolplane_types.go index 8d4da133..bcb6bc4b 100644 --- a/api/v1alpha1/tenantcontrolplane_types.go +++ b/api/v1alpha1/tenantcontrolplane_types.go @@ -19,6 +19,11 @@ type NetworkProfileSpec struct { // to specific networks for security purposes. // Example: {"192.168.1.0/24", "10.0.0.0/8"} LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"` + // Specify the LoadBalancer class in case of multiple load balancer implementations. + // Field supported only for Tenant Control Plane instances exposed using a LoadBalancer Service. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:rule="oldSelf == '' || oldSelf == self",message="LoadBalancerClass can not be changed once set" + LoadBalancerClass *string `json:"loadBalancerClass,omitempty"` // Address where API server of will be exposed. // In case of LoadBalancer Service, this can be empty in order to use the exposed IP provided by the cloud controller manager. Address string `json:"address,omitempty"` @@ -268,6 +273,8 @@ type AddonsSpec struct { // +kubebuilder:validation:XValidation:rule="!has(oldSelf.dataStore) || has(self.dataStore)", message="unsetting the dataStore is not supported" // +kubebuilder:validation:XValidation:rule="!has(oldSelf.dataStoreSchema) || has(self.dataStoreSchema)", message="unsetting the dataStoreSchema is not supported" // +kubebuilder:validation:XValidation:rule="!has(self.networkProfile.loadBalancerSourceRanges) || (size(self.networkProfile.loadBalancerSourceRanges) == 0 || self.controlPlane.service.serviceType == 'LoadBalancer')", message="LoadBalancer source ranges are supported only with LoadBalancer service type" +// +kubebuilder:validation:XValidation:rule="!has(self.networkProfile.loadBalancerClass) || self.controlPlane.service.serviceType == 'LoadBalancer'", message="LoadBalancerClass is supported only with LoadBalancer service type" +// +kubebuilder:validation:XValidation:rule="oldSelf.controlPlane.service.serviceType != self.controlPlane.service.serviceType || (!has(oldSelf.networkProfile.loadBalancerClass) && has(self.networkProfile.loadBalancerClass))",message="LoadBalancerClass can not be unset" type TenantControlPlaneSpec struct { // DataStore allows to specify a DataStore that should be used to store the Kubernetes data for the given Tenant Control Plane. diff --git a/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml b/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml index 8de739fd..27c07ce4 100644 --- a/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml +++ b/charts/kamaji/crds/kamaji.clastix.io_tenantcontrolplanes.yaml @@ -6566,6 +6566,15 @@ spec: items: type: string type: array + loadBalancerClass: + description: |- + Specify the LoadBalancer class in case of multiple load balancer implementations. + Field supported only for Tenant Control Plane instances exposed using a LoadBalancer Service. + minLength: 1 + type: string + x-kubernetes-validations: + - message: LoadBalancerClass can not be changed once set + rule: oldSelf == '' || oldSelf == self loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges restricts the IP ranges that can access @@ -6603,6 +6612,10 @@ spec: rule: '!has(oldSelf.dataStoreSchema) || has(self.dataStoreSchema)' - message: LoadBalancer source ranges are supported only with LoadBalancer service type rule: '!has(self.networkProfile.loadBalancerSourceRanges) || (size(self.networkProfile.loadBalancerSourceRanges) == 0 || self.controlPlane.service.serviceType == ''LoadBalancer'')' + - message: LoadBalancerClass is supported only with LoadBalancer service type + rule: '!has(self.networkProfile.loadBalancerClass) || self.controlPlane.service.serviceType == ''LoadBalancer''' + - message: LoadBalancerClass can not be unset + rule: oldSelf.controlPlane.service.serviceType != self.controlPlane.service.serviceType || (!has(oldSelf.networkProfile.loadBalancerClass) && has(self.networkProfile.loadBalancerClass)) status: description: TenantControlPlaneStatus defines the observed state of TenantControlPlane. properties: diff --git a/docs/content/reference/api.md b/docs/content/reference/api.md index d51d8fcb..24f6a048 100644 --- a/docs/content/reference/api.md +++ b/docs/content/reference/api.md @@ -13943,6 +13943,14 @@ Service CIDR 10.96.0.0/16, the resulting DNS Service IP will be 10.96.0.10 for I for IPv6 from the CIDR 2001:db8:abcd::/64 the resulting DNS Service IP will be 2001:db8:abcd::10.
false + + loadBalancerClass + string + + Specify the LoadBalancer class in case of multiple load balancer implementations. +Field supported only for Tenant Control Plane instances exposed using a LoadBalancer Service.
+ + false loadBalancerSourceRanges []string diff --git a/internal/resources/k8s_service_resource.go b/internal/resources/k8s_service_resource.go index e592f822..f854858f 100644 --- a/internal/resources/k8s_service_resource.go +++ b/internal/resources/k8s_service_resource.go @@ -11,6 +11,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" @@ -102,6 +103,11 @@ func (r *KubernetesServiceResource) mutate(ctx context.Context, tenantControlPla switch tenantControlPlane.Spec.ControlPlane.Service.ServiceType { case kamajiv1alpha1.ServiceTypeLoadBalancer: r.resource.Spec.Type = corev1.ServiceTypeLoadBalancer + + if tenantControlPlane.Spec.NetworkProfile.LoadBalancerClass != nil { + r.resource.Spec.LoadBalancerClass = ptr.To(*tenantControlPlane.Spec.NetworkProfile.LoadBalancerClass) + } + if len(tenantControlPlane.Spec.NetworkProfile.LoadBalancerSourceRanges) > 0 { r.resource.Spec.LoadBalancerSourceRanges = tenantControlPlane.Spec.NetworkProfile.LoadBalancerSourceRanges }