adding e2e tests

This commit is contained in:
Enrico Candino
2026-06-15 16:03:28 +02:00
parent fcb0baeac9
commit d01ae2e820
2 changed files with 88 additions and 14 deletions
+9 -14
View File
@@ -151,15 +151,9 @@ func (c *ClusterReconciler) ensureHCPKubernetesEndpointSlice(ctx context.Context
endpointSlice.Labels[discoveryv1.LabelServiceName] = "kubernetes"
endpointSlice.AddressType = addressType
endpoint := discoveryv1.Endpoint{
Addresses: []string{addr.IP},
endpointSlice.Endpoints = []discoveryv1.Endpoint{
{Addresses: []string{addr.IP}},
}
if addr.Hostname != "" {
endpoint.Hostname = &addr.Hostname
}
endpointSlice.Endpoints = []discoveryv1.Endpoint{endpoint}
portName := "https"
endpointSlice.Ports = []discoveryv1.EndpointPort{
@@ -177,7 +171,7 @@ func (c *ClusterReconciler) ensureHCPKubernetesEndpointSlice(ctx context.Context
}
log.V(1).Info("HCP kubernetes endpointslice reconciled",
"address", addr.IP, "hostname", addr.Hostname, "port", port)
"address", addr.IP, "host", host, "port", port)
return nil
}
@@ -248,7 +242,7 @@ func (c *ClusterReconciler) ensureHCPKubernetesEndpoints(ctx context.Context, cl
return fmt.Errorf("upserting default/kubernetes endpoints in virtual cluster: %w", err)
}
log.V(1).Info("HCP kubernetes endpoints reconciled", "address", addr.IP, "hostname", addr.Hostname, "port", port)
log.V(1).Info("HCP kubernetes endpoints reconciled", "address", addr.IP, "host", host, "port", port)
return nil
}
@@ -288,8 +282,9 @@ func parseHCPHostPort(rawURL string) (string, int32, error) {
// hcpEndpointAddress builds a corev1.EndpointAddress from the externally
// reachable host. Endpoints require an IP; if the host is a DNS name we
// resolve it and keep the original name as Hostname so logs/events remain
// human-readable.
// resolve it. The Hostname field is intentionally left unset: the
// kubernetes API validates it as a DNS-1123 label (no dots), so an FQDN
// like "host.example.com" would be rejected.
func hcpEndpointAddress(host string) (corev1.EndpointAddress, error) {
if ip := net.ParseIP(host); ip != nil {
if ip.IsLoopback() {
@@ -317,8 +312,8 @@ func hcpEndpointAddress(host string) (corev1.EndpointAddress, error) {
}
if v4 := filteredIPs[0].To4(); v4 != nil {
return corev1.EndpointAddress{IP: v4.String(), Hostname: host}, nil
return corev1.EndpointAddress{IP: v4.String()}, nil
}
return corev1.EndpointAddress{IP: filteredIPs[0].String(), Hostname: host}, nil
return corev1.EndpointAddress{IP: filteredIPs[0].String()}, nil
}
+79
View File
@@ -5,8 +5,11 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/rancher/k3k/pkg/apis/k3k.io/v1beta1"
k3kcluster "github.com/rancher/k3k/pkg/controller/cluster"
fwk3k "github.com/rancher/k3k/tests/framework/k3k"
. "github.com/onsi/ginkgo/v2"
@@ -61,3 +64,79 @@ var _ = When("creating a shared mode cluster", Label(e2eTestLabel), Label(slowTe
Should(Succeed())
})
})
var _ = When("creating an HCP mode cluster", Label(e2eTestLabel), Label(slowTestsLabel), func() {
var virtualCluster *VirtualCluster
BeforeEach(func() {
namespace := fwk3k.CreateNamespace(k8s)
DeferCleanup(func() {
fwk3k.DeleteNamespaces(k8s, namespace.Name)
})
cluster := NewCluster(namespace.Name)
cluster.Spec.Mode = v1beta1.HCPClusterMode
CreateCluster(cluster)
client, restConfig := NewVirtualK8sClientAndConfig(cluster)
virtualCluster = &VirtualCluster{
Cluster: cluster,
RestConfig: restConfig,
Client: client,
}
})
It("is up and running", func() {
Eventually(func(g Gomega) {
ctx := GinkgoT().Context()
key := client.ObjectKeyFromObject(virtualCluster.Cluster)
g.Expect(k8sClient.Get(ctx, key, virtualCluster.Cluster)).To(Succeed())
g.Expect(virtualCluster.Cluster.Status.Phase).To(BeEquivalentTo(v1beta1.ClusterReady))
}).
WithTimeout(time.Minute).
WithPolling(time.Second).
Should(Succeed())
})
It("creates a populated token secret", func() {
ctx := GinkgoT().Context()
var tokenSecret corev1.Secret
err := k8sClient.Get(ctx, client.ObjectKey{
Name: k3kcluster.TokenSecretName(virtualCluster.Cluster.Name),
Namespace: virtualCluster.Cluster.Namespace,
}, &tokenSecret)
Expect(err).NotTo(HaveOccurred())
Expect(tokenSecret.Data["token"]).NotTo(BeEmpty())
})
It("reconciles default/kubernetes Endpoints and EndpointSlice", func() {
ctx := GinkgoT().Context()
Eventually(func(g Gomega) {
endpoints, err := virtualCluster.Client.CoreV1().Endpoints("default").Get(ctx, "kubernetes", metav1.GetOptions{})
g.Expect(err).To(Not(HaveOccurred()))
g.Expect(endpoints.Subsets).To(HaveLen(1))
g.Expect(endpoints.Subsets[0].Addresses).To(HaveLen(1))
g.Expect(endpoints.Subsets[0].Addresses[0].IP).To(Equal(hostIP))
}).
WithTimeout(time.Minute).
WithPolling(time.Second).
Should(Succeed())
Eventually(func(g Gomega) {
slices, err := virtualCluster.Client.DiscoveryV1().EndpointSlices("default").List(ctx, metav1.ListOptions{
LabelSelector: "kubernetes.io/service-name=kubernetes",
})
g.Expect(err).To(Not(HaveOccurred()))
g.Expect(slices.Items).To(HaveLen(1))
g.Expect(slices.Items[0].Endpoints).To(HaveLen(1))
g.Expect(slices.Items[0].Endpoints[0].Addresses).To(ContainElement(hostIP))
}).
WithTimeout(time.Minute).
WithPolling(time.Second).
Should(Succeed())
})
})