Skip to content

test: add E2E tests for manual APIKey approval and rejection workflows#66

Merged
eguzki merged 3 commits into
Kuadrant:mainfrom
emmaaroche:e2e-manual-approval-tests
May 26, 2026
Merged

test: add E2E tests for manual APIKey approval and rejection workflows#66
eguzki merged 3 commits into
Kuadrant:mainfrom
emmaaroche:e2e-manual-approval-tests

Conversation

@emmaaroche
Copy link
Copy Markdown
Contributor

@emmaaroche emmaaroche commented May 25, 2026

Summary

Add E2E test coverage for manual APIKey approval and rejection workflows.

Both manual workflow tests verify:

  1. APIProduct created with approvalMode: manual
  2. APIKey created in consumer namespace → Pending=True
  3. APIKeyRequest created in owner namespace → Pending=True
  4. Manual APIKeyApproval created (approved: true/false)
  5. Condition propagates to APIKeyRequest (Approved/Denied=True)
  6. Condition propagates to APIKey (Approved/Denied=True)

Closes #61

Changes

New Tests (test/e2e/manual_workflow_test.go):

  • Manual approval flow: owner approves APIKey request, verifies Approved=True propagates
  • Rejection flow: owner denies APIKey request, verifies Denied=True propagates

Refactoring:

  • Extracted common setup/teardown code to avoid duplication between automatic and manual tests:
    • CreateHTTPRoute() - HTTPRoute creation
    • CreateAuthPolicy() - AuthPolicy creation + status patch
    • CleanupNamespaces() - namespace cleanup
    • LogDebugInfoOnFailure() - debug logging on test failure
  • Updated automatic_approval_test.go to use shared helpers

Verification Steps

make test-e2e 

Expected: 6/6 tests pass including new manual approval and rejection tests.

Summary by CodeRabbit

  • Tests
    • Automatic approval test refactored to use shared helpers for setup, teardown and failure diagnostics, improving clarity and maintainability.
    • Added a new manual workflow e2e test covering API key approval and rejection paths, namespace lifecycle and expected state transitions.
    • Introduced reusable test helpers for creating test resources, cleaning up namespaces asynchronously and emitting debug information on failures.

Review Change Stack

Signed-off-by: emmaaroche <eroche@redhat.com>
@emmaaroche emmaaroche requested review from R-Lawton and eguzki May 25, 2026 14:37
@emmaaroche emmaaroche self-assigned this May 25, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 61852c06-0cc2-4795-84e7-eb5b71216ad4

📥 Commits

Reviewing files that changed from the base of the PR and between da74336 and 564d25b.

📒 Files selected for processing (1)
  • test/e2e/test_helpers.go

📝 Walkthrough

Walkthrough

Adds reusable e2e test helpers for Kubernetes operations and failure diagnostics, refactors the automatic approval test to use those helpers, and introduces a new manual approval/rejection e2e test exercising both approval and denial flows.

Changes

Manual Approval E2E Testing Coverage

Layer / File(s) Summary
Shared e2e test helpers
test/e2e/test_helpers.go
New helper functions for namespace cleanup (CleanupNamespaces), conditional failure diagnostics (LogDebugInfoOnFailure), and Kubernetes resource creation/status patching (CreateHTTPRoute, CreateAuthPolicy).
Refactor automatic approval test to use helpers
test/e2e/automatic_approval_test.go
Automatic approval test updated to call helper functions for failure logging, HTTPRoute/AuthPolicy creation, and namespace deletion instead of inline kubectl/YAML and status patch blocks; APIProduct apply logic is retained.
New manual approval and rejection workflow test
test/e2e/manual_workflow_test.go
New Ginkgo suite that sets up namespaces and Kuadrant, applies an APIProduct in manual mode, creates consumer Secret/APIKey, verifies Pending conditions, creates an APIKeyApproval (approve/deny), and asserts status transitions on APIKeyRequest and downstream APIKey.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • R-Lawton
  • didierofrivia

Poem

🐇 In my burrow I patch and apply with care,

Helpers to tidy namespaces and snare.
Logs whispered softly when tests go awry,
Approve or deny — I watch clouds float by.
A hop, a test, and then a celebratory share.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding E2E tests for manual APIKey approval and rejection workflows, which is exactly what the changeset delivers.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/e2e/test_helpers.go (1)

91-99: ⚡ Quick win

Keep collecting namespace events even when controller pod lookup fails.

Line 93 and Line 98 return early, so owner/consumer events are never logged if pod discovery fails. That removes key diagnostics exactly when failures occur.

Proposed fix
-	podOutput, err := utils.Run(cmd)
-	if err != nil {
-		_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Failed to get controller pod name: %s\n", err)
-		return
-	}
-	podNames := utils.GetNonEmptyLines(podOutput)
-	if len(podNames) == 0 {
-		_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "No controller pod found\n")
-		return
-	}
-	controllerPodName := podNames[0]
+	podOutput, err := utils.Run(cmd)
+	controllerPodName := ""
+	if err != nil {
+		_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Failed to get controller pod name: %s\n", err)
+	} else {
+		podNames := utils.GetNonEmptyLines(podOutput)
+		if len(podNames) == 0 {
+			_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "No controller pod found\n")
+		} else {
+			controllerPodName = podNames[0]
+		}
+	}
 
-	ginkgo.By("Fetching controller manager pod logs")
-	cmd = exec.Command("kubectl", "logs", controllerPodName, "-n", controllerNamespace)
-	controllerLogs, err := utils.Run(cmd)
-	if err == nil {
-		_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Controller logs:\n%s\n", controllerLogs)
-	} else {
-		_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Failed to get Controller logs: %s\n", err)
-	}
+	if controllerPodName != "" {
+		ginkgo.By("Fetching controller manager pod logs")
+		cmd = exec.Command("kubectl", "logs", controllerPodName, "-n", controllerNamespace)
+		controllerLogs, err := utils.Run(cmd)
+		if err == nil {
+			_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Controller logs:\n%s\n", controllerLogs)
+		} else {
+			_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Failed to get Controller logs: %s\n", err)
+		}
+	}
@@
-	ginkgo.By("Fetching controller manager pod description")
-	cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", controllerNamespace)
-	podDescription, err := utils.Run(cmd)
-	if err == nil {
-		_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Pod description:\n%s\n", podDescription)
-	} else {
-		_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Failed to describe controller pod: %s\n", err)
-	}
+	if controllerPodName != "" {
+		ginkgo.By("Fetching controller manager pod description")
+		cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", controllerNamespace)
+		podDescription, err := utils.Run(cmd)
+		if err == nil {
+			_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Pod description:\n%s\n", podDescription)
+		} else {
+			_, _ = fmt.Fprintf(ginkgo.GinkgoWriter, "Failed to describe controller pod: %s\n", err)
+		}
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/test_helpers.go` around lines 91 - 99, The current code returns
early on controller pod lookup failure (the err check and the len(podNames) == 0
check), which prevents later namespace owner/consumer event collection; remove
those two early returns and instead only log the error/notice via
ginkgo.GinkgoWriter (using the existing fmt.Fprintf calls) and let execution
continue so the namespace event collection runs; keep using
utils.GetNonEmptyLines(podOutput) and ensure any later code that assumes
podNames handles an empty slice gracefully (e.g., skip pod-specific steps but
still collect owner/consumer events).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/e2e/test_helpers.go`:
- Around line 60-71: CleanupNamespaces currently discards errors from utils.Run
when running "kubectl delete ns ..."; update the CleanupNamespaces function to
capture the output and error returned by utils.Run for each kubectl delete
invocation and, on non-nil error, fail the test with clear context (e.g., call
ginkgo.Fail or use ginkgo.Expect/Fail) including the command, stdout/stderr and
the error; reference the kubectl delete invocations inside CleanupNamespaces and
utils.Run to locate the calls to change.

---

Nitpick comments:
In `@test/e2e/test_helpers.go`:
- Around line 91-99: The current code returns early on controller pod lookup
failure (the err check and the len(podNames) == 0 check), which prevents later
namespace owner/consumer event collection; remove those two early returns and
instead only log the error/notice via ginkgo.GinkgoWriter (using the existing
fmt.Fprintf calls) and let execution continue so the namespace event collection
runs; keep using utils.GetNonEmptyLines(podOutput) and ensure any later code
that assumes podNames handles an empty slice gracefully (e.g., skip pod-specific
steps but still collect owner/consumer events).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d2f60552-da78-426c-b1a2-e32a7f68f384

📥 Commits

Reviewing files that changed from the base of the PR and between 93f23ec and 752916d.

📒 Files selected for processing (3)
  • test/e2e/automatic_approval_test.go
  • test/e2e/manual_workflow_test.go
  • test/e2e/test_helpers.go

Comment thread test/e2e/test_helpers.go Outdated
Signed-off-by: emmaaroche <eroche@redhat.com>
Copy link
Copy Markdown
Contributor

@eguzki eguzki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good

One minor thing commented. This should be good to go anyway.

Comment thread test/e2e/test_helpers.go
func CleanupNamespaces(ownerNamespace, consumerNamespace, kuadrantNamespace string) {
ginkgo.By("cleaning up kuadrant namespace")
cmd := exec.Command("kubectl", "delete", "ns", kuadrantNamespace, "--wait=false")
output, err := utils.Run(cmd)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: will fail the test if namespace deletion fails. Maybe namespaces are already deleted or in progress.

Signed-off-by: emmaaroche <eroche@redhat.com>
@emmaaroche emmaaroche requested a review from eguzki May 26, 2026 09:33
@eguzki eguzki merged commit b2ab687 into Kuadrant:main May 26, 2026
10 checks passed
@emmaaroche emmaaroche deleted the e2e-manual-approval-tests branch May 26, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add E2E tests for manual approval and rejection flows

2 participants