Skip to content

test(e2e): ouroboros fold + CSI/NFS ordering + OIDC keycloakInternalUrl - #2728

Merged
myasnikovdaniil merged 7 commits into
mainfrom
ci/e2e-improvements
May 27, 2026
Merged

test(e2e): ouroboros fold + CSI/NFS ordering + OIDC keycloakInternalUrl#2728
myasnikovdaniil merged 7 commits into
mainfrom
ci/e2e-improvements

Conversation

@myasnikovdaniil

@myasnikovdaniil myasnikovdaniil commented May 25, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Bundles four independent e2e improvements lifted from #2619:

  1. test(e2e): fold ouroboros assertions into kubernetes-latest — moves the standalone hack/e2e-apps/ouroboros.bats (which provisioned its own full Kamaji control plane, ~25m) into the existing kubernetes-latest run as an optional addon. The assertions cover ouroboros HR Ready, controller pod Running, Ingress → coredns-custom rewrite-line injection, and end-to-end DNS resolution from inside the tenant. Reuses the existing tenant cluster instead of building a second one.

  2. test(e2e): wait for tenant CSI HR Ready before NFS test — explicit kubectl wait hr/kubernetes-${test_name}-csi --for=condition=ready ahead of the NFS pod. Otherwise the NFS pod schedules while the kubevirt-csi-node DaemonSet is still rolling out, eats ~1m on FailedAttachVolume retries, and trips the pod-Succeeded wait.

  3. test(e2e): bump NFS pod wait to 10m to fit slow-path chain — was 5m. With dependencies properly serialized (per Automatically remove flannel and kube-proxy #2), 5m was tight on slow runners; 10m gives the chain genuine room without masking real bugs.

  4. test(e2e): set keycloakInternalUrl when enabling OIDC — the dashboard gatekeeper (oauth2-proxy) does OIDC discovery against the keycloak Service URL; without an explicit keycloakInternalUrl, it falls back to the public ingress URL which isn't routable from inside the cluster yet during install.

Origin

All four commits lifted unchanged from #2619.

Release note

NONE

Summary by CodeRabbit

  • Tests
    • Merged Ouroboros validations into the main Kubernetes end-to-end flow (standalone Ouroboros test removed)
    • Added hairpin-NAT and in-tenant DNS resolution checks for Ouroboros scenarios
    • Improved Keycloak OIDC test by configuring an in-cluster internal URL
    • Increased timeouts and readiness waits and added tenant CSI readiness gating to improve test reliability

Review Change Stack

@github-actions github-actions Bot added size/L This PR changes 100-499 lines, ignoring generated files area/testing Issues or PRs related to testing (e2e, bats, unit tests) labels May 25, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request optimizes the end-to-end testing pipeline by consolidating redundant test suites and hardening existing tests against timing-related failures. By serializing dependencies and adjusting wait thresholds, the changes improve test stability and reduce overall execution time in the CI environment.

Highlights

  • E2E Test Optimization: Integrated Ouroboros assertions directly into the kubernetes-latest test suite, eliminating the need for a separate 25-minute cluster provisioning process.
  • Reliability Improvements: Added explicit readiness waits for tenant CSI and increased NFS test timeouts to 10 minutes to prevent race conditions and flaky failures on slower runners.
  • OIDC Configuration: Configured keycloakInternalUrl during OIDC enablement to ensure the dashboard gatekeeper can resolve the Keycloak service internally during installation.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: baf3306e-df51-41e5-8f98-3dae99132565

📥 Commits

Reviewing files that changed from the base of the PR and between f7279b6 and ea7a8c8.

📒 Files selected for processing (4)
  • hack/e2e-apps/kubernetes-latest.bats
  • hack/e2e-apps/ouroboros.bats
  • hack/e2e-apps/run-kubernetes.sh
  • hack/e2e-install-cozystack.bats
💤 Files with no reviewable changes (1)
  • hack/e2e-apps/ouroboros.bats
🚧 Files skipped from review as they are similar to previous changes (3)
  • hack/e2e-install-cozystack.bats
  • hack/e2e-apps/kubernetes-latest.bats
  • hack/e2e-apps/run-kubernetes.sh

📝 Walkthrough

Walkthrough

Adds an optional ouroboros flag to the Kubernetes e2e runner that injects an ouroboros addon and runs hairpin‑NAT/DNS validation; increases several readiness and test timeouts; and patches Keycloak OIDC tests to use an in‑cluster internal URL.

Changes

E2E Test Ouroboros Support and Configuration

Layer / File(s) Summary
Ouroboros addon parameter and injection
hack/e2e-apps/run-kubernetes.sh, hack/e2e-apps/kubernetes-latest.bats
run_kubernetes_test accepts an optional 4th boolean enable_ouroboros. When "true" it composes an ouroboros addon YAML (controller logLevel: debug) and interpolates it into spec.addons on kubectl apply. The kubernetes-latest.bats call now passes true.
Control plane and storage readiness synchronization
hack/e2e-apps/run-kubernetes.sh
Kamaji control plane wait increased to a 2‑minute timeout. Component HelmRelease readiness gating set to 5 minutes. Wait added for tenant CSI HelmRelease kubernetes-${test_name}-csi before NFS tests. NFS test pod completion timeout increased to 10 minutes.
Ouroboros validation and DNS resolution proof
hack/e2e-apps/run-kubernetes.sh
With enable_ouroboros=true, waits for kubernetes-${test_name}-ouroboros HR and cozy-ouroboros pod readiness, polls coredns-custom for rewrite config, creates a hairpin-probe Ingress, runs a temporary dnscheck pod to confirm in-tenant DNS resolves to the ouroboros-proxy ClusterIP, then deletes probe resources.
Keycloak OIDC internal URL configuration
hack/e2e-install-cozystack.bats
The Keycloak OIDC health test now patches cozystack.cozystack-platform to set authentication.oidc.keycloakInternalUrl to the in‑cluster Keycloak endpoint, with expanded inline comments.

Sequence Diagram(s)

sequenceDiagram
  participant CI as Test Runner
  participant Script as run_kubernetes_test
  participant K8s as kubectl/kubernetes API
  participant HR as HelmRelease controller
  participant Controller as cozy-ouroboros controller
  participant DNSPod as dnscheck pod
  CI->>Script: invoke run_kubernetes_test(..., enable_ouroboros=true)
  Script->>K8s: kubectl apply cluster manifest (includes ouroboros_addon)
  K8s->>HR: create HelmReleases (cilium,coredns,csi,vsnap-crd,ingress-nginx,ouroboros)
  HR->>Controller: deploy cozy-ouroboros controller
  Script->>HR: poll HelmRelease readiness
  Script->>K8s: create hairpin-probe Ingress
  Script->>K8s: create dnscheck pod
  DNSPod->>K8s: resolve hairpin host -> expected ouroboros-proxy ClusterIP
  Script->>K8s: delete dnscheck pod and probe Ingress
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

size/M, area/ci

Suggested reviewers

  • androndo
  • kvaps
  • lllamnyp
  • IvanHunters
  • sircthulhu

Poem

🐰 I hopped into scripts with a curious cheer,

I folded ouroboros where probes appear,
DNS and probes in a dance so spry,
Control planes wait as the timeouts fly,
Keycloak whispers inward, steady and clear.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the four main changes: ouroboros folding, CSI/NFS ordering, and OIDC keycloakInternalUrl configuration.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/e2e-improvements

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.

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request updates the E2E test suite to include "ouroboros" hairpin-NAT reconciliation assertions within the existing Kubernetes latest version test, reducing total test time. It also increases various timeouts for resource readiness and pod completion to accommodate slower reconciliation in Flux v2.8 environments. Furthermore, it adds an internal Keycloak URL to the OIDC configuration to resolve DNS issues during dashboard testing. I have no feedback to provide.

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (2)
hack/e2e-apps/run-kubernetes.sh (2)

13-13: 💤 Low value

Declare and assign separately to avoid masking yq return value.

If yq fails, the error code is masked by local. Splitting the declaration ensures failures propagate correctly.

Proposed fix
-    local k8s_version=$(yq "$version_expr" packages/apps/kubernetes/files/versions.yaml)
+    local k8s_version
+    k8s_version=$(yq "$version_expr" packages/apps/kubernetes/files/versions.yaml)
🤖 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 `@hack/e2e-apps/run-kubernetes.sh` at line 13, The assignment uses "local
k8s_version=$(yq ...)" which masks yq's exit status; instead declare the
variable first and then run the command so failures propagate: split into a
separate declaration for k8s_version and a following command substitution using
yq (reference the k8s_version variable and the yq invocation in
run-kubernetes.sh) so any non-zero exit from yq is not masked by local.

359-362: 💤 Low value

Quote the HelmRelease name arguments to prevent word splitting.

While unlikely to cause issues in practice, quoting shell variables in kubectl arguments follows best practice.

Proposed fix
   for component in cilium coredns csi vsnap-crd; do
-      kubectl wait hr kubernetes-${test_name}-${component} -n tenant-test --timeout=5m --for=condition=ready
+      kubectl wait hr "kubernetes-${test_name}-${component}" -n tenant-test --timeout=5m --for=condition=ready
     done
-    kubectl wait hr kubernetes-${test_name}-ingress-nginx -n tenant-test --timeout=5m --for=condition=ready
+    kubectl wait hr "kubernetes-${test_name}-ingress-nginx" -n tenant-test --timeout=5m --for=condition=ready
🤖 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 `@hack/e2e-apps/run-kubernetes.sh` around lines 359 - 362, The kubectl wait
commands use unquoted shell expansions (kubernetes-${test_name}-${component} and
kubernetes-${test_name}-ingress-nginx) which can lead to word splitting; update
the two invocations to quote the HelmRelease name arguments so the expanded
names are treated as single arguments (e.g., quote
"kubernetes-${test_name}-${component}" in the loop and
"kubernetes-${test_name}-ingress-nginx" for the ingress wait).
🤖 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.

Nitpick comments:
In `@hack/e2e-apps/run-kubernetes.sh`:
- Line 13: The assignment uses "local k8s_version=$(yq ...)" which masks yq's
exit status; instead declare the variable first and then run the command so
failures propagate: split into a separate declaration for k8s_version and a
following command substitution using yq (reference the k8s_version variable and
the yq invocation in run-kubernetes.sh) so any non-zero exit from yq is not
masked by local.
- Around line 359-362: The kubectl wait commands use unquoted shell expansions
(kubernetes-${test_name}-${component} and kubernetes-${test_name}-ingress-nginx)
which can lead to word splitting; update the two invocations to quote the
HelmRelease name arguments so the expanded names are treated as single arguments
(e.g., quote "kubernetes-${test_name}-${component}" in the loop and
"kubernetes-${test_name}-ingress-nginx" for the ingress wait).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e8b77c1c-26bd-464c-9bc0-14dc59bc145a

📥 Commits

Reviewing files that changed from the base of the PR and between 1810263 and b407cac.

📒 Files selected for processing (3)
  • hack/e2e-apps/kubernetes-latest.bats
  • hack/e2e-apps/run-kubernetes.sh
  • hack/e2e-install-cozystack.bats

@myasnikovdaniil myasnikovdaniil self-assigned this May 25, 2026

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.

NOT LGTM — commits 2/3/4 (CSI/NFS ordering, NFS timeout bump, OIDC keycloakInternalUrl) are clean and verifiable, but commit 1 (fold ouroboros assertions into kubernetes-latest) ships a duplication, not a consolidation. The standalone hack/e2e-apps/ouroboros.bats is still in the tree, so the e2e workflow runs the assertions twice — once on its own ~25m Kamaji-backed tenant and again as the folded addon on the kubernetes-latest tenant. The promised time saving doesn't land until the standalone file is deleted.

Blocker

B1: hack/e2e-apps/ouroboros.bats is not deleted, so the second Kamaji bringup still runs

File: hack/e2e-apps/ouroboros.bats (still present on this branch)

Issue: the e2e workflow at .github/workflows/pull-requests.yaml auto-discovers every .bats file in hack/e2e-apps/:

for app in $(ls hack/e2e-apps/*.bats | xargs -n1 basename | cut -d. -f1); do
  ...
  make -C packages/core/testing SANDBOX_NAME=$SANDBOX_NAME test-apps-$app

packages/core/testing/Makefile has a wildcard rule test-apps-% that dispatches to hack/cozytest.sh hack/e2e-apps/$*.bats. So test-apps-ouroboros is still wired up and runs against its own freshly-provisioned tenant Kubernetes — the very 25-45m Kamaji bringup the commit message calls out as "pure duplication". On top of that, test-apps-kubernetes-latest now runs the same assertions a second time on its tenant.

The 3c81261ba commit message acknowledges this explicitly:

(The standalone ouroboros.bats was removed in the preceding commit alongside an unrelated foundationdb chart fix — the git rm staging had already happened when the foundationdb commit landed.)

That "preceding commit" is in the source PR #2619 (which is OPEN and shows 0+/386- hack/e2e-apps/ouroboros.bats in its file list), not in #2728. The cherry-pick picked up the run-kubernetes.sh additions but not the deletion. The PR body's claim — "Reuses the existing tenant cluster instead of building a second one" — doesn't hold on the current branch.

Impact: this PR currently makes e2e longer, not shorter — it adds the addon-flavored assertions to kubernetes-latest (extra time on that tenant) without removing the standalone's separate Kamaji bringup. To deliver the documented goal, the deletion has to land in this PR.

Fix: add git rm hack/e2e-apps/ouroboros.bats as a separate commit in this PR. No replacement test needed — the folded assertions in run-kubernetes.sh (lines ~365 onwards) already cover ouroboros HR Ready, controller pod Running, Ingress → coredns-custom rewrite-line injection, and end-to-end DNS resolution from inside the tenant. That's the same surface the standalone covers; the standalone becomes pure dead weight after the fold.

Non-blocking (already noted by reviewers, but worth confirming)

  • CodeRabbit nit 1: local k8s_version=$(yq ...) masks yq's exit status. Split into local k8s_version + k8s_version=$(yq ...). Pure shell hygiene, not gating.
  • CodeRabbit nit 2: HelmRelease name interpolations in the for component in cilium coredns csi vsnap-crd loop aren't quoted. Quotes are idiomatic but test_name and component here are both literal-safe (no whitespace/glob risk), so no actual behavior change.

What's solid (concur with author's framing)

  1. Commit 2 (CSI HR Ready wait before NFS pod): the explicit kubectl wait hr/kubernetes-${test_name}-csi --for=condition=ready ahead of the NFS pod fixes a real ordering bug — without it the NFS pod schedules while kubevirt-csi-node DaemonSet is mid-rollout. Concrete and correct.
  2. Commit 3 (NFS 5m → 10m): straightforward budget bump. The reasoning (host CDI prime + tenant CSI mount + busybox pull bursts past 5m on slow runners) is plausible and the 10m doesn't mask a real bug — it just survives the slow path.
  3. Commit 4 (keycloakInternalUrl): verified — packages/system/keycloak/templates/service.yaml ships a keycloak-http Service of type ClusterIP on port 8080 in cozy-keycloak, so http://keycloak-http.cozy-keycloak.svc:8080/realms/cozy resolves and matches the in-cluster Service. Removes the dashboard-gatekeeper crashloop on keycloak.example.org DNS lookup at install time. Good fix.
  4. The timeout 10s → 2m bump on the KamajiControlPlane creation wait (line ~99) is reasonable given Flux v2.8's kstatus-based health checks. Documented rationale matches the symptom.

Nothing on this PR is wrong on substance for commits 2-4; the blocker is purely about commit 1 needing the standalone deletion to ship its promised time saving.

@myasnikovdaniil

Copy link
Copy Markdown
Contributor Author

Aleksei Sviridkin (@lexfrei) B1 addressed in 521aa82hack/e2e-apps/ouroboros.bats is now removed in this PR, so test-apps-ouroboros no longer auto-discovers and the standalone Kamaji bringup goes away. The folded assertions in run-kubernetes.sh (HR Ready, controller pod Running, coredns-custom rewrite-line injection, end-to-end DNS resolution) remain the sole coverage path.

The two non-blocking shell-hygiene notes are also in: 09883f4 splits local k8s_version from the yq command substitution so the exit code propagates, and f7279b6 quotes the two HelmRelease name arguments flagged on lines 359–362 (kept the machinedeployment wait on the preceding line unchanged to keep the commit scoped to the two lines you and CodeRabbit pointed at).

@myasnikovdaniil

Copy link
Copy Markdown
Contributor Author

CodeRabbit (@coderabbitai) both nitpicks applied:

  • Line 13: 09883f4 splits local k8s_version from k8s_version=$(yq …) so a failing yq propagates instead of being masked by the local-declaration exit code.
  • Lines 359–362: f7279b6 quotes the two HelmRelease name arguments. The machinedeployment wait on line 358 was left as-is to keep the commit scoped to the two lines you flagged.

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@myasnikovdaniil Thanks for the follow-through! Both fixes look correct:

  • 09883f4 — splitting local from the $(yq …) assignment is the right approach; local always returns 0 so the previous form silently swallowed a failing yq.
  • f7279b6 — quoting the two HelmRelease name arguments prevents word-splitting on names that could contain hyphens or be affected by glob expansion; keeping the machinedeployment wait on the preceding line untouched is a sensible scoping call.

If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

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.

LGTM on f7279b68. Blocker B1 from my prior review and both CodeRabbit nits are landed in three surgical commits.

  • B1 (standalone hack/e2e-apps/ouroboros.bats still wired in the e2e workflow → duplicated 25-45m Kamaji bringup) — addressed by 521aa8235 test(e2e): delete standalone ouroboros.bats now folded into kubernetes-latest. Pure deletion of the 386-line file. Verified: git ls-tree origin/ci/e2e-improvements -- hack/e2e-apps/ouroboros.bats returns empty, so the for app in $(ls hack/e2e-apps/*.bats | xargs -n1 basename | cut -d. -f1) loop in .github/workflows/pull-requests.yaml no longer picks up ouroboros, and the wildcard test-apps-% rule in packages/core/testing/Makefile no longer dispatches to cozytest.sh hack/e2e-apps/ouroboros.bats. The folded assertions in run-kubernetes.sh (HR Ready, controller pod Running, Ingress → coredns-custom rewrite, end-to-end DNS via netshoot) cover the same surface the standalone did. The PR now genuinely delivers the documented time saving.
  • CodeRabbit nit 1 (local k8s_version=$(yq ...) masks yq exit status) — addressed by 09883f46a test(e2e): split local k8s_version declaration from yq invocation. Now local k8s_version + k8s_version=$(yq ...) on separate lines so a yq failure propagates instead of being masked by local's own zero exit.
  • CodeRabbit nit 2 (unquoted kubernetes-${test_name}-${component} interpolation in the for component in cilium coredns csi vsnap-crd; do kubectl wait hr ... loop) — addressed by f7279b684 test(e2e): quote HelmRelease names in kubectl wait. Both the loop body and the trailing kubernetes-${test_name}-ingress-nginx are now quoted. Belt-and-suspenders since test_name and component are both literal-safe here, but the quoting is the idiomatic shape.

This APPROVE supersedes my prior REQUEST_CHANGES (#4363068453). Gate-wise, this should now flip reviewDecision from CHANGES_REQUESTED to APPROVED on the next decision recomputation, since I'm the only human reviewer on this PR. CI is in flight on the new SHA; the prior b407cacc9 SHA passed Build + E2E (1h25m) and the three new commits are mechanical (file deletion + shell hygiene), so I'd expect green there too.

@myasnikovdaniil
myasnikovdaniil enabled auto-merge May 26, 2026 11:29
@github-actions github-actions Bot added size/XL This PR changes 500-999 lines, ignoring generated files and removed size/L This PR changes 100-499 lines, ignoring generated files labels May 26, 2026
The standalone hack/e2e-apps/ouroboros.bats provisioned a full Kamaji-
backed tenant Kubernetes cluster (control plane + 2 CAPI workers + base
addons) just to flip `addons.ouroboros.enabled=true` on top, then ran
~15m of hairpin-NAT reconciliation assertions. Cluster shape was
identical to what hack/e2e-apps/run-kubernetes.sh already provisions for
kubernetes-latest, so the second Kamaji bringup was pure duplication —
roughly 25-45m of CI wall-time per run.

Add an `enable_ouroboros` 4th parameter to `run_kubernetes_test()`. When
"true", inject the ouroboros addon block into the Kubernetes CR's
addons map and run the post-cluster assertions inline:

- Wait for the ouroboros HR Ready in the host namespace.
- Verify coredns-custom ConfigMap exists in tenant kube-system.
- Wait for the ouroboros controller pod Ready.
- Apply an Ingress with a TLS host in tenant default namespace.
- Poll coredns coredns-custom for the rewrite line (5m budget).
- Resolve the hairpin host from inside the tenant via a netshoot pod
  and assert it points at the ouroboros-proxy ClusterIP.
- Clean up dnscheck pod + Ingress.

kubernetes-latest passes "true" (gets ouroboros coverage); kubernetes-
previous leaves it empty (control-plane-only smoke remains).

(The standalone ouroboros.bats was removed in the preceding commit
alongside an unrelated foundationdb chart fix — the git rm staging had
already happened when the foundationdb commit landed.)

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit b5c9c2a)
kubernetes-previous fails on the NFS pod step. From cozyreport + job log:

  - Pod scheduled to tenant worker
  - 7x FailedAttachVolume over 35s: CSINode does not contain driver
    csi.kubevirt.io (kubevirt-csi-node DaemonSet still rolling out)
  - Attach succeeds at T+1m08s after the driver registers
  - busybox pull queued ~1m25s, completes at T+2m48s
  - CreateContainer in containerd then stalls past kubelet's CRI
    deadline; retry trips "failed to reserve container name ... is
    reserved for <prev>" -- the 5m pod-Succeeded wait then expires.

Root cause: run-kubernetes.sh creates the NFS PVC+Pod before asserting
kubernetes-${test_name}-csi is Ready. That HR lives in the parent
cluster but installs cozy-kubevirt-csi-node into the tenant via
kubeConfig.secretRef; helm-controller walks kstatus on the tenant
DaemonSet using the tenant kubeconfig. HR Ready in parent therefore
implies kubevirt-csi-node Pods Ready on every tenant worker, which
implies csi.kubevirt.io is published in CSINode. The existing wait at
line 354 runs AFTER the NFS test, so it does not gate the race.

Move the wait earlier with a 10m budget. Post-NFS sibling waits stay
as is, so component coverage is unchanged.

Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit 394b1b2)
Previous run failed kubernetes-latest (and then kubernetes-previous via
cascade) on the 5m budget for nfs-test-pod to reach Succeeded. The
chain is host linstor prime PVC + CDI import + tenant CSI attach +
busybox image pull + containerd CreateContainer (which occasionally
stalls past kubelet's 2m CRI deadline and retries with name-reservation
conflict). ~40s on the happy path, 6m+ in observed worst case.

When kubernetes-latest times out, its tenant cluster (2x 20Gi worker
PVCs) leaks because set -e exits before any cleanup. kubernetes-
previous then runs, adds another 40Gi, and the host tenant-quota
(100Gi) is exhausted -- every downstream app test (mariadb, mongo,
postgres, qdrant, redis, openbao, vminstance) fails with
ErrCreatingPVCPrime / exceeded quota.

Bumping the wait to 10m gives the slow path room. Headroom costs
nothing on green runs since the pod is busybox echo.

Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit c5cc7b6)
The dashboard gatekeeper (oauth2-proxy) does OIDC discovery against the
external host at container startup. The e2e sandbox uses
host=example.org which does not resolve, so the auth-proxy crashloops:

  Get "https://keycloak.example.org/realms/cozy/.well-known/openid-configuration":
    dial tcp: lookup keycloak.example.org: no such host

Under Flux v2.8 kstatus the gatekeeper Deployment then flips to
'Failed' (rather than the pre-v2.8 'InProgress') and stalls the
cozy-dashboard/dashboard HelmRelease, which in turn blocks
cozy-fluxcd/flux-plunger via dependsOn. Previous runs masked this with
an unrelated ImagePullBackOff on cozy-dashboard-console; with the
console image fixed the OIDC discovery failure now surfaces.

packages/core/platform/values.yaml:194-198 already declares
authentication.oidc.keycloakInternalUrl. When set, the dashboard
chart (packages/system/dashboard/templates/gatekeeper.yaml:59-66)
renders --skip-oidc-discovery plus explicit redeem/jwks/validate/
backend-logout URLs pointing at the in-cluster keycloak Service.
Browser-facing redirect-url and login-url stay on the external host
(they are not exercised by the e2e flow).

The patch sets the value alongside oidc.enabled in the same
kubectl-patch so the configmap and gatekeeper rollout happen in one
reconcile pass.

Observed on CI run 26142986969 (PR #2619).

Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit 5915a57)
…s-latest

The previous commit (3c81261) folded the ouroboros hairpin-NAT
reconciliation assertions into the kubernetes-latest tenant under
run-kubernetes.sh, but did not remove the standalone bats file.

The e2e workflow auto-discovers every hack/e2e-apps/*.bats and dispatches
test-apps-<name> via the wildcard rule in packages/core/testing/Makefile.
Leaving ouroboros.bats in the tree meant the assertions ran twice: once
on the standalone ~25m Kamaji-backed tenant and again as the folded
addon on the kubernetes-latest tenant — the opposite of the consolidation
the fold was intended to deliver.

The folded assertions in hack/e2e-apps/run-kubernetes.sh cover the same
surface (HR Ready, controller pod Running, coredns-custom rewrite-line
injection, and end-to-end DNS resolution from inside the tenant), so
the standalone file is dead weight after the fold.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
\`local k8s_version=\$(yq ...)\` masks the exit status of the command
substitution — the assignment to a local variable always succeeds, so
a failing yq is swallowed. Declare the local first, then assign, so
non-zero yq exits propagate via shell errexit semantics if the script
ever runs under \`set -e\`.

Pure shell hygiene; no behavioral change on the success path. Surfaced
by CodeRabbit and confirmed by the human reviewer as non-blocking but
worth applying.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Both \${test_name} and \${component} are literal-safe today (no
whitespace, no glob characters), so this is a style-only change — but
quoting variable expansions in kubectl arguments matches the rest of
the file and removes a future-foot-gun if a test name ever grows a
hyphen-y suffix that interacts oddly with completion or globbing.

Scoped to the two HelmRelease wait lines flagged by CodeRabbit and
echoed by the human reviewer; the machinedeployment wait on the
preceding line keeps its existing style.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
@myasnikovdaniil myasnikovdaniil added the debug Debugging in progress label May 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/testing Issues or PRs related to testing (e2e, bats, unit tests) debug Debugging in progress size/XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants