Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions test/e2e/v2/tests/control_plane_infrastructure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func InfrastructureRegistryValidationTest(getTestCtx internal.TestContextGetter)
testCtx := getTestCtx()

var podsNotBelongingToWorkloads []string
namespacesChecked := 0

for _, namespace := range internal.GetInfrastructureNamespaces() {
ns := &corev1.Namespace{}
Expand All @@ -99,6 +100,7 @@ func InfrastructureRegistryValidationTest(getTestCtx internal.TestContextGetter)
continue
}
Expect(err).NotTo(HaveOccurred(), "failed to get namespace %s", namespace)
namespacesChecked++

podList := &corev1.PodList{}
err = testCtx.MgmtClient.List(testCtx.Context, podList, &crclient.ListOptions{
Expand All @@ -122,6 +124,8 @@ func InfrastructureRegistryValidationTest(getTestCtx internal.TestContextGetter)
}
}

Expect(namespacesChecked).NotTo(BeZero(),
"expected at least one infrastructure namespace to exist")
Expect(podsNotBelongingToWorkloads).To(BeEmpty(),
"The following pods do not belong to any predefined infrastructure workload:\n%s",
strings.Join(podsNotBelongingToWorkloads, "\n"))
Expand Down Expand Up @@ -158,6 +162,10 @@ func InfrastructureResourceRequestsTest(getTestCtx internal.TestContextGetter) {
}
}

if len(matchingPods) == 0 {
Skip(fmt.Sprintf("no matching pods found for workload %s", workload.Name))
}

var failures []string
for _, pod := range matchingPods {
failures = append(failures, validateContainerResourceRequests(pod.Namespace, pod.Name, pod.Spec.Containers)...)
Expand Down
6 changes: 4 additions & 2 deletions test/e2e/v2/tests/control_plane_workloads_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func DeploymentGenerationTest(getTestCtx internal.TestContextGetter) {
}

deployment := &appsv1.Deployment{}
err := testCtx.MgmtClient.Get(context.Background(), crclient.ObjectKey{
err := testCtx.MgmtClient.Get(testCtx.Context, crclient.ObjectKey{
Namespace: testCtx.ControlPlaneNamespace,
Name: workload.Name,
}, deployment)
Expand Down Expand Up @@ -722,6 +722,8 @@ func WorkloadRegistryValidationTest(getTestCtx internal.TestContextGetter) {
Namespace: testCtx.ControlPlaneNamespace,
})
Expect(err).NotTo(HaveOccurred(), "failed to list pods in control plane namespace")
Expect(podList.Items).NotTo(BeEmpty(),
"expected pods in control plane namespace %s", testCtx.ControlPlaneNamespace)

workloadSelectors := make(map[string]labels.Selector)
for _, workload := range workloads {
Expand Down Expand Up @@ -767,7 +769,7 @@ func SecurityContextUIDTest(getTestCtx internal.TestContextGetter) {

// Get the control plane namespace to check for UID annotation
controlPlaneNamespace := &corev1.Namespace{}
err := testCtx.MgmtClient.Get(context.Background(), crclient.ObjectKey{Name: testCtx.ControlPlaneNamespace}, controlPlaneNamespace)
err := testCtx.MgmtClient.Get(testCtx.Context, crclient.ObjectKey{Name: testCtx.ControlPlaneNamespace}, controlPlaneNamespace)
Expect(err).NotTo(HaveOccurred(), "failed to get namespace %s", testCtx.ControlPlaneNamespace)

uid, ok := controlPlaneNamespace.Annotations["hypershift.openshift.io/default-security-context-uid"]
Expand Down
22 changes: 12 additions & 10 deletions test/e2e/v2/tests/etcd_chaos_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,14 @@ func EtcdKillRandomMembersTest(getTestCtx internal.TestContextGetter) {
ctx := testCtx.Context
cpNamespace := testCtx.ControlPlaneNamespace

guestClient := testCtx.GetHostedClusterClient()
hcClient := testCtx.GetHostedClusterClient()

// Create marker data that should survive the chaos
markerCM := createMarkerConfigMap(ctx, guestClient)
markerCM := createMarkerConfigMap(ctx, hcClient)
DeferCleanup(func() {
if err := guestClient.Delete(ctx, markerCM); err != nil && !apierrors.IsNotFound(err) {
GinkgoWriter.Printf("Warning: failed to cleanup marker ConfigMap: %v\n", err)
err := hcClient.Delete(ctx, markerCM)
if err != nil && !apierrors.IsNotFound(err) {
Expect(err).NotTo(HaveOccurred(), "cleanup: failed to delete marker ConfigMap %s", markerCM.Name)
}
})

Expand Down Expand Up @@ -160,7 +161,7 @@ func EtcdKillRandomMembersTest(getTestCtx internal.TestContextGetter) {

waitForEtcdConvergence(ctx, testCtx.MgmtClient, cpNamespace, ptr.Deref(etcdSts.Spec.Replicas, 0))

verifyMarkerSurvived(ctx, guestClient, markerCM)
verifyMarkerSurvived(ctx, hcClient, markerCM)
})
}

Expand All @@ -173,13 +174,14 @@ func EtcdKillAllMembersTest(getTestCtx internal.TestContextGetter) {
ctx := testCtx.Context
cpNamespace := testCtx.ControlPlaneNamespace

guestClient := testCtx.GetHostedClusterClient()
hcClient := testCtx.GetHostedClusterClient()

// Create marker data that should survive the chaos
markerCM := createMarkerConfigMap(ctx, guestClient)
markerCM := createMarkerConfigMap(ctx, hcClient)
DeferCleanup(func() {
if err := guestClient.Delete(ctx, markerCM); err != nil && !apierrors.IsNotFound(err) {
GinkgoWriter.Printf("Warning: failed to cleanup marker ConfigMap: %v\n", err)
err := hcClient.Delete(ctx, markerCM)
if err != nil && !apierrors.IsNotFound(err) {
Expect(err).NotTo(HaveOccurred(), "cleanup: failed to delete marker ConfigMap %s", markerCM.Name)
}
})

Expand Down Expand Up @@ -236,7 +238,7 @@ func EtcdKillAllMembersTest(getTestCtx internal.TestContextGetter) {

waitForEtcdConvergence(ctx, testCtx.MgmtClient, cpNamespace, ptr.Deref(etcdSts.Spec.Replicas, 0))

verifyMarkerSurvived(ctx, guestClient, markerCM)
verifyMarkerSurvived(ctx, hcClient, markerCM)
})
}

Expand Down
10 changes: 10 additions & 0 deletions test/e2e/v2/tests/hosted_cluster_aws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ func EnsureDefaultSecurityGroupTagsTest(getTestCtx internal.TestContextGetter) {
Skip("default security group tags test is only for AWS platform")
}

Expect(hc.Status.Platform).NotTo(BeNil(),
"HostedCluster %s/%s should have platform status", hc.Namespace, hc.Name)
Expect(hc.Status.Platform.AWS).NotTo(BeNil(),
"HostedCluster %s/%s should have AWS platform status", hc.Namespace, hc.Name)
sgID := hc.Status.Platform.AWS.DefaultWorkerSecurityGroupID
Expect(sgID).NotTo(BeEmpty(), "HostedCluster status should have DefaultWorkerSecurityGroupID set")

Expand Down Expand Up @@ -202,6 +206,12 @@ func AWSCCMWithCustomizationsTest(getTestCtx internal.TestContextGetter) {
},
}
Expect(hcClient.Create(tc.Context, testSvc)).To(Succeed(), "failed to create LoadBalancer service")
DeferCleanup(func() {
err := hcClient.Delete(tc.Context, testSvc)
if err != nil && !apierrors.IsNotFound(err) {
Expect(err).NotTo(HaveOccurred(), "cleanup: failed to delete test service %s", testSvc.Name)
}
})

var lbHostname string
Eventually(func(g Gomega) {
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/v2/tests/hosted_cluster_ccm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package tests

import (
"context"
"strings"

. "github.com/onsi/ginkgo/v2"
Expand Down Expand Up @@ -51,7 +50,7 @@ func GCPCloudControllerManagerTest(getTestCtx internal.TestContextGetter) {
Expect(hostedClusterClient).NotTo(BeNil(), "hosted cluster client is nil; HostedCluster may not have KubeConfig status set")

nodes = &corev1.NodeList{}
Expect(hostedClusterClient.List(context.Background(), nodes)).To(Succeed())
Expect(hostedClusterClient.List(testCtx.Context, nodes)).To(Succeed())
Expect(nodes.Items).NotTo(BeEmpty(), "cluster should have nodes")
})

Expand Down Expand Up @@ -112,6 +111,7 @@ var _ = Describe("Hosted Cluster CCM", Label("hosted-cluster-ccm"), func() {
BeforeEach(func() {
testCtx = internal.GetTestContext()
Expect(testCtx).NotTo(BeNil(), "test context should be set up in BeforeSuite")
testCtx.ValidateHostedCluster()
})

RegisterHostedClusterCCMTests(func() *internal.TestContext { return testCtx })
Expand Down
2 changes: 2 additions & 0 deletions test/e2e/v2/tests/hosted_cluster_health_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ func EnsureCAPIFinalizersTest(getTestCtx internal.TestContextGetter) {
When("CAPI components are deployed", func() {
It("should have component finalizers on all CAPI deployments", func() {
tc := getTestCtx()
Expect(hcc.CAPIComponents).NotTo(BeEmpty(),
"expected CAPI components to be defined in HostedControlPlaneConfiguration")
for _, name := range hcc.CAPIComponents {
deployment := &appsv1.Deployment{}
Expect(tc.MgmtClient.Get(tc.Context, crclient.ObjectKey{
Expand Down
2 changes: 2 additions & 0 deletions test/e2e/v2/tests/hosted_cluster_image_registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ func ImageRegistryCapabilityEnabledTest(getTestCtx internal.TestContextGetter) {
}
Expect(hc.Spec.Platform.GCP).NotTo(BeNil(),
"GCP platform spec must be set for GCP HostedCluster %s/%s", hc.Namespace, hc.Name)
Expect(hc.Spec.Platform.GCP.WorkloadIdentity).NotTo(BeNil(),
"GCP platform spec should have WorkloadIdentity configured for HostedCluster %s/%s", hc.Namespace, hc.Name)
imageRegistryEmail = string(hc.Spec.Platform.GCP.WorkloadIdentity.ServiceAccountsEmails.ImageRegistry)
Expect(imageRegistryEmail).NotTo(BeEmpty(),
"imageRegistry service account email must be set in GCP WorkloadIdentity config for %s/%s",
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/v2/tests/hosted_cluster_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func EnsureMetricsForwarderWorkingTest(getTestCtx internal.TestContextGetter) {
g.Expect(pod.Status.Phase).To(Equal(corev1.PodRunning), "prometheus pod should be running")
}, 5*time.Minute, 10*time.Second).Should(Succeed())

By("Verifying guest Prometheus is scraping kube-apiserver via the metrics-forwarder")
By("Verifying hosted cluster Prometheus is scraping kube-apiserver via the metrics-forwarder")
Eventually(func(g Gomega) {
output, err := v2util.RunCommandInPod(tc.Context, hcClientset, hcRestConfig,
monitoringNamespace, promPodName, "prometheus",
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/v2/tests/hosted_cluster_security_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ import (
)

func RegisterHostedClusterSecurityTests(getTestCtx internal.TestContextGetter) {
EnsureGuestWebhooksValidatedTest(getTestCtx)
EnsureHostedClusterWebhooksValidatedTest(getTestCtx)
EnsureAdmissionPoliciesTest(getTestCtx)
EnsureNetworkPoliciesTest(getTestCtx)
}

func EnsureGuestWebhooksValidatedTest(getTestCtx internal.TestContextGetter) {
func EnsureHostedClusterWebhooksValidatedTest(getTestCtx internal.TestContextGetter) {
When("a webhook targeting a control plane service is created in the hosted cluster", func() {
It("should be automatically deleted", func() {
tc := getTestCtx()
Expand Down
51 changes: 29 additions & 22 deletions test/e2e/v2/tests/nodepool_autoscaling_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func AutoscalingScaleUpDownTest(getTestCtx internal.TestContextGetter) {
testCtx.ValidateHostedClusterClient()

hc := testCtx.GetHostedCluster()
guestClient := testCtx.GetHostedClusterClient()
hcClient := testCtx.GetHostedClusterClient()
ctx := testCtx.Context

// Find the default NodePool to copy platform config
Expand All @@ -63,14 +63,16 @@ func AutoscalingScaleUpDownTest(getTestCtx internal.TestContextGetter) {
GinkgoWriter.Printf("Created autoscaling NodePool %s with min=1, max=3\n", autoscalingNP.Name)

// Ensure cleanup
defer cleanupNodePool(ctx, testCtx.MgmtClient, autoscalingNP)
DeferCleanup(func() {
cleanupNodePool(ctx, testCtx.MgmtClient, autoscalingNP)
})

npLabelSelector := e2eutil.WithClientOptions(crclient.MatchingLabelsSelector{
Selector: labels.SelectorFromSet(labels.Set{hyperv1.NodePoolLabel: autoscalingNP.Name}),
})

// Wait for NodePool to be ready with 1 node (min replicas)
nodes := e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, guestClient, 1, hc.Spec.Platform.Type, fmt.Sprintf("for NodePool %s", autoscalingNP.Name), npLabelSelector)
nodes := e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, hcClient, 1, hc.Spec.Platform.Type, fmt.Sprintf("for NodePool %s", autoscalingNP.Name), npLabelSelector)
Expect(nodes).To(HaveLen(1), "should have exactly 1 node initially")

// Get node capacity for workload sizing
Expand All @@ -83,19 +85,21 @@ func AutoscalingScaleUpDownTest(getTestCtx internal.TestContextGetter) {
// cluster autoscaler must scale it up.
workloadMemRequest := *resource.NewQuantity(bytes/2, resource.BinarySI)
workload := newAutoscalingWorkload(3, workloadMemRequest, autoscalingLabel)
err = guestClient.Create(ctx, workload)
err = hcClient.Create(ctx, workload)
Expect(err).NotTo(HaveOccurred(), "failed to create workload")

defer cleanupWorkload(ctx, guestClient, workload)
DeferCleanup(func() {
cleanupWorkload(ctx, hcClient, workload)
})

// Wait for scale-up to 3 nodes
e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, guestClient, 3, hc.Spec.Platform.Type, fmt.Sprintf("for NodePool %s", autoscalingNP.Name), npLabelSelector)
e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, hcClient, 3, hc.Spec.Platform.Type, fmt.Sprintf("for NodePool %s", autoscalingNP.Name), npLabelSelector)

// Delete workload to trigger scale-down
cleanupWorkload(ctx, guestClient, workload)
cleanupWorkload(ctx, hcClient, workload)

// Wait for scale-down to 1 node (min replicas)
e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, guestClient, 1, hc.Spec.Platform.Type, fmt.Sprintf("for NodePool %s", autoscalingNP.Name), npLabelSelector)
e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, hcClient, 1, hc.Spec.Platform.Type, fmt.Sprintf("for NodePool %s", autoscalingNP.Name), npLabelSelector)
})
}

Expand All @@ -110,7 +114,7 @@ func AutoscalingBalancingTest(getTestCtx internal.TestContextGetter) {
e2eutil.GinkgoAtLeast(e2eutil.Version420)

hc := testCtx.GetHostedCluster()
guestClient := testCtx.GetHostedClusterClient()
hcClient := testCtx.GetHostedClusterClient()
ctx := testCtx.Context
cpNamespace := testCtx.ControlPlaneNamespace

Expand All @@ -133,15 +137,12 @@ func AutoscalingBalancingTest(getTestCtx internal.TestContextGetter) {

DeferCleanup(func() {
latest := &hyperv1.HostedCluster{}
if err := testCtx.MgmtClient.Get(ctx, crclient.ObjectKeyFromObject(hc), latest); err != nil {
GinkgoWriter.Printf("Warning: failed to get HostedCluster for cleanup: %v\n", err)
return
}
Expect(testCtx.MgmtClient.Get(ctx, crclient.ObjectKeyFromObject(hc), latest)).To(Succeed(),
"cleanup: failed to get HostedCluster for autoscaling config reset")
patch := crclient.MergeFrom(latest.DeepCopy())
latest.Spec.Autoscaling = hyperv1.ClusterAutoscaling{}
if err := testCtx.MgmtClient.Patch(ctx, latest, patch); err != nil {
GinkgoWriter.Printf("Warning: failed to reset autoscaler config: %v\n", err)
}
Expect(testCtx.MgmtClient.Patch(ctx, latest, patch)).To(Succeed(),
"cleanup: failed to reset autoscaler config on HostedCluster")
})

// Wait for autoscaler deployment to pick up the new config
Expand Down Expand Up @@ -184,12 +185,16 @@ func AutoscalingBalancingTest(getTestCtx internal.TestContextGetter) {
autoscalingNP1 := buildAutoscalingNodePool(defaultNP, 1, 3, np1Labels)
err = testCtx.MgmtClient.Create(ctx, autoscalingNP1)
Expect(err).NotTo(HaveOccurred(), "failed to create first autoscaling NodePool")
defer cleanupNodePool(ctx, testCtx.MgmtClient, autoscalingNP1)
DeferCleanup(func() {
cleanupNodePool(ctx, testCtx.MgmtClient, autoscalingNP1)
})

autoscalingNP2 := buildAutoscalingNodePool(defaultNP, 1, 3, np2Labels)
err = testCtx.MgmtClient.Create(ctx, autoscalingNP2)
Expect(err).NotTo(HaveOccurred(), "failed to create second autoscaling NodePool")
defer cleanupNodePool(ctx, testCtx.MgmtClient, autoscalingNP2)
DeferCleanup(func() {
cleanupNodePool(ctx, testCtx.MgmtClient, autoscalingNP2)
})

np1LabelSelector := e2eutil.WithClientOptions(crclient.MatchingLabelsSelector{
Selector: labels.SelectorFromSet(labels.Set{hyperv1.NodePoolLabel: autoscalingNP1.Name}),
Expand All @@ -199,8 +204,8 @@ func AutoscalingBalancingTest(getTestCtx internal.TestContextGetter) {
})

// Wait for initial nodes (1 per NodePool at min replicas)
nodes := e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, guestClient, 1, hc.Spec.Platform.Type, "for NP1", np1LabelSelector)
e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, guestClient, 1, hc.Spec.Platform.Type, "for NP2", np2LabelSelector)
nodes := e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, hcClient, 1, hc.Spec.Platform.Type, "for NP1", np1LabelSelector)
e2eutil.WaitForNReadyNodesWithOptions(GinkgoTB(), ctx, hcClient, 1, hc.Spec.Platform.Type, "for NP2", np2LabelSelector)

// Get node capacity for workload sizing
memCapacity := nodes[0].Status.Allocatable[corev1.ResourceMemory]
Expand All @@ -210,9 +215,11 @@ func AutoscalingBalancingTest(getTestCtx internal.TestContextGetter) {
// Create workload targeting the autoscaling NodePools via the shared label.
workloadMemRequest := *resource.NewQuantity(bytes/2, resource.BinarySI)
workload := newAutoscalingWorkload(4, workloadMemRequest, sharedLabel)
err = guestClient.Create(ctx, workload)
err = hcClient.Create(ctx, workload)
Expect(err).NotTo(HaveOccurred(), "failed to create workload")
defer cleanupWorkload(ctx, guestClient, workload)
DeferCleanup(func() {
cleanupWorkload(ctx, hcClient, workload)
})

// Wait for total 4 nodes across both NPs, then verify balanced distribution
Eventually(func() (bool, error) {
Expand Down
Loading