Skip to content

Commit

Permalink
tests: Fix flakey TestConfigureNotAttachedHttpListenerOptions (#10480)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidjumani authored Dec 16, 2024
1 parent 89f934c commit 97edbf8
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
changelog:
- type: NON_USER_FACING
issueLink: https://github.com/solo-io/solo-projects/issues/6617
description: Fix flakey TestConfigureNotAttachedHttpListenerOptions caused by the gateway-proxy pod being deployed after the test begins leading to a timeout.
34 changes: 28 additions & 6 deletions test/gomega/matchers/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ type ExpectedPod struct {
// Status is the pod phase status (e.g. Running, Pending, Succeeded, Failed). Optional.
Status corev1.PodPhase

// Ready indicates that the Pod is able to serve requests. Optional.
Ready bool

// TODO(npolshak): Add more fields to match on as needed
}

Expand All @@ -41,28 +44,47 @@ func (pm *podMatcher) Match(actual interface{}) (bool, error) {
}
}
if !foundContainer {
log.Printf("expected pod to have container '%s', but it was not found", pm.expectedPod.ContainerName)
log.Printf("expected pod %s to have container '%s', but it was not found", pod.Name, pm.expectedPod.ContainerName)
return false, nil
}
}

if pm.expectedPod.Status != "" {
if pod.Status.Phase != pm.expectedPod.Status {
log.Printf("expected pod to have status %s, but it was %s", pm.expectedPod.Status, pod.Status.Phase)
log.Printf("expected pod %s to have status %s, but it was %s", pod.Name, pm.expectedPod.Status, pod.Status.Phase)
return false, nil
}
}

if pm.expectedPod.Ready {
for _, condition := range pod.Status.Conditions {
if condition.Type == corev1.PodReady {
ready := condition.Status == corev1.ConditionTrue
if !ready {
log.Printf("expected pod %s to have condition ready, but it was not ready", pod.Name)
}
return ready, nil
}
}
log.Printf("expected pod %s to have condition ready, but it was not found", pod.Name)
return false, nil
}

return true, nil
}

func (pm *podMatcher) FailureMessage(actual interface{}) string {
var errorMsg string
pod, ok := actual.(corev1.Pod)
if !ok {
return fmt.Sprintf("expected a pod, got %T", actual)
}

if pm.expectedPod.ContainerName != "" {
errorMsg += fmt.Sprintf("Expected pod to have container '%s', but it was not found", pm.expectedPod.ContainerName)
errorMsg += fmt.Sprintf("Expected pod %s to have container '%s', but it was not found", pod.Name, pm.expectedPod.ContainerName)
}
if pm.expectedPod.Status != "" {
errorMsg += fmt.Sprintf("Expected pod to have status '%s', but it was not found", pm.expectedPod.Status)
errorMsg += fmt.Sprintf("Expected pod %s to have status '%s', but it was not found", pod.Name, pm.expectedPod.Status)
}
return errorMsg
}
Expand All @@ -76,10 +98,10 @@ func (pm *podMatcher) NegatedFailureMessage(actual interface{}) string {
for _, container := range pod.Spec.Containers {
containers += container.Name + ", "
}
errorMsg += fmt.Sprintf("Expected pod to have container '%s', but it found %s", pm.expectedPod.ContainerName, containers)
errorMsg += fmt.Sprintf("Expected pod %s to have container '%s', but it found %s", pod.Name, pm.expectedPod.ContainerName, containers)
}
if pm.expectedPod.Status != "" {
errorMsg += fmt.Sprintf("Expected pod to have status '%s', but it found %s", pm.expectedPod.Status, pod.Status.Phase)
errorMsg += fmt.Sprintf("Expected pod %s to have status '%s', but it found %s", pod.Name, pm.expectedPod.Status, pod.Status.Phase)
}
return errorMsg
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ func (s *testingSuite) SetupSuite() {
s.testInstallation.Assertions.EventuallyPodsRunning(s.ctx, nginxPod.ObjectMeta.GetNamespace(), metav1.ListOptions{
LabelSelector: "app.kubernetes.io/name=nginx",
})
s.testInstallation.Assertions.EventuallyPodsRunning(s.ctx, testdefaults.CurlPod.GetNamespace(), metav1.ListOptions{
LabelSelector: "app=curl",
})

// include gateway manifests for the tests, so we recreate it for each test run
s.manifests = map[string][]string{
Expand Down Expand Up @@ -88,6 +91,10 @@ func (s *testingSuite) AfterTest(suiteName, testName string) {
output, err := s.testInstallation.Actions.Kubectl().DeleteFileWithOutput(s.ctx, manifest)
s.testInstallation.Assertions.ExpectObjectDeleted(manifest, err, output)
}
s.testInstallation.Assertions.EventuallyObjectsNotExist(s.ctx, proxyService, proxyDeployment)
s.testInstallation.Assertions.EventuallyPodsNotExist(s.ctx, proxyDeployment.ObjectMeta.GetNamespace(), metav1.ListOptions{
LabelSelector: "app.kubernetes.io/name=gloo-proxy-gw",
})
}

func (s *testingSuite) TestConfigureHttpListenerOptions() {
Expand Down
23 changes: 21 additions & 2 deletions test/kubernetes/testutils/assertions/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EventuallyPodsRunning asserts that the pod(s) are in the ready state
// EventuallyPodsRunning asserts that the pod(s) are running and ready.
func (p *Provider) EventuallyPodsRunning(
ctx context.Context,
podNamespace string,
listOpt metav1.ListOptions,
timeout ...time.Duration,
) {
p.EventuallyPodsMatches(ctx, podNamespace, listOpt, matchers.PodMatches(matchers.ExpectedPod{Status: corev1.PodRunning}), timeout...)
p.EventuallyPodsMatches(ctx, podNamespace, listOpt, matchers.PodMatches(matchers.ExpectedPod{Status: corev1.PodRunning, Ready: true}), timeout...)
}

// EventuallyPodsMatches asserts that the pod(s) in the given namespace matches the provided matcher
Expand All @@ -45,3 +45,22 @@ func (p *Provider) EventuallyPodsMatches(
WithPolling(pollingInterval).
Should(gomega.Succeed(), fmt.Sprintf("Failed to match pod in namespace %s", podNamespace))
}

// EventuallyPodsNotExist asserts that the pod(s) are no longer present
func (p *Provider) EventuallyPodsNotExist(
ctx context.Context,
podNamespace string,
listOpt metav1.ListOptions,
timeout ...time.Duration,
) {
currentTimeout, pollingInterval := helper.GetTimeouts(timeout...)

p.Gomega.Eventually(func(g gomega.Gomega) {
pods, err := p.clusterContext.Clientset.CoreV1().Pods(podNamespace).List(ctx, listOpt)
g.Expect(err).NotTo(gomega.HaveOccurred(), "Failed to list pods")
g.Expect(pods.Items).To(gomega.BeEmpty(), "Pods found")
}).
WithTimeout(currentTimeout).
WithPolling(pollingInterval).
Should(gomega.Succeed(), fmt.Sprintf("Failed to match pod in namespace %s", podNamespace))
}

0 comments on commit 97edbf8

Please sign in to comment.