fix(gateway): allow explicit parentRefs for kube-apiserver TLSRoute (#1074)

Previously, when Kamaji created TLSRoutes for the kube-apiserver and
konnectivity, it automatically set the parentRefs `port` and `sectionName`,
overriding any user-provided values via TCP spec. This prevented users
from targeting specific Gateway listeners.

This change allows users to explicitly define parentRefs for the
kube-apiserver TLSRoute through `TCP.spec.controlPlane.gateway.parentRefs`.

The konnectivity TLSRoute behavior remains unchanged.

Signed-off-by: Parth Yadav <parth@coredge.io>
This commit is contained in:
Parth Yadav
2026-02-18 18:45:23 +01:00
committed by GitHub
parent 13a3aa70f5
commit cc8a8e14fd
11 changed files with 200 additions and 253 deletions
-1
View File
@@ -155,7 +155,6 @@ type IngressSpec struct {
}
// GatewaySpec defines the options for the Gateway which will expose API Server of the Tenant Control Plane.
// +kubebuilder:validation:XValidation:rule="!has(self.parentRefs) || size(self.parentRefs) == 0 || self.parentRefs.all(ref, !has(ref.port) && !has(ref.sectionName))",message="parentRefs must not specify port or sectionName, these are set automatically by Kamaji"
type GatewaySpec struct {
// AdditionalMetadata to add Labels and Annotations support.
AdditionalMetadata AdditionalMetadata `json:"additionalMetadata,omitempty"`
@@ -6896,9 +6896,6 @@ versions:
type: object
type: array
type: object
x-kubernetes-validations:
- message: parentRefs must not specify port or sectionName, these are set automatically by Kamaji
rule: '!has(self.parentRefs) || size(self.parentRefs) == 0 || self.parentRefs.all(ref, !has(ref.port) && !has(ref.sectionName))'
ingress:
description: Defining the options for an Optional Ingress which will expose API Server of the Tenant Control Plane
properties:
@@ -6904,9 +6904,6 @@ spec:
type: object
type: array
type: object
x-kubernetes-validations:
- message: parentRefs must not specify port or sectionName, these are set automatically by Kamaji
rule: '!has(self.parentRefs) || size(self.parentRefs) == 0 || self.parentRefs.all(ref, !has(ref.port) && !has(ref.sectionName))'
ingress:
description: Defining the options for an Optional Ingress which will expose API Server of the Tenant Control Plane
properties:
+130 -112
View File
@@ -1,106 +1,34 @@
# Gateway API Support
# Gateway API
Kamaji provides built-in support for the [Gateway API](https://gateway-api.sigs.k8s.io/), allowing you to expose Tenant Control Planes using TLSRoute resources with SNI-based routing. This enables hostname-based routing to multiple Tenant Control Planes through a single Gateway resource, reducing the need for dedicated LoadBalancer services.
Kamaji provides built-in support for the [Gateway API](https://gateway-api.sigs.k8s.io/), allowing Tenant Control Planes to be exposed as SNI-based addresses/urls. This eliminates the need for a dedicated LoadBalancer IP per TCP. A single Gateway resource can be used for multiple Tenant Control Planes and provide access to them with hostname-based routing (like `https://mycluster.xyz.com:6443`).
## Overview
You can configure Gateway in Tenant Control Plane via `tcp.spec.controlPlane.gateway`, Kamaji will automatically create a `TLSRoute` resource with corresponding spec. To make this configuration work, you need to ensure `gateway` exists (is created by you) and `tcp.spec.controlPlane.gateway` points to your gateway.
Gateway API support in Kamaji automatically creates and manages TLSRoute resources for your Tenant Control Planes. When you configure a Gateway for a Tenant Control Plane, Kamaji automatically creates TLSRoutes for the Control Plane API Server. If konnectivity is enabled, a separate TLSRoute is created for it. Both TLSRoutes use the same hostname and Gateway resource, but route to different ports(listeners) using port-based routing and semantic `sectionName` values.
We will cover a few examples below on how this is done.
Therefore, the target `Gateway` resource must have right listener configurations (see the Gateway [example section](#gateway-resource-setup) below).
## How It Works
When you configure `spec.controlPlane.gateway` in a TenantControlPlane resource, Kamaji automatically:
1. **Creates a TLSRoute for the control plane** that routes for port 6443 (or `spec.networkProfile.port`) with sectionName `"kube-apiserver"`
2. **Creates a TLSRoute for Konnectivity** (if konnectivity addon is enabled) that routes for port 8132 (or `spec.addons.konnectivity.server.port`) with sectionName `"konnectivity-server"`
Both TLSRoutes:
- Use the same hostname from `spec.controlPlane.gateway.hostname`
- Reference the same parent Gateway resource via `parentRefs`
- The `port` and `sectionName` fields are set automatically by Kamaji
- Route to the appropriate Tenant Control Plane service
The Gateway resource must have listeners configured for both ports (6443 and 8132) to support both routes.
## Prerequisites
Before using Gateway API support, ensure:
Before using Gateway API mode, please ensure:
1. **Gateway API CRDs are installed** in your cluster (Required CRDs: `GatewayClass`, `Gateway`, `TLSRoute`)
2. **A Gateway resource exists** with appropriate listeners configured:
- At minimum, listeners for ports 6443 (control plane) and 8132 (Konnectivity)
- TLS protocol with Passthrough mode
- Hostname pattern matching your Tenant Control Plane hostnames
2. **A Gateway resource exists** with appropriate configuration (see examples in this guide):
- Listeners for kube-apiserver.
- Use TLS protocol with Passthrough mode
- Hostname (or Hostname pattern) matching your Tenant Control Plane hostname
3. **DNS is configured** to resolve your hostnames to the Gateway's external address
3. (optional) **DNS is configured** to resolve hostnames (or hostname pattern) to the Gateway's LoadBalancer IP address. (This is needed for worker nodes to join, for testing we will use host entries in `/etc/hosts` for this guide)
4. **Gateway controller is running** (e.g., Envoy Gateway, Istio Gateway, etc.)
## Configuration
To replicate the guide below, please install [Envoy Gateway](https://gateway.envoyproxy.io/docs/tasks/quickstart/).
### TenantControlPlane Gateway Configuration
Next, create a gateway resource:
Enable Gateway API mode by setting the `spec.controlPlane.gateway` field in your TenantControlPlane resource:
#### Gateway Resource Setup
```yaml
apiVersion: kamaji.clastix.io/v1alpha1
kind: TenantControlPlane
metadata:
name: tcp-1
spec:
controlPlane:
# ... gateway configuration:
gateway:
hostname: "tcp1.cluster.dev"
parentRefs:
- name: gateway
namespace: default
additionalMetadata:
labels:
environment: production
annotations:
example.com/custom: "value"
# ... rest of the spec
deployment:
replicas: 1
service:
serviceType: ClusterIP
dataStore: default
kubernetes:
version: v1.29.0
kubelet:
cgroupfs: systemd
networkProfile:
port: 6443
certSANs:
- "c11.cluster.dev" # make sure to set this.
addons:
coreDNS: {}
kubeProxy: {}
konnectivity: {}
```
**Required fields:**
- `hostname`: The hostname that will be used for routing (must match Gateway listener hostname pattern)
- `parentRefs`: Array of Gateway references (name and namespace)
**Optional fields:**
- `additionalMetadata.labels`: Custom labels to add to TLSRoute resources
- `additionalMetadata.annotations`: Custom annotations to add to TLSRoute resources
!!! warning "Port and sectionName are set automatically"
Do not specify `port` or `sectionName` in `parentRefs`. Kamaji automatically sets these fields in TLSRoutes.
### Gateway Resource Setup
Your Gateway resource must have listeners configured for both the control plane and Konnectivity ports. Here's an example Gateway configuration:
Your Gateway resource must have listeners configured for the control plane. Here's an example Gateway configuration:
```yaml
apiVersion: gateway.networking.k8s.io/v1
@@ -130,27 +58,94 @@ spec:
kind: TLSRoute
namespaces:
from: All
```
The above gateway is configured with envoy gateway controller. You can achieve the same results with any other gateway controller that supports `TLSRoutes` and TLS passthrough mode.
The rest of this guide focuses on TCP.
## TenantControlPlane Gateway Configuration
Enable Gateway API mode by setting the `spec.controlPlane.gateway` field in your TenantControlPlane resource:
```yaml
apiVersion: kamaji.clastix.io/v1alpha1
kind: TenantControlPlane
metadata:
name: tcp-1
spec:
controlPlane:
# ... gateway configuration:
gateway:
hostname: "tcp1.cluster.dev"
parentRefs:
- name: gateway
namespace: default
sectionName: kube-apiserver
port: 6443
additionalMetadata:
labels:
environment: production
annotations:
example.com/custom: "value"
# ... rest of the spec
deployment:
replicas: 1
service:
serviceType: ClusterIP
dataStore: default
kubernetes:
version: v1.29.0
kubelet:
cgroupfs: systemd
networkProfile:
port: 6443
certSANs:
- "tcp1.cluster.dev" # make sure to set this.
addons:
coreDNS: {}
kubeProxy: {}
# if konnectivity addon is enabled:
- name: konnectivity-server
port: 8132
protocol: TLS
hostname: 'tcp1.cluster.dev'
tls:
mode: Passthrough
allowedRoutes:
kinds:
- group: gateway.networking.k8s.io
kind: TLSRoute
namespaces:
from: All
```
**Required fields:**
## Multiple Tenant Control Planes
- `hostname`: The hostname that will be used for routing (must match Gateway listener hostname pattern)
- `parentRefs`: Array of Gateway references
You can use the same Gateway resource for multiple Tenant Control Planes by using different hostnames:
**Optional fields:**
- `additionalMetadata.labels`: Custom labels to add to TLSRoute resources
- `additionalMetadata.annotations`: Custom annotations to add to TLSRoute resources
!!! info
### Verify
From our kubectl client machine / remote machines we can access the cluster above with the hostname.
**Step 1:** Fetch load balancer IP of the gateway.
`kubectl get gateway gateway -n default -o jsonpath='{.status.addresses[0].value}'`
**Step 2:** Add host entries in `/etc/hosts` with the above hostname and gateway LB IP.
`echo "<LB_IP> tcp1.cluster.dev" | sudo tee -a /etc/hosts`
**Step 3:** Fetch kubeconfig of tcp cluster.
`kubectl get secrets tcp-1-admin-kubeconfig -o jsonpath='{.data.admin\.conf}' | base64 -d > kubeconfig`
**Step 4:** Test connectivity:
`kubectl --kubeconfig kubeconfig cluster-info`
### Multiple Tenant Control Planes
We can use the same Gateway resource for multiple Tenant Control Planes by using different hostnames per tenant cluster.
Let us extend the above example for multiple tenant control planes behind single gateway (and LB IP).
```yaml
# Gateway with wildcard hostname
@@ -160,10 +155,13 @@ metadata:
name: gateway
spec:
listeners:
- hostname: '*.cluster.dev'
name: kube-apiserver
- name: kube-apiserver
port: 6443
# ...
# note: we changed to wildcard hostname pattern matching
# for cluster.dev
hostname: '*.cluster.dev'
# ...
---
# Tenant Control Plane 1
apiVersion: kamaji.clastix.io/v1alpha1
@@ -194,17 +192,37 @@ spec:
# ...
```
Each Tenant Control Plane will get its own TLSRoutes with the respective hostnames, all routing through the same Gateway resource.
Each Tenant Control Plane needs to use a different hostname. For each TCP, Kamaji creates a `TLSRoutes` resource with the respective hostnames, all `TLSRoutes` routing through the same Gateway resource.
You can check the Gateway status in the TenantControlPlane:
```bash
kubectl get tenantcontrolplane tcp-1 -o yaml
### Konnectivity
If konnectivity addon is enabled, Kamaji creates a separate TLSRoute for it. But this is hardcoded with the listener name `konnectivity-server` and port `8132`. All gateways mentioned in `spec.controlPlane.gateway.parentRefs` must contain a listener with the same configuration for the given hostname. Below is example configuration:
```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gateway
namespace: default
spec:
gatewayClassName: envoy-gw-class
listeners:
- ...
- ...
- name: konnectivity-server
port: 8132
protocol: TLS
hostname: 'tcp1.cluster.dev'
tls:
mode: Passthrough
allowedRoutes:
kinds:
- group: gateway.networking.k8s.io
kind: TLSRoute
namespaces:
from: All
```
Look for the `status.kubernetesResources.gateway` and `status.addons.konnectivity.gateway` fields.
## Additional Resources
- [Gateway API Documentation](https://gateway-api.sigs.k8s.io/)
+32 -1
View File
@@ -48,7 +48,9 @@ var _ = Describe("Deploy a TenantControlPlane with Gateway API and Konnectivity"
},
GatewayParentRefs: []gatewayv1.ParentReference{
{
Name: "test-gateway",
Name: "test-gateway",
Port: pointer.To(gatewayv1.PortNumber(6443)),
SectionName: pointer.To(gatewayv1.SectionName("cp-listener")),
},
},
},
@@ -96,6 +98,35 @@ var _ = Describe("Deploy a TenantControlPlane with Gateway API and Konnectivity"
StatusMustEqualTo(tcp, kamajiv1alpha1.VersionReady)
})
It("Should create control plane TLSRoute preserving user-provided parentRef fields", func() {
Eventually(func() error {
route := &gatewayv1alpha2.TLSRoute{}
if err := k8sClient.Get(context.Background(), types.NamespacedName{
Name: tcp.Name,
Namespace: tcp.Namespace,
}, route); err != nil {
return err
}
if len(route.Spec.ParentRefs) == 0 {
return fmt.Errorf("parentRefs is empty")
}
if route.Spec.ParentRefs[0].SectionName == nil {
return fmt.Errorf("sectionName is nil")
}
if *route.Spec.ParentRefs[0].SectionName != gatewayv1.SectionName("cp-listener") {
return fmt.Errorf("expected sectionName 'cp-listener', got '%s'", *route.Spec.ParentRefs[0].SectionName)
}
if route.Spec.ParentRefs[0].Port == nil {
return fmt.Errorf("port is nil")
}
if *route.Spec.ParentRefs[0].Port != gatewayv1.PortNumber(6443) {
return fmt.Errorf("expected port 6443, got '%d'", *route.Spec.ParentRefs[0].Port)
}
return nil
}).WithTimeout(time.Minute).Should(Succeed())
})
It("Should create Konnectivity TLSRoute with correct sectionName", func() {
Eventually(func() error {
route := &gatewayv1alpha2.TLSRoute{}
+12 -4
View File
@@ -48,7 +48,9 @@ var _ = Describe("Deploy a TenantControlPlane with Gateway API", func() {
},
GatewayParentRefs: []gatewayv1.ParentReference{
{
Name: "test-gateway",
Name: "test-gateway",
Port: pointer.To(gatewayv1.PortNumber(6443)),
SectionName: pointer.To(gatewayv1.SectionName("cp-listener")),
},
},
},
@@ -90,7 +92,7 @@ var _ = Describe("Deploy a TenantControlPlane with Gateway API", func() {
StatusMustEqualTo(tcp, kamajiv1alpha1.VersionReady)
})
It("Should create control plane TLSRoute with correct sectionName", func() {
It("Should create control plane TLSRoute preserving user-provided parentRef fields", func() {
Eventually(func() error {
route := &gatewayv1alpha2.TLSRoute{}
// TODO: Check ownership.
@@ -106,8 +108,14 @@ var _ = Describe("Deploy a TenantControlPlane with Gateway API", func() {
if route.Spec.ParentRefs[0].SectionName == nil {
return fmt.Errorf("sectionName is nil")
}
if *route.Spec.ParentRefs[0].SectionName != gatewayv1.SectionName("kube-apiserver") {
return fmt.Errorf("expected sectionName 'kube-apiserver', got '%s'", *route.Spec.ParentRefs[0].SectionName)
if *route.Spec.ParentRefs[0].SectionName != gatewayv1.SectionName("cp-listener") {
return fmt.Errorf("expected sectionName 'cp-listener', got '%s'", *route.Spec.ParentRefs[0].SectionName)
}
if route.Spec.ParentRefs[0].Port == nil {
return fmt.Errorf("port is nil")
}
if *route.Spec.ParentRefs[0].Port != gatewayv1.PortNumber(6443) {
return fmt.Errorf("expected port 6443, got '%d'", *route.Spec.ParentRefs[0].Port)
}
return nil
+2 -2
View File
@@ -212,7 +212,7 @@ func ScaleTenantControlPlane(tcp *kamajiv1alpha1.TenantControlPlane, replicas in
Expect(err).To(Succeed())
}
// CreateGatewayWithListeners creates a Gateway with both kube-apiserver and konnectivity-server listeners.
// CreateGatewayWithListeners creates a Gateway with control plane and konnectivity-server listeners.
func CreateGatewayWithListeners(gatewayName, namespace, gatewayClassName, hostname string) {
GinkgoHelper()
gateway := &gatewayv1.Gateway{
@@ -224,7 +224,7 @@ func CreateGatewayWithListeners(gatewayName, namespace, gatewayClassName, hostna
GatewayClassName: gatewayv1.ObjectName(gatewayClassName),
Listeners: []gatewayv1.Listener{
{
Name: "kube-apiserver",
Name: "cp-listener",
Port: 6443,
Protocol: gatewayv1.TLSProtocolType,
Hostname: pointer.To(gatewayv1.Hostname(hostname)),
+4 -5
View File
@@ -150,6 +150,10 @@ func (r *KubernetesGatewayResource) mutate(tcp *kamajiv1alpha1.TenantControlPlan
tcp.Spec.ControlPlane.Gateway.AdditionalMetadata.Annotations)
r.resource.SetAnnotations(annotations)
if tcp.Spec.ControlPlane.Gateway.GatewayParentRefs != nil {
r.resource.Spec.ParentRefs = tcp.Spec.ControlPlane.Gateway.GatewayParentRefs
}
serviceName := gatewayv1alpha2.ObjectName(tcp.Status.Kubernetes.Service.Name)
servicePort := tcp.Status.Kubernetes.Service.Port
@@ -157,11 +161,6 @@ func (r *KubernetesGatewayResource) mutate(tcp *kamajiv1alpha1.TenantControlPlan
return fmt.Errorf("service not ready, cannot create TLSRoute")
}
if tcp.Spec.ControlPlane.Gateway.GatewayParentRefs != nil {
// Copy parentRefs and explicitly set port and sectionName fields
r.resource.Spec.ParentRefs = NewParentRefsSpecWithPortAndSection(tcp.Spec.ControlPlane.Gateway.GatewayParentRefs, servicePort, "kube-apiserver")
}
rule := gatewayv1alpha2.TLSRouteRule{
BackendRefs: []gatewayv1alpha2.BackendRef{
{
+6 -108
View File
@@ -102,30 +102,6 @@ var _ = Describe("KubernetesGatewayResource", func() {
Expect(shouldUpdate).To(BeTrue())
})
It("should set port and sectionName in parentRefs, overriding any user-provided values", func() {
customPort := gatewayv1.PortNumber(9999)
customSectionName := gatewayv1.SectionName("custom")
tcp.Spec.ControlPlane.Gateway.GatewayParentRefs[0].Port = &customPort
tcp.Spec.ControlPlane.Gateway.GatewayParentRefs[0].SectionName = &customSectionName
err := resource.Define(ctx, tcp)
Expect(err).NotTo(HaveOccurred())
_, err = resource.CreateOrUpdate(ctx, tcp)
Expect(err).NotTo(HaveOccurred())
route := &gatewayv1alpha2.TLSRoute{}
err = resource.Client.Get(ctx, client.ObjectKey{Name: tcp.Name, Namespace: tcp.Namespace}, route)
Expect(err).NotTo(HaveOccurred())
Expect(route.Spec.ParentRefs).To(HaveLen(1))
Expect(route.Spec.ParentRefs[0].Port).NotTo(BeNil())
Expect(*route.Spec.ParentRefs[0].Port).To(Equal(tcp.Status.Kubernetes.Service.Port))
Expect(*route.Spec.ParentRefs[0].Port).NotTo(Equal(customPort))
Expect(route.Spec.ParentRefs[0].SectionName).NotTo(BeNil())
Expect(*route.Spec.ParentRefs[0].SectionName).To(Equal(gatewayv1.SectionName("kube-apiserver")))
Expect(*route.Spec.ParentRefs[0].SectionName).NotTo(Equal(customSectionName))
})
It("should handle multiple parentRefs correctly", func() {
namespace := gatewayv1.Namespace("default")
tcp.Spec.ControlPlane.Gateway.GatewayParentRefs = []gatewayv1alpha2.ParentReference{
@@ -149,13 +125,12 @@ var _ = Describe("KubernetesGatewayResource", func() {
err = resource.Client.Get(ctx, client.ObjectKey{Name: tcp.Name, Namespace: tcp.Namespace}, route)
Expect(err).NotTo(HaveOccurred())
Expect(route.Spec.ParentRefs).To(HaveLen(2))
for i := range route.Spec.ParentRefs {
Expect(route.Spec.ParentRefs[i].Port).NotTo(BeNil())
Expect(*route.Spec.ParentRefs[i].Port).To(Equal(tcp.Status.Kubernetes.Service.Port))
Expect(route.Spec.ParentRefs[i].SectionName).NotTo(BeNil())
Expect(*route.Spec.ParentRefs[i].SectionName).To(Equal(gatewayv1.SectionName("kube-apiserver")))
}
Expect(route.Spec.ParentRefs[0].Name).To(Equal(gatewayv1alpha2.ObjectName("test-gateway-1")))
Expect(route.Spec.ParentRefs[0].Namespace).NotTo(BeNil())
Expect(*route.Spec.ParentRefs[0].Namespace).To(Equal(namespace))
Expect(route.Spec.ParentRefs[1].Name).To(Equal(gatewayv1alpha2.ObjectName("test-gateway-2")))
Expect(route.Spec.ParentRefs[1].Namespace).NotTo(BeNil())
Expect(*route.Spec.ParentRefs[1].Namespace).To(Equal(namespace))
})
})
@@ -292,81 +267,4 @@ var _ = Describe("KubernetesGatewayResource", func() {
Expect(listener.Port).To(Equal(gatewayv1.PortNumber(80)))
})
})
Describe("NewParentRefsSpecWithPortAndSection", func() {
var (
parentRefs []gatewayv1.ParentReference
testPort int32
testSectionName string
)
BeforeEach(func() {
namespace := gatewayv1.Namespace("default")
namespace2 := gatewayv1.Namespace("other")
testPort = int32(6443)
testSectionName = "kube-apiserver"
originalPort := gatewayv1.PortNumber(9999)
originalSectionName := gatewayv1.SectionName("original")
parentRefs = []gatewayv1.ParentReference{
{
Name: "test-gateway-1",
Namespace: &namespace,
Port: &originalPort,
SectionName: &originalSectionName,
},
{
Name: "test-gateway-2",
Namespace: &namespace2,
},
}
})
It("should create copy of parentRefs with port and sectionName set", func() {
result := resources.NewParentRefsSpecWithPortAndSection(parentRefs, testPort, testSectionName)
Expect(result).To(HaveLen(2))
for i := range result {
Expect(result[i].Name).To(Equal(parentRefs[i].Name))
Expect(result[i].Namespace).To(Equal(parentRefs[i].Namespace))
Expect(result[i].Port).NotTo(BeNil())
Expect(*result[i].Port).To(Equal(testPort))
Expect(result[i].SectionName).NotTo(BeNil())
Expect(*result[i].SectionName).To(Equal(gatewayv1.SectionName(testSectionName)))
}
})
It("should not modify original parentRefs", func() {
// Store original values for verification
originalFirstPort := parentRefs[0].Port
originalFirstSectionName := parentRefs[0].SectionName
originalSecondPort := parentRefs[1].Port
originalSecondSectionName := parentRefs[1].SectionName
result := resources.NewParentRefsSpecWithPortAndSection(parentRefs, testPort, testSectionName)
// Original should remain unchanged
Expect(parentRefs[0].Port).To(Equal(originalFirstPort))
Expect(parentRefs[0].SectionName).To(Equal(originalFirstSectionName))
Expect(parentRefs[1].Port).To(Equal(originalSecondPort))
Expect(parentRefs[1].SectionName).To(Equal(originalSecondSectionName))
// Result should have new values
Expect(result[0].Port).NotTo(BeNil())
Expect(*result[0].Port).To(Equal(testPort))
Expect(result[0].SectionName).NotTo(BeNil())
Expect(*result[0].SectionName).To(Equal(gatewayv1.SectionName(testSectionName)))
Expect(result[1].Port).NotTo(BeNil())
Expect(*result[1].Port).To(Equal(testPort))
Expect(result[1].SectionName).NotTo(BeNil())
Expect(*result[1].SectionName).To(Equal(gatewayv1.SectionName(testSectionName)))
})
It("should handle empty parentRefs slice", func() {
parentRefs = []gatewayv1.ParentReference{}
result := resources.NewParentRefsSpecWithPortAndSection(parentRefs, testPort, testSectionName)
Expect(result).To(BeEmpty())
})
})
})
-13
View File
@@ -226,16 +226,3 @@ func BuildGatewayAccessPointsStatus(ctx context.Context, c client.Client, route
return accessPoints, nil
}
// NewParentRefsSpecWithPortAndSection creates a copy of parentRefs with port and sectionName set for each reference.
func NewParentRefsSpecWithPortAndSection(parentRefs []gatewayv1.ParentReference, port int32, sectionName string) []gatewayv1.ParentReference {
result := make([]gatewayv1.ParentReference, len(parentRefs))
sectionNamePtr := gatewayv1.SectionName(sectionName)
for i, parentRef := range parentRefs {
result[i] = *parentRef.DeepCopy()
result[i].Port = &port
result[i].SectionName = &sectionNamePtr
}
return result
}
@@ -182,7 +182,7 @@ func (r *KubernetesKonnectivityGatewayResource) mutate(tcp *kamajiv1alpha1.Tenan
if tcp.Spec.ControlPlane.Gateway.GatewayParentRefs == nil {
return fmt.Errorf("control plane gateway parentRefs are not specified")
}
r.resource.Spec.ParentRefs = resources.NewParentRefsSpecWithPortAndSection(tcp.Spec.ControlPlane.Gateway.GatewayParentRefs, servicePort, "konnectivity-server")
r.resource.Spec.ParentRefs = newParentRefsSpecWithPortAndSection(tcp.Spec.ControlPlane.Gateway.GatewayParentRefs, servicePort, "konnectivity-server")
rule := gatewayv1alpha2.TLSRouteRule{
BackendRefs: []gatewayv1alpha2.BackendRef{
@@ -230,3 +230,16 @@ func (r *KubernetesKonnectivityGatewayResource) CreateOrUpdate(ctx context.Conte
func (r *KubernetesKonnectivityGatewayResource) GetName() string {
return "konnectivity_gateway_routes"
}
// newParentRefsSpecWithPortAndSection creates a copy of parentRefs with port and sectionName set for each reference.
func newParentRefsSpecWithPortAndSection(parentRefs []gatewayv1.ParentReference, port int32, sectionName string) []gatewayv1.ParentReference {
result := make([]gatewayv1.ParentReference, len(parentRefs))
sectionNamePtr := gatewayv1.SectionName(sectionName)
for i, parentRef := range parentRefs {
result[i] = *parentRef.DeepCopy()
result[i].Port = &port
result[i].SectionName = &sectionNamePtr
}
return result
}