Skip to content

fix(e2e): drain tenant VMs/PVCs between kubernetes tests to fix the node-join flake - #3159

Merged
Aleksei Sviridkin (lexfrei) merged 2 commits into
mainfrom
fix/e2e-tenant-cleanup-vm-drain
Jul 1, 2026
Merged

Aleksei Sviridkin (lexfrei) merged 2 commits into
mainfrom
fix/e2e-tenant-cleanup-vm-drain

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Jun 30, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

Fixes the dominant flake in the tenant-Kubernetes e2e suite, where a run fails on worker-node-join under sandbox memory/storage pressure.

The two heavy Kamaji tenant tests — kubernetes-latest then kubernetes-previous — run back-to-back in one CI sandbox, each provisioning a tenant cluster with KubeVirt worker VMs. The inter-test cleanup hook (cozy_cleanup in hack/e2e-apps/run-kubernetes.sh) deletes the tenant Kubernetes CR and waits only for the CR to disappear. That wait finalizes as soon as the CR's finalizers clear, which merely triggers teardown of the CAPK worker VMs and their DataVolume-backed disk PVCs — it does not await it. The virt-launcher pods keep their guest RAM reserved until the VMIs are gone, so the next tenant test's worker VMs begin scheduling against a sandbox the previous tenant has not yet vacated. Under the constrained sandbox this starves memory, a worker VM misses the node-join budget, and the MachineHealthCheck cannot remediate when both workers are unhealthy — so the run flakes on worker-node-join.

This adds a bounded drain barrier to cozy_cleanup: after deleting the CR it now blocks until the tenant's VirtualMachines, VirtualMachineInstances and disk PVCs have actually drained from the tenant-test namespace, so the next test starts on a freed sandbox.

The wait is bounded (5m) and best-effort: cozytest already runs cozy_cleanup wrapped in || true, and the waiter returns loudly (warning plus a leftover dump) on timeout, so a stuck teardown can never hang the job past the deadline — it leaves the sandbox no worse than before. The probe is namespace-scoped: tenant-test is provisioned with etcd/monitoring/seaweedfs disabled so it carries no baseline PVCs, and the e2e apps run sequentially each cleaning up after themselves, so the only VMs/VMIs/PVCs present belong to the tenant being torn down.

The pure drain exit-condition (cozy_tenant_drained) is factored out and unit-tested in hack/run-kubernetes-drain_test.bats (runs under make unit-tests), including the invariant that a failed probe's err sentinel is never misread as a completed drain.

Screenshots

Not applicable — e2e harness change, no UI.

Release note

NONE

Summary by CodeRabbit

  • Bug Fixes
    • Improved Kubernetes test cleanup so tenant resources are fully drained before the next test starts, reducing leftover VMs, VM instances, and PVCs.
    • Added more reliable timeout handling and clearer diagnostics when teardown or node readiness checks fail, making flaky test issues easier to identify.
  • Tests
    • Added coverage for tenant-drain detection to verify empty, whitespace-only, multi-resource, and error scenarios behave as expected.

The inter-test cleanup hook deletes the tenant Kubernetes CR and waits
only for the CR to disappear. That wait finalizes as soon as the CR's
finalizers clear, which merely TRIGGERS teardown of the CAPK worker VMs
and their DataVolume-backed disk PVCs -- it does not await it. The
virt-launcher pods keep their guest RAM reserved until the VMIs are
gone, so the next back-to-back tenant test's worker VMs begin scheduling
against a sandbox the previous tenant has not yet vacated. Under the
constrained CI sandbox this starves memory, a worker VM misses the
node-join budget, and the run flakes on worker-node-join (the
MachineHealthCheck cannot remediate when both workers are unhealthy).

Block cozy_cleanup until the tenant VMs, VMIs and disk PVCs have
actually drained from tenant-test before it returns, so the next test
starts on a freed sandbox. The wait is bounded (5m) and best-effort:
cozytest runs cozy_cleanup wrapped in `|| true` and the waiter returns
loudly on timeout, so a stuck teardown can never hang the job longer
than the deadline. The probe is namespace-scoped -- tenant-test is
provisioned with etcd/monitoring/seaweedfs disabled so it carries no
baseline PVCs, and e2e apps run sequentially each cleaning up after
themselves, so the only VMs/VMIs/PVCs present belong to the tenant being
torn down.

The pure drain exit-condition (cozy_tenant_drained) is unit-tested in
hack/run-kubernetes-drain_test.bats, including the invariant that a
failed probe's "err" sentinel is never misread as a completed drain.

Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
@github-actions github-actions Bot added area/testing Issues or PRs related to testing (e2e, bats, unit tests) kind/bug Categorizes issue or PR as related to a bug size/L This PR changes 100-499 lines, ignoring generated files labels Jun 30, 2026
@coderabbitai

coderabbitai Bot commented Jun 30, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a whitespace-only drain predicate (cozy_tenant_drained) and a bounded polling wait (cozy_wait_tenant_drained) for tenant VMs/VMIs/PVCs to the Kubernetes e2e script, wires it into cleanup teardown, expands node-join failure diagnostics, and adds a bats test suite covering the predicate's behavior.

Changes

Tenant Drain Wait and Diagnostics

Layer / File(s) Summary
Drain predicate and polling wait
hack/e2e-apps/run-kubernetes.sh
Adds cozy_tenant_drained to treat whitespace-only captures as drained and non-empty/"err" captures as not drained, and cozy_wait_tenant_drained to poll VMs/VMIs/PVCs with a timeout, emitting warnings and diagnostics on failure.
Cleanup wiring and failure diagnostics
hack/e2e-apps/run-kubernetes.sh
cozy_cleanup now calls cozy_wait_tenant_drained 300 || true after deleting the tenant CR; node-join failure handling is restructured to capture worker VM/VMI/virt-launcher/pod state and tenant CSR/talos-csr-signer logs instead of the prior simple describe/hr output.
Bats tests for drain predicate
hack/run-kubernetes-drain_test.bats
New test suite validates cozy_tenant_drained across empty, no-argument, remaining-resource, PVC-remaining, multi-line, "err" sentinel, and whitespace-only scenarios.

Sequence Diagram(s)

sequenceDiagram
  participant cozy_cleanup
  participant cozy_wait_tenant_drained
  participant cozy_tenant_drained
  participant KubernetesAPI

  cozy_cleanup->>cozy_wait_tenant_drained: cozy_wait_tenant_drained 300
  loop until drained or timeout
    cozy_wait_tenant_drained->>KubernetesAPI: probe VMs, VMIs, PVCs
    KubernetesAPI-->>cozy_wait_tenant_drained: resource captures
    cozy_wait_tenant_drained->>cozy_tenant_drained: check whitespace-only
    cozy_tenant_drained-->>cozy_wait_tenant_drained: drained / not-drained
  end
  cozy_wait_tenant_drained-->>cozy_cleanup: success or timeout warning
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Suggested labels

kind/cleanup, size/M

Suggested reviewers

  • kvaps
  • lllamnyp
  • androndo
  • IvanHunters
  • sircthulhu
  • myasnikovdaniil

Poem

A rabbit watched the VMs fade,
No more phantom pods delayed,
With whitespace checks so clean and neat,
I hop and thump my little feet! 🐰
Drained at last, the tenant's clear—
Next test starts without a fear!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.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 clearly summarizes the main change: draining tenant VMs/PVCs between kubernetes e2e tests to address the node-join flake.
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.
✨ 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 fix/e2e-tenant-cleanup-vm-drain

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.

When a tenant Kubernetes cluster hits the 12m node-Ready deadline with
fewer than two nodes joined, the failure path dumped only `describe
nodes` and `get hr`. That cannot tell apart the two node-join failure
sub-modes: a worker VM that never booted (virt-launcher Pending or
OOMKilled) versus a VM that booted fine but whose kubelet never
registered a Node. The tenant cilium-operator HelmRelease reports
"InProgress" identically in both, so the current dump is not enough to
diagnose the failure or design a fix.

Dump scoped, guarded diagnostics before failing fast:
- worker VM/VMI/virt-launcher state on the management cluster, which is
  what actually splits the two sub-modes;
- tenant kubelet CSRs plus the talos-csr-signer sidecar log, which reveal
  a boot-but-no-Node stall.

In-guest Talos/kubelet capture is deliberately left out: talosctl needs a
tenant-cluster talosconfig the runner does not have (the tenant workers
use a separate Talos CA from the management sandbox), so the gap is
documented in the failure path rather than shipped as a call that would
fail mTLS and capture nothing.

Every capture is guarded with `|| true` so a capture failure never masks
the real exit.

Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
@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 addresses a recurring flake in the tenant-Kubernetes e2e suite caused by resource contention in the sandbox. By implementing a wait mechanism that ensures complete teardown of tenant infrastructure between sequential tests, the change prevents memory and storage starvation for subsequent test runs. Additionally, it improves diagnostic logging for node-join failures to facilitate faster debugging of future issues.

Highlights

  • Inter-test cleanup improvement: Added a bounded drain barrier to the cozy_cleanup process to ensure tenant VirtualMachines, VirtualMachineInstances, and PVCs are fully removed before the next test begins.
  • Improved failure diagnostics: Enhanced the node-join failure reporting to provide detailed state captures of VMs, pods, and CSRs, helping to distinguish between boot failures and registration issues.
  • Unit testing: Introduced a new BATS test file to verify the drain logic, ensuring that transient API errors are correctly handled and do not trigger premature test execution.
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. ↩

@dosubot dosubot Bot added the kind/flake Categorizes issue or PR as related to a flaky test label Jul 1, 2026

@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 introduces a mechanism to wait for tenant KubeVirt VMs, VMIs, and PVCs to be fully drained during teardown in hack/e2e-apps/run-kubernetes.sh to prevent resource starvation and flakes in subsequent tests. It also adds detailed diagnostic outputs on node-join failures and includes Bats unit tests for the new cozy_tenant_drained helper in hack/run-kubernetes-drain_test.bats. The reviewer feedback points out that several variables in the newly added shell functions (cozy_tenant_drained and cozy_wait_tenant_drained) are not declared as local, which can cause them to leak into the global environment of the calling shell when the script is sourced.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +12 to +19
cozy_tenant_drained() {
for _capture in "$@"; do
case "$_capture" in
*[![:space:]]*) return 1 ;;
esac
done
return 0
}

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.

medium

The loop variable _capture is not declared as local. Since this script is sourced by other test scripts, failing to declare variables as local causes them to leak into the global shell environment, which can lead to unexpected side effects or name collisions.

Suggested change
cozy_tenant_drained() {
for _capture in "$@"; do
case "$_capture" in
*[![:space:]]*) return 1 ;;
esac
done
return 0
}
cozy_tenant_drained() {
local _capture
for _capture in "$@"; do
case "$_capture" in
*[![:space:]]*) return 1 ;;
esac
done
return 0
}

Comment on lines +39 to +58
cozy_wait_tenant_drained() {
_ns=tenant-test
_timeout="${1:-300}"
_deadline=$(( $(date +%s) + _timeout ))
while :; do
_vm=$(kubectl -n "$_ns" get virtualmachines.kubevirt.io -o name 2>/dev/null) || _vm=err
_vmi=$(kubectl -n "$_ns" get virtualmachineinstances.kubevirt.io -o name 2>/dev/null) || _vmi=err
_pvc=$(kubectl -n "$_ns" get pvc -o name 2>/dev/null) || _pvc=err
if cozy_tenant_drained "$_vm" "$_vmi" "$_pvc"; then
echo "» tenant VMs/VMIs/PVCs drained from $_ns"
return 0
fi
if [ "$(date +%s)" -ge "$_deadline" ]; then
echo "» WARNING: tenant teardown did not drain within ${_timeout}s; continuing (next test may face memory/storage pressure)" >&2
kubectl -n "$_ns" get virtualmachines.kubevirt.io,virtualmachineinstances.kubevirt.io,pvc 2>&1 | sed 's/^/ drain-leftover: /' >&2 || true
return 1
fi
sleep 5
done
}

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.

medium

The variables _ns, _timeout, _deadline, _vm, _vmi, and _pvc are not declared as local. Since this script is sourced, these variables will leak into the global environment of the calling shell, potentially causing conflicts with other scripts or tests.

cozy_wait_tenant_drained() {
  local _ns=tenant-test
  local _timeout="${1:-300}"
  local _deadline=$(( $(date +%s) + _timeout ))
  local _vm _vmi _pvc
  while :; do
    _vm=$(kubectl -n "$_ns" get virtualmachines.kubevirt.io -o name 2>/dev/null) || _vm=err
    _vmi=$(kubectl -n "$_ns" get virtualmachineinstances.kubevirt.io -o name 2>/dev/null) || _vmi=err
    _pvc=$(kubectl -n "$_ns" get pvc -o name 2>/dev/null) || _pvc=err
    if cozy_tenant_drained "$_vm" "$_vmi" "$_pvc"; then
      echo "» tenant VMs/VMIs/PVCs drained from $_ns"
      return 0
    fi
    if [ "$(date +%s)" -ge "$_deadline" ]; then
      echo "» WARNING: tenant teardown did not drain within ${_timeout}s; continuing (next test may face memory/storage pressure)" >&2
      kubectl -n "$_ns" get virtualmachines.kubevirt.io,virtualmachineinstances.kubevirt.io,pvc 2>&1 | sed 's/^/  drain-leftover: /' >&2 || true
      return 1
    fi
    sleep 5
  done
}

@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)

39-58: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Scope the polling loop's scratch variables with local.

_ns, _timeout, _deadline, _vm, _vmi, _pvc are all unscoped, inconsistent with the local-based convention used throughout run_kubernetes_test in this same file. Given cozy_cleanup/cozy_wait_tenant_drained run in the same shell as the rest of the cozytest hooks, these generic names (especially _ns, _deadline) are collision-prone with future additions.

♻️ Proposed fix
 cozy_wait_tenant_drained() {
+  local _ns _timeout _deadline _vm _vmi _pvc
   _ns=tenant-test
   _timeout="${1:-300}"
🤖 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 39 - 58, The polling helper
cozy_wait_tenant_drained currently uses unscoped scratch variables (_ns,
_timeout, _deadline, _vm, _vmi, _pvc), which can collide with other shell state
in the same process. Update cozy_wait_tenant_drained to declare these temporary
values with local, matching the convention used in run_kubernetes_test, and keep
the rest of the loop logic unchanged so the function’s behavior stays the same
while avoiding variable leakage.

12-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Declare _capture as local.

cozy_tenant_drained doesn't scope _capture with local, unlike the rest of this file's functions (e.g. run_kubernetes_test uses local version_expr, local k8s_version, etc.). Since this is bash (per the local usage elsewhere), an unscoped loop variable leaks into the caller's shell/global namespace and could collide with a same-named variable in another cozytest-sourced function running in the same shell.

♻️ Proposed fix
 cozy_tenant_drained() {
+  local _capture
   for _capture in "$@"; do
     case "$_capture" in
       *[![:space:]]*) return 1 ;;
     esac
   done
   return 0
 }
🤖 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 12 - 19, The
cozy_tenant_drained function leaks its loop variable into the caller’s shell
because _capture is not scoped locally. Update cozy_tenant_drained in
run-kubernetes.sh to declare _capture with local before the loop, matching the
style used by run_kubernetes_test and the other bash helpers, so the variable
stays confined to the function.
🤖 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`:
- Around line 39-58: The polling helper cozy_wait_tenant_drained currently uses
unscoped scratch variables (_ns, _timeout, _deadline, _vm, _vmi, _pvc), which
can collide with other shell state in the same process. Update
cozy_wait_tenant_drained to declare these temporary values with local, matching
the convention used in run_kubernetes_test, and keep the rest of the loop logic
unchanged so the function’s behavior stays the same while avoiding variable
leakage.
- Around line 12-19: The cozy_tenant_drained function leaks its loop variable
into the caller’s shell because _capture is not scoped locally. Update
cozy_tenant_drained in run-kubernetes.sh to declare _capture with local before
the loop, matching the style used by run_kubernetes_test and the other bash
helpers, so the variable stays confined to the function.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f333729e-dd4e-4c50-805a-0e4cbbf4bc0f

📥 Commits

Reviewing files that changed from the base of the PR and between 20e4eab and d54e3e4.

📒 Files selected for processing (2)
  • hack/e2e-apps/run-kubernetes.sh
  • hack/run-kubernetes-drain_test.bats

@IvanHunters IvanHunters left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verdict

LGTM

The drain barrier is correct, bounded, and best-effort; the critical err-sentinel invariant holds and is unit-tested, so the barrier cannot silently degrade into a no-op — no blocking issues found.

Findings

None.

The change was verified end to end:

  • All 7 unit tests pass under the real runner (hack/cozytest.sh hack/run-kubernetes-drain_test.bats), 0 failures.
  • The new code (cozy_tenant_drained, cozy_wait_tenant_drained) introduces zero shellcheck findings — every shellcheck hit on run-kubernetes.sh is on pre-existing lines (SC3043 local, SC2034 port, SC2086 on ${test_name}), none in the added ranges.
  • err-sentinel path traced: _vm=$(kubectl ... 2>/dev/null) || _vm=err sets the literal err only on a non-zero kubectl exit; cozy_tenant_drained matches err under *[![:space:]]* and returns not-drained. Empty stdout from a successful probe is whitespace and reads as drained; empty stdout from a failed probe becomes err and does not. The "barrier is a no-op → PR fails to fix the flake" failure mode does not occur.
  • Bounded wait confirmed: _deadline computed once from date +%s, timeout branch returns 1 loudly with a drain-leftover: dump to stderr, and cozy_cleanup calls it as cozy_wait_tenant_drained 300 || true. cozytest.sh additionally runs the whole cozy_cleanup under || true, so it can never hang or fail the job past 5m.
  • cozy_cleanup is a file-scope function; cozytest.sh's parent-shell EXIT trap does command -v cozy_cleanup && cozy_cleanup || true — confirmed in the runner source.
  • The unit test sources run-kubernetes.sh inside each @test body, which runs in a subshell in run_one, so cozy_cleanup does NOT leak into the unit-test runner's parent EXIT trap — make unit-tests will not trigger any cluster teardown.

Claim mismatches

None. All PR-body claims verified [OK]:

  • "wait finalizes as soon as the CR disappears but does not await VM/PVC teardown" [OK] — kubectl wait --for=delete on the Kubernetes CR returns on finalizer clearance; CAPK/KubeVirt child VMs/VMIs and DataVolume-backed PVCs are torn down asynchronously by their own controllers, outliving CR removal.
  • "barrier blocks until VMs/VMIs/disk PVCs drain from tenant-test" [OK] — namespace-scoped probes on virtualmachines.kubevirt.io, virtualmachineinstances.kubevirt.io, pvc.
  • "bounded 5m and best-effort" [OK].
  • "cozy_tenant_drained factored out and unit-tested including the err-sentinel invariant" [OK] — 7 passing tests including the err case.
  • "tenant-test provisioned with etcd/monitoring/seaweedfs disabled, no baseline PVCs" [OK] — confirmed at hack/e2e-install-cozystack.bats:307-321 (etcd: false, monitoring: false, seaweedfs: false).
  • release-note block present (NONE).

Operational risks

None that block. The best-effort-on-timeout is a deliberate design: on a genuine teardown regression the barrier will not fail CI, it warns and dumps leftovers. This is acceptable for an inter-test cleanup hook (its job is to free the sandbox, not to gate on teardown health), and the loud stderr warning + drain-leftover: dump keeps a real regression visible in CI logs. Worth a one-line acknowledgement that this hook will not turn a teardown regression red — but not a defect.

Nitpick (non-blocking)

  • hack/e2e-apps/run-kubernetes.sh — the scratch variables in cozy_tenant_drained (_capture) and cozy_wait_tenant_drained (_ns, _timeout, _deadline, _vm, _vmi, _pvc) are not declared local. Since these functions run in the same shell as the other cozytest hooks, the generic names are collision-prone. Declaring them local matches the convention used by run_kubernetes_test in the same file.

Caveats

  • No packages/ touched — files are exactly hack/e2e-apps/run-kubernetes.sh and hack/run-kubernetes-drain_test.bats. Blast radius is CI-only; zero customer-cluster upgrade or fresh-install impact.
  • The new bats file is auto-discovered by make unit-tests via BATS_UNIT_FILES := $(filter-out hack/e2e-%.bats,$(wildcard hack/*.bats)) — it matches hack/*.bats and is not an e2e- file, so it is picked up. It defines no setup_file/setup/teardown hooks (which cozytest.sh ignores anyway), so no dead-code hooks were introduced.

Recommended follow-ups

  • hack/e2e-apps/vminstance.bats also provisions KubeVirt VMs in tenant-test, but it deletes its vminstances.apps.cozystack.io/vmdisks.apps.cozystack.io CRs inline with blocking kubectl delete --timeout=3m and is a single lightweight VM — it does not exhibit the back-to-back Kamaji-tenant RAM-starvation pattern this PR targets. No shared helper is warranted now; no action needed unless that test later grows heavier VM footprints.

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) kind/bug Categorizes issue or PR as related to a bug kind/flake Categorizes issue or PR as related to a flaky test size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants