mirror of
https://github.com/clastix/kamaji.git
synced 2026-02-14 10:00:02 +00:00
This change extends Gateway API support to Konnectivity addons. When `spec.controlPlane.gateway` is configured and Konnectivity addon is enabled, Kamaji automatically creates two TLSRoutes: 1. A Control plane TLSRoute (port 6443, sectionName "kube-apiserver") 2. A Konnectivity TLSRoute (port 8132, sectionName "konnectivity-server") Both routes use the hostname specified in `gateway.hostname` and reference the same Gateway resource via `parentRefs`, with `port` and `sectionName` set automatically by Kamaji. This patch also adds CEL validation to prevent users from specifying `port` or `sectionName` in Gateway `parentRefs`, as these fields are now managed automatically by Kamaji. Signed-off-by: Parth Yadav <parth@coredge.io>
152 lines
4.5 KiB
Go
152 lines
4.5 KiB
Go
// Copyright 2022 Clastix Labs
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package e2e
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
pointer "k8s.io/utils/ptr"
|
|
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
|
|
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
|
|
|
|
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
|
)
|
|
|
|
var _ = Describe("Deploy a TenantControlPlane with Gateway API and Konnectivity", func() {
|
|
var tcp *kamajiv1alpha1.TenantControlPlane
|
|
|
|
JustBeforeEach(func() {
|
|
tcp = &kamajiv1alpha1.TenantControlPlane{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "tcp-konnectivity-gateway",
|
|
Namespace: "default",
|
|
},
|
|
Spec: kamajiv1alpha1.TenantControlPlaneSpec{
|
|
ControlPlane: kamajiv1alpha1.ControlPlane{
|
|
Deployment: kamajiv1alpha1.DeploymentSpec{
|
|
Replicas: pointer.To(int32(1)),
|
|
},
|
|
Service: kamajiv1alpha1.ServiceSpec{
|
|
ServiceType: "ClusterIP",
|
|
},
|
|
Gateway: &kamajiv1alpha1.GatewaySpec{
|
|
Hostname: gatewayv1.Hostname("tcp-gateway-konnectivity.example.com"),
|
|
AdditionalMetadata: kamajiv1alpha1.AdditionalMetadata{
|
|
Labels: map[string]string{
|
|
"test.kamaji.io/gateway": "true",
|
|
},
|
|
Annotations: map[string]string{
|
|
"test.kamaji.io/created-by": "e2e-test",
|
|
},
|
|
},
|
|
GatewayParentRefs: []gatewayv1.ParentReference{
|
|
{
|
|
Name: "test-gateway",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
NetworkProfile: kamajiv1alpha1.NetworkProfileSpec{
|
|
Address: "172.18.0.4",
|
|
},
|
|
Kubernetes: kamajiv1alpha1.KubernetesSpec{
|
|
Version: "v1.28.0",
|
|
Kubelet: kamajiv1alpha1.KubeletSpec{
|
|
CGroupFS: "cgroupfs",
|
|
},
|
|
AdmissionControllers: kamajiv1alpha1.AdmissionControllers{
|
|
"LimitRanger",
|
|
"ResourceQuota",
|
|
},
|
|
},
|
|
Addons: kamajiv1alpha1.AddonsSpec{
|
|
Konnectivity: &kamajiv1alpha1.KonnectivitySpec{
|
|
KonnectivityServerSpec: kamajiv1alpha1.KonnectivityServerSpec{
|
|
Port: 8132,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
Expect(k8sClient.Create(context.Background(), tcp)).NotTo(HaveOccurred())
|
|
})
|
|
|
|
JustAfterEach(func() {
|
|
Expect(k8sClient.Delete(context.Background(), tcp)).Should(Succeed())
|
|
|
|
// Wait for the object to be completely deleted
|
|
Eventually(func() bool {
|
|
err := k8sClient.Get(context.Background(), types.NamespacedName{
|
|
Name: tcp.Name,
|
|
Namespace: tcp.Namespace,
|
|
}, &kamajiv1alpha1.TenantControlPlane{})
|
|
|
|
return err != nil // Returns true when object is not found (deleted)
|
|
}).WithTimeout(time.Minute).Should(BeTrue())
|
|
})
|
|
|
|
It("Should be Ready", func() {
|
|
StatusMustEqualTo(tcp, kamajiv1alpha1.VersionReady)
|
|
})
|
|
|
|
It("Should create Konnectivity TLSRoute with correct sectionName", func() {
|
|
Eventually(func() error {
|
|
route := &gatewayv1alpha2.TLSRoute{}
|
|
if err := k8sClient.Get(context.Background(), types.NamespacedName{
|
|
Name: tcp.Name + "-konnectivity",
|
|
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("konnectivity-server") {
|
|
return fmt.Errorf("expected sectionName 'konnectivity-server', got '%s'", *route.Spec.ParentRefs[0].SectionName)
|
|
}
|
|
|
|
return nil
|
|
}).WithTimeout(time.Minute).Should(Succeed())
|
|
})
|
|
|
|
It("Should use same hostname for both TLSRoutes", func() {
|
|
Eventually(func() error {
|
|
controlPlaneRoute := &gatewayv1alpha2.TLSRoute{}
|
|
if err := k8sClient.Get(context.Background(), types.NamespacedName{
|
|
Name: tcp.Name,
|
|
Namespace: tcp.Namespace,
|
|
}, controlPlaneRoute); err != nil {
|
|
return err
|
|
}
|
|
|
|
konnectivityRoute := &gatewayv1alpha2.TLSRoute{}
|
|
if err := k8sClient.Get(context.Background(), types.NamespacedName{
|
|
Name: tcp.Name + "-konnectivity",
|
|
Namespace: tcp.Namespace,
|
|
}, konnectivityRoute); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(controlPlaneRoute.Spec.Hostnames) == 0 || len(konnectivityRoute.Spec.Hostnames) == 0 {
|
|
return fmt.Errorf("hostnames are empty")
|
|
}
|
|
if controlPlaneRoute.Spec.Hostnames[0] != konnectivityRoute.Spec.Hostnames[0] {
|
|
return fmt.Errorf("hostnames do not match: control plane '%s', konnectivity '%s'",
|
|
controlPlaneRoute.Spec.Hostnames[0], konnectivityRoute.Spec.Hostnames[0])
|
|
}
|
|
|
|
return nil
|
|
}).WithTimeout(time.Minute).Should(Succeed())
|
|
})
|
|
})
|