Skip to content

test(tenant, harbor, seaweedfs, api): anchor guards that pass on a missing document - #3639

Merged
Aleksei Sviridkin (lexfrei) merged 3 commits into
mainfrom
test/anchor-wave-cataloged
Aug 8, 2026
Merged

test(tenant, harbor, seaweedfs, api): anchor guards that pass on a missing document#3639
Aleksei Sviridkin (lexfrei) merged 3 commits into
mainfrom
test/anchor-wave-cataloged

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Five helm-unittest suites asserted things that stayed green when the thing they guard disappeared. No chart or template logic changes here — only the tests, and each fix is measured in both directions.

tenant no_upgrade_force_test.yaml. Every test asserted notExists: spec.upgrade.force and nothing else. A notExists passes on a template that renders no document at all, so renaming the value that gates one of these releases leaves its test green while the release it guards is gone. Measured on etcd.yaml: with the gate renamed, the suite reported 6 passed and a sibling suite's equal was the only thing in the chart that noticed. Each test now pins the HelmRelease name alongside the absence.

The same file also covers computeplane.yaml now. Seven templates in this chart render a HelmRelease and the list held six; the module landed after the suite was written. The invariant holds there today, so this closes an unguarded template rather than a live regression. That is the gap that produced this suite in the first place, when the first sweep missed gateway.yaml.

Two rationales in that header were wrong and are corrected. The template list was said to be there because namespace.yaml's lookup errors under helm-unittest; it does not, it returns empty offline and the template renders, which is what namespace.yaml's own header says and what namespace_ancestor_labels_test.yaml relies on. Removing the whole list leaves the chart's suites passing, so the list stays for the reason that actually applies. And helm-controller does not deprecate upgrade.force: the CRD vendored at internal/fluxinstall/manifests/fluxcd.yaml, which is what the pinned Flux 2.8.x ships, describes it as a replacement strategy with no deprecation marker. recreate is the neighbouring field that carries one.

harbor, both suites. Both addressed their subject by document index. An index is a position, so a template that gains a document ahead of the one under test moves every later assertion onto a different object. Measured by inserting one document at the head of each template: the cleanup suite reddens outright, while two of the four jobservice tests keep passing: the two notExists ones, satisfied against an object that never had the path. Every document these suites assert on is unique by kind within its template, so each test now names its subject. A selector that matches nothing fails loudly, including on the notExists tests.

Indices are also easy to get wrong by hand: helm-unittest numbers documents in template source order while helm template prints them sorted by kind, so the rendered output is not the order being counted.

seaweedfs and cozystack-api. Both forbade a rule by naming it in full, and helm-unittest compares every field it is handed by value equality, so one respelling walks past. For seaweedfs that is not theoretical: ungating the cnpg block and adding a verb to the rule is the same grant and more, and the guard stayed green while a Client instance held delete on another app's Postgres cluster. The Role is now bounded by shape. A Client renders exactly two rules, both in the core group, and the cnpg grant is gated between them, so ungating it adds a third whatever its spelling.

For cozystack-api the count bound sits beside the existing named-rule assert rather than replacing it. Neither covers the other: templates/rbac.yaml carries no template directives, so the list is pinned at exactly sixteen rules from both sides, while a grant swapped in for an existing one leaves the count where it was and only the named-rule assert sees it. Measured on all three: append, delete, and swap.

Screenshots

Not a UI change.

Downstream repositories

Walked the trigger map against the diff. It touches five files, all under packages/*/*/tests/, and no chart, template, values file or tooling. Nothing in the map keys on test files.

Release note

NONE

Summary by CodeRabbit

  • Tests
    • Improved validation of rendered Kubernetes resources across Harbor, tenant, SeaweedFS, and system API configurations.
    • Tests now identify resources by kind and relevant properties, making checks more reliable when rendered document ordering changes.
    • Expanded coverage for tenant upgrade settings, compute plane resources, storage class propagation, cleanup permissions, and network policy access.
    • Added stricter assertions for expected resource counts, names, rules, and omitted settings.

Each test asserted only `notExists: spec.upgrade.force`, which passes on a
template that renders no document at all. Renaming the value that gates one
of these releases makes the template render nothing and leaves its test
green: measured on etcd.yaml, where the guard stayed green while a sibling
suite's `equal` was the only thing that noticed the release had vanished.
Pin each HelmRelease name alongside the absence so the assertion has a
document to be about.

Cover computeplane.yaml. Seven templates in this chart emit a HelmRelease
and the list held six; the module arrived after the suite was written. The
invariant holds there today, so this closes an unguarded template rather
than a live regression — which is the same gap that produced this suite,
whose first pass missed gateway.yaml.

Correct two claims in the header. The template restriction was said to be
there because namespace.yaml's `lookup` errors under helm-unittest; it does
not, the lookup returns empty offline and the template renders, which is
what its own header says and what namespace_ancestor_labels_test.yaml
relies on. The restriction stays, for the reason that actually applies: it
keeps an unrelated template breaking out of this suite's result.

helm-controller also does not deprecate upgrade.force. The CRD vendored at
internal/fluxinstall/manifests/fluxcd.yaml, which is what the pinned Flux
2.8.x ships, describes it as a replacement strategy and carries no
deprecation marker; `recreate` is the neighbouring field that does. Later
upstream documentation adds that the field is ignored under server-side
apply, and that sentence is not in the pinned CRD, so the comment says
which is which. The reason to keep the flag off is client-side apply,
where it replaces resources instead of patching them.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
Both suites addressed their subject by document index. An index is a
position, so a template that gains a document ahead of the one under test
moves every later assertion onto a different object, and what happens then
depends on the assertion: measured by inserting one document at the head of
each template, the cleanup suite reddens outright, while two of the four
jobservice tests keep passing because a `notExists` against an object that
never had the path is satisfied for the wrong reason.

Indices are also easy to get wrong by hand. helm-unittest numbers documents
in template source order, while `helm template` prints them sorted by kind,
so the rendered output is not the order being counted.

Every document these suites assert on is unique by kind within its template,
so each test now names its subject. A selector that matches nothing fails,
including on the `notExists` tests, so the anchor holds in the direction that
was silent before.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
Each suite forbade a rule by naming it in full, and helm-unittest compares
every field it is handed by value equality, so one respelling walks past.

For seaweedfs that is not theoretical. Ungating the cnpg block and adding a
verb to the rule (get,list,delete rather than get,delete) is the same grant
and more, and the guard stayed green while a Client instance held delete on
another app's Postgres cluster. Bound the Role by shape: a Client renders
exactly two rules, both in the core group, and the cnpg grant is gated
between them, so ungating it adds a third whatever its spelling. The rules
themselves stay unpinned because the secret list is long and changes on its
own schedule.

For cozystack-api, add a count bound beside the existing spelling assert
rather than in place of it. The two catch different things and neither
covers the other: templates/rbac.yaml carries no template directives, so
the list is pinned at exactly sixteen rules, while a grant swapped in for
an existing one leaves the count where it was and only the named-rule
assert sees it. The count is pinned from both sides — a dropped grant is
the failure this suite is about, since the apiserver then returns forbidden
and List silently drops the dropdown. Measured on all three: append,
delete, and swap.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
@github-actions github-actions Bot added size/L This PR changes 100-499 lines, ignoring generated files area/api Issues or PRs related to the cozystack-api aggregated API server area/storage Issues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor) area/tenant Issues or PRs related to the tenant chart and multi-tenancy labels Aug 8, 2026
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Helm test assertion hardening

Layer / File(s) Summary
Rendered resource selection
packages/apps/harbor/tests/cleanup_hook_test.yaml, packages/apps/harbor/tests/jobservice_storageclass_test.yaml
Tests select rendered resources by kind and path instead of fixed document positions.
Tenant HelmRelease validation
packages/apps/tenant/tests/no_upgrade_force_test.yaml
Tests add the computeplane HelmRelease and verify resource names before checking that spec.upgrade.force is absent.
RBAC structure validation
packages/extra/seaweedfs/tests/cleanup_client_test.yaml, packages/system/cozystack-api/tests/rbac_test.yaml
Tests validate RBAC rule groups, exact rule counts, and full CiliumNetworkPolicy permissions.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related issues

Possibly related PRs

Suggested labels: area/testing

Suggested reviewers: ivanhunters, myasnikovdaniil

🚥 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 clearly summarizes the main change: strengthening test guards so missing documents cannot produce false passes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/anchor-wave-cataloged

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.

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

Actionable comments posted: 1

🤖 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 `@packages/system/cozystack-api/tests/rbac_test.yaml`:
- Around line 16-26: Update the explanatory comment in the RBAC test to refer
directly to the complementary Cilium test and sixteen-rule count test, replacing
the inaccurate phrase “last two tests.” Preserve the existing explanation of how
those two tests bound the role.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 85685a0d-653b-445f-999c-4efcc6759a17

📥 Commits

Reviewing files that changed from the base of the PR and between 605030b and 9d1d680.

📒 Files selected for processing (5)
  • packages/apps/harbor/tests/cleanup_hook_test.yaml
  • packages/apps/harbor/tests/jobservice_storageclass_test.yaml
  • packages/apps/tenant/tests/no_upgrade_force_test.yaml
  • packages/extra/seaweedfs/tests/cleanup_client_test.yaml
  • packages/system/cozystack-api/tests/rbac_test.yaml

Comment on lines +16 to +26
#
# The last two tests bound the role from two directions, and neither covers the
# other. The count bound pins the list at exactly sixteen: templates/rbac.yaml
# carries no template directives, so anything appended makes rules[16] exist and
# anything dropped takes rules[15] away, whatever the rule is called. It says
# nothing about a grant swapped in for an existing one, because the count does
# not move under a swap. The spelling assert catches that case for the one rule
# it names, and misses every other wording of it, because helm-unittest compares
# each field it is handed by value equality and `any: true` only selects which
# fields are compared. Changing the rule count on purpose means moving both
# indices below, which is the review this role should get.

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the test references in this comment.

“The last two tests” is inaccurate. The objectstorage.k8s.io test at Line 47 is between the Cilium test and the sixteen-rule test. Name the complementary tests directly.

Suggested wording
-# The last two tests bound the role from two directions, and neither covers the
+# The Cilium access and rule-count tests bound the role from two directions, and neither covers the
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#
# The last two tests bound the role from two directions, and neither covers the
# other. The count bound pins the list at exactly sixteen: templates/rbac.yaml
# carries no template directives, so anything appended makes rules[16] exist and
# anything dropped takes rules[15] away, whatever the rule is called. It says
# nothing about a grant swapped in for an existing one, because the count does
# not move under a swap. The spelling assert catches that case for the one rule
# it names, and misses every other wording of it, because helm-unittest compares
# each field it is handed by value equality and `any: true` only selects which
# fields are compared. Changing the rule count on purpose means moving both
# indices below, which is the review this role should get.
#
# The Cilium access and rule-count tests bound the role from two directions, and neither covers the
# other. The count bound pins the list at exactly sixteen: templates/rbac.yaml
# carries no template directives, so anything appended makes rules[16] exist and
# anything dropped takes rules[15] away, whatever the rule is called. It says
# nothing about a grant swapped in for an existing one, because the count does
# not move under a swap. The spelling assert catches that case for the one rule
# it names, and misses every other wording of it, because helm-unittest compares
# each field it is handed by value equality and `any: true` only selects which
# fields are compared. Changing the rule count on purpose means moving both
# indices below, which is the review this role should get.
🤖 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 `@packages/system/cozystack-api/tests/rbac_test.yaml` around lines 16 - 26,
Update the explanatory comment in the RBAC test to refer directly to the
complementary Cilium test and sixteen-rule count test, replacing the inaccurate
phrase “last two tests.” Preserve the existing explanation of how those two
tests bound the role.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api Issues or PRs related to the cozystack-api aggregated API server area/storage Issues or PRs related to storage (linstor, seaweedfs, bucket, velero, harbor) area/tenant Issues or PRs related to the tenant chart and multi-tenancy size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant