ci: consolidate CI fixes (#2602 flux 2.8 + #2601 seaweedfs-db + #2612 kubevirt TPM + #2615 e2e trace) - #2619
ci: consolidate CI fixes (#2602 flux 2.8 + #2601 seaweedfs-db + #2612 kubevirt TPM + #2615 e2e trace)#2619myasnikovdaniil wants to merge 40 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR splits SeaweedFS DB into a dedicated chart/HelmRelease with migration, upgrades Flux Operator/Instance to 0.48.0 (adds opt‑in web UI and CRD changes), normalizes KubeVirt instancetypes/preferences, expands VM profiles, and updates tests/infrastructure. ChangesSeaweedFS HelmRelease Split
Flux Operator and Instance Upgrades
KubeVirt and VM Guest Catalogs
Infrastructure and Template Cleanup
Estimated code review effort 🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
Summary of ChangesHello, 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 serves as a consolidation of four critical fixes required to stabilize the CI pipeline. By decoupling the SeaweedFS database from the system components, the PR eliminates race conditions that previously caused deployment failures. Additionally, it includes necessary upgrades to FluxCD and KubeVirt configurations, ensuring the platform remains compatible with recent upstream changes. Highlights
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. Ignored Files
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
internal/fluxinstall/manifests/fluxcd-tenants.yaml (1)
8-8:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate the deployment version label to match the upgraded controller stack.
app.kubernetes.io/versionis stillv2.7.3while this manifest now deploys Helm Controllerv1.5.0(Flux 2.8 line). Keeping the label stale can confuse observability and inventory automation.Suggested patch
- app.kubernetes.io/version: v2.7.3 + app.kubernetes.io/version: v2.8.0Also applies to: 59-59
🤖 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 `@internal/fluxinstall/manifests/fluxcd-tenants.yaml` at line 8, Update the stale label app.kubernetes.io/version in the fluxcd-tenants manifest to the new controller stack version (e.g., change from v2.7.3 to the correct version that matches Helm Controller v1.5.0 / Flux 2.8); locate the YAML key app.kubernetes.io/version in fluxcd-tenants (and the similar occurrence at the other reported location) and replace the value so the deployment label reflects the upgraded controller stack.
🤖 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 `@docs/superpowers/plans/2026-05-10-split-seaweedfs-system.md`:
- Around line 169-175: The fenced code block that currently starts with ```
should include a language tag to satisfy markdownlint MD040; update the opening
fence to include a language (e.g., change ``` to ```text) for the block
containing the Kubernetes cluster YAML snippet (the block with "apiVersion:
postgresql.cnpg.io/v1" and "kind: Cluster" metadata) so the linter recognizes
the language.
- Line 25: The plan still references the old migration identifier migrations/39
for the seaweedfs migration but the merged PR renumbered it to migrations/40
with version stamp 41; update every occurrence of migrations/39 in the document
to migrations/40 and change the corresponding version stamp to 41 (also update
any manual verification/runbook text that mentions migration 39 or the old
version) so the plan matches the merged PR state.
In `@docs/superpowers/specs/2026-05-10-split-seaweedfs-system-design.md`:
- Around line 7-9: The fenced code block containing the literal "dial tcp
<ClusterIP>:5432 (seaweedfs-db-rw): connect: operation not permitted" (and the
other fenced blocks in the same file at the ranges you noted) need a language
annotation to satisfy MD040; update each triple-backtick fence from ``` to
```text (or another appropriate language like ```bash) for the blocks that show
plain output/error to remove the markdownlint warning, e.g., change the fence
around the "dial tcp ..." block and the blocks referenced at ranges 25-40 and
137-156 to include the language identifier.
In `@packages/core/platform/images/migrations/migrations/40`:
- Line 13: The script uses a POSIX sh shebang but then calls "set -euo
pipefail", which fails on Alpine's /bin/sh; change the shebang from "#!/bin/sh"
to "#!/bin/bash" at the top of the migration scripts (or alternatively remove
"pipefail" from the "set -euo pipefail" invocation) so the "set -euo pipefail"
line runs correctly; update the same pattern in the other migration scripts that
use "set -euo pipefail" (e.g., the migrations containing that exact "set -euo
pipefail" line) to ensure consistency.
In `@packages/extra/seaweedfs/templates/seaweedfs.yaml`:
- Around line 120-122: The manifest defines two separate spec.dependsOn entries
which creates duplicate keys; merge them into a single spec.dependsOn list and
remove the unnecessary ingress dependency so only the DB dependency remains.
Locate the spec.dependsOn blocks (the one referencing "{{ .Release.Name }}-db"
and the earlier ingress entry), combine their items into one YAML array under a
single dependsOn key, and drop the ingress item so the final dependsOn contains
only the "{{ .Release.Name }}-db" entry.
In
`@packages/system/fluxcd-operator/charts/flux-operator/templates/httproute.yaml`:
- Line 1: The HTTPRoute template currently renders when
.Values.web.httpRoute.enabled is true even if the web server is disabled; update
the guard in templates/httproute.yaml so the top-level conditional requires both
.Values.web.httpRoute.enabled and .Values.web.enabled (i.e., render only when
the HTTPRoute is enabled and the web server is enabled), and verify any matching
{% raw %}}{{- end }}{% endraw %} or else blocks still align with the new
combined condition.
In
`@packages/system/fluxcd-operator/charts/flux-operator/templates/web-standard-roles.yaml`:
- Around line 34-36: The RBAC block granting apiGroups: ["*"] and resources:
["*"] with verbs: ["get","list","watch"] in the flux-web-admin role is overly
permissive and allows cluster-wide read of sensitive objects (e.g., Secrets);
update the flux-web-admin (and flux-web-user if present) role definitions to
remove wildcard apiGroups/resources and instead enumerate only non-sensitive
resource kinds (e.g., pods, deployments, services, configmaps, ingresses) or
split into two roles (broad read for non-sensitive resources + a separate,
tightly-scoped role for anything sensitive), or convert the binding pattern to a
namespace-scoped Role/RoleBinding; locate and adjust the apiGroups/resources
block in web-standard-roles.yaml for the flux-web-admin role and ensure
documentation/comments instruct cluster admins to use namespace-scoped
RoleBindings if cluster-wide access is not intended.
- Around line 16-18: The ClusterRole "flux-web-user" currently grants
cluster-wide read on all apiGroups/resources which exposes Secrets and other
sensitive objects; change the ClusterRole to restrict resources to only
non-sensitive types (e.g., "pods","services","configmaps" if acceptable) and
explicitly remove "secrets" and other sensitive resources from the resources
list, or replace the ClusterRole with a namespaced Role and update any bindings
to use Role/RoleBinding to scope permissions per-namespace; look for the
resource/role definition in web-standard-roles.yaml and update the
apiGroups/resources/verbs accordingly to follow least privilege.
In `@packages/system/fluxcd-operator/charts/flux-operator/values.yaml`:
- Around line 17-19: The default enables the Flux Status web UI contrary to the
PR's opt-in requirement; change the value of web.enabled from true to false in
values.yaml (the web.enabled setting) so the web UI is disabled by default and
add or update a comment explaining it must be explicitly enabled by consumers.
In `@packages/system/kubevirt-instancetypes/templates/preferences.yaml`:
- Around line 7-11: The annotations openshift.io/documentation-url and
openshift.io/support-url currently use YAML literal block scalars (the "|" plus
quoted URL) which yields values like "\"https://...\"\n"; fix by emitting plain
scalar URLs (no | and no surrounding quotes/newline) for those keys across the
template (replace the block scalar nodes with bare string nodes for
openshift.io/documentation-url and openshift.io/support-url). Do not hard-edit
generated files long-term—update the regen pipeline instead (the kustomize build
+ yq -i select steps) to preserve upstream plain-scalar URLs from
kubevirt/common-instancetypes so future generations produce bare URLs rather
than block scalars.
---
Outside diff comments:
In `@internal/fluxinstall/manifests/fluxcd-tenants.yaml`:
- Line 8: Update the stale label app.kubernetes.io/version in the fluxcd-tenants
manifest to the new controller stack version (e.g., change from v2.7.3 to the
correct version that matches Helm Controller v1.5.0 / Flux 2.8); locate the YAML
key app.kubernetes.io/version in fluxcd-tenants (and the similar occurrence at
the other reported location) and replace the value so the deployment label
reflects the upgraded controller stack.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 737c2589-4e2c-4d6c-92d6-5d2b2ba3f634
📒 Files selected for processing (49)
docs/superpowers/plans/2026-05-10-split-seaweedfs-system.mddocs/superpowers/specs/2026-05-10-split-seaweedfs-system-design.mdhack/e2e-install-cozystack.batsinternal/fluxinstall/manifests/fluxcd-tenants.yamlinternal/fluxinstall/manifests/fluxcd.yamlpackages/apps/vm-instance/values.schema.jsonpackages/core/platform/images/migrations/migrations/40packages/core/platform/sources/seaweedfs-application.yamlpackages/extra/seaweedfs/templates/seaweedfs-db.yamlpackages/extra/seaweedfs/templates/seaweedfs.yamlpackages/system/fluxcd-operator/charts/flux-operator/Chart.yamlpackages/system/fluxcd-operator/charts/flux-operator/README.mdpackages/system/fluxcd-operator/charts/flux-operator/templates/NOTES.txtpackages/system/fluxcd-operator/charts/flux-operator/templates/_helpers.tplpackages/system/fluxcd-operator/charts/flux-operator/templates/admin-clusterrole.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/aggregate-clusterrole.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/crds.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/deployment.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/httproute.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/ingress.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/network-policy.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/networkpolicy.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/service.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/web-clusterrole.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/web-secret.yamlpackages/system/fluxcd-operator/charts/flux-operator/templates/web-standard-roles.yamlpackages/system/fluxcd-operator/charts/flux-operator/values.schema.jsonpackages/system/fluxcd-operator/charts/flux-operator/values.yamlpackages/system/fluxcd-operator/patches/networkPolicy.diffpackages/system/fluxcd-operator/values.yamlpackages/system/fluxcd/charts/flux-instance/Chart.yamlpackages/system/fluxcd/charts/flux-instance/README.mdpackages/system/fluxcd/charts/flux-instance/templates/NOTES.txtpackages/system/fluxcd/charts/flux-instance/templates/healthcheck.yamlpackages/system/fluxcd/charts/flux-instance/templates/instance.yamlpackages/system/fluxcd/charts/flux-instance/values.schema.jsonpackages/system/fluxcd/charts/flux-instance/values.yamlpackages/system/fluxcd/values.yamlpackages/system/kubevirt-instancetypes/Makefilepackages/system/kubevirt-instancetypes/templates/instancetypes.yamlpackages/system/kubevirt-instancetypes/templates/preferences.yamlpackages/system/seaweedfs-db/Chart.yamlpackages/system/seaweedfs-db/Makefilepackages/system/seaweedfs-db/README.mdpackages/system/seaweedfs-db/templates/database.yamlpackages/system/seaweedfs-db/values.schema.jsonpackages/system/seaweedfs-db/values.yamlpackages/system/seaweedfs/values.yamlpackages/system/vm-instance-rd/cozyrds/vm-instance.yaml
💤 Files with no reviewable changes (2)
- packages/system/seaweedfs/values.yaml
- packages/system/kubevirt-instancetypes/Makefile
| - `packages/system/seaweedfs-db/Makefile` | ||
| - `packages/system/seaweedfs-db/templates/database.yaml` (moved from system/seaweedfs) | ||
| - `packages/extra/seaweedfs/templates/seaweedfs-db.yaml` | ||
| - `packages/core/platform/images/migrations/migrations/39` |
There was a problem hiding this comment.
Update migration numbering in the plan to match the merged PR state.
This plan still instructs creating/running migration 39, but this PR’s merge resolution renumbered the seaweedfs migration to 40 (with version stamp 41). Keeping 39 here can lead to wrong manual verification and operator runbooks.
Suggested doc fix
-- `packages/core/platform/images/migrations/migrations/39`
+- `packages/core/platform/images/migrations/migrations/40`
...
-# Migration 38 --> 39
+# Migration 40 --> 41
...
-kubectl create configmap -n cozy-system cozystack-version \
- --from-literal=version=39 --dry-run=client -o yaml | kubectl apply -f-
+kubectl create configmap -n cozy-system cozystack-version \
+ --from-literal=version=41 --dry-run=client -o yaml | kubectl apply -f-Also applies to: 487-529
🤖 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 `@docs/superpowers/plans/2026-05-10-split-seaweedfs-system.md` at line 25, The
plan still references the old migration identifier migrations/39 for the
seaweedfs migration but the merged PR renumbered it to migrations/40 with
version stamp 41; update every occurrence of migrations/39 in the document to
migrations/40 and change the corresponding version stamp to 41 (also update any
manual verification/runbook text that mentions migration 39 or the old version)
so the plan matches the merged PR state.
| ``` | ||
| --- | ||
| apiVersion: postgresql.cnpg.io/v1 | ||
| kind: Cluster | ||
| metadata: | ||
| name: seaweedfs-db | ||
| ``` |
There was a problem hiding this comment.
Add a language to the fenced code block to satisfy markdownlint (MD040).
Use a language tag (for this snippet, text is fine).
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 169-169: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 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 `@docs/superpowers/plans/2026-05-10-split-seaweedfs-system.md` around lines 169
- 175, The fenced code block that currently starts with ``` should include a
language tag to satisfy markdownlint MD040; update the opening fence to include
a language (e.g., change ``` to ```text) for the block containing the Kubernetes
cluster YAML snippet (the block with "apiVersion: postgresql.cnpg.io/v1" and
"kind: Cluster" metadata) so the linter recognizes the language.
| ``` | ||
| dial tcp <ClusterIP>:5432 (seaweedfs-db-rw): connect: operation not permitted | ||
| ``` |
There was a problem hiding this comment.
Annotate fenced code blocks with a language (MD040).
Please add a language to these fences (e.g., text) to avoid markdownlint warnings.
Also applies to: 25-40, 137-156
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 7-7: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 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 `@docs/superpowers/specs/2026-05-10-split-seaweedfs-system-design.md` around
lines 7 - 9, The fenced code block containing the literal "dial tcp
<ClusterIP>:5432 (seaweedfs-db-rw): connect: operation not permitted" (and the
other fenced blocks in the same file at the ranges you noted) need a language
annotation to satisfy MD040; update each triple-backtick fence from ``` to
```text (or another appropriate language like ```bash) for the blocks that show
plain output/error to remove the markdownlint warning, e.g., change the fence
around the "dial tcp ..." block and the blocks referenced at ranges 25-40 and
137-156 to include the language identifier.
| # so the seaweedfs-system upgrade (which no longer renders the Cluster) does | ||
| # not delete it during the transition. | ||
|
|
||
| set -euo pipefail |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Verify shell/runtime assumptions for migration scripts.
echo "== Migration scripts using /bin/sh + pipefail =="
rg -n '^#!/bin/sh|pipefail' packages/core/platform/images/migrations -C1
echo
echo "== Migration image build files (check if bash is guaranteed) =="
fd -i 'Dockerfile*' packages/core/platform/images/migrations | while read -r f; do
echo "--- $f"
sed -n '1,120p' "$f"
doneRepository: cozystack/cozystack
Length of output: 10050
Change shebang to #!/bin/bash or remove pipefail from strict mode.
Line 13 uses set -euo pipefail with #!/bin/sh, but /bin/sh on Alpine (busybox) does not support pipefail. This causes the script to fail immediately before any migration logic runs. The Dockerfile explicitly installs bash, so the preferred fix is to use #!/bin/bash as the shebang. This same issue appears across many migration scripts (27–40 and others) and should be addressed systematically.
Recommended fix
-#!/bin/sh
+#!/bin/bash🤖 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/core/platform/images/migrations/migrations/40` at line 13, The
script uses a POSIX sh shebang but then calls "set -euo pipefail", which fails
on Alpine's /bin/sh; change the shebang from "#!/bin/sh" to "#!/bin/bash" at the
top of the migration scripts (or alternatively remove "pipefail" from the "set
-euo pipefail" invocation) so the "set -euo pipefail" line runs correctly;
update the same pattern in the other migration scripts that use "set -euo
pipefail" (e.g., the migrations containing that exact "set -euo pipefail" line)
to ensure consistency.
| @@ -0,0 +1,26 @@ | |||
| {{- if .Values.web.httpRoute.enabled -}} | |||
There was a problem hiding this comment.
Add web.enabled guard to HTTPRoute rendering.
Line 1 renders the route even when the web server is disabled, which can produce a route to a non-serving backend port.
Suggested fix
-{{- if .Values.web.httpRoute.enabled -}}
+{{- if and .Values.web.enabled .Values.web.httpRoute.enabled -}}📝 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.
| {{- if .Values.web.httpRoute.enabled -}} | |
| {{- if and .Values.web.enabled .Values.web.httpRoute.enabled -}} |
🧰 Tools
🪛 YAMLlint (1.38.0)
[error] 1-1: syntax error: expected the node content, but found '-'
(syntax)
🤖 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/fluxcd-operator/charts/flux-operator/templates/httproute.yaml`
at line 1, The HTTPRoute template currently renders when
.Values.web.httpRoute.enabled is true even if the web server is disabled; update
the guard in templates/httproute.yaml so the top-level conditional requires both
.Values.web.httpRoute.enabled and .Values.web.enabled (i.e., render only when
the HTTPRoute is enabled and the web server is enabled), and verify any matching
{% raw %}}{{- end }}{% endraw %} or else blocks still align with the new
combined condition.
| - apiGroups: ["*"] | ||
| resources: ["*"] | ||
| verbs: ["get", "list", "watch"] |
There was a problem hiding this comment.
Overly permissive RBAC grants cluster-wide read access to all resources including Secrets.
The flux-web-user role grants get/list/watch on apiGroups: ["*"] and resources: ["*"], which allows reading ALL cluster resources including Secrets, ConfigMaps, and other sensitive data across all namespaces. This violates the principle of least privilege and could expose credentials, tokens, and private keys to any user assigned this role.
Consider scoping the broad read permissions to non-sensitive resource types, or document that cluster admins should create namespace-scoped RoleBindings rather than cluster-wide ClusterRoleBindings to limit exposure.
🤖 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/fluxcd-operator/charts/flux-operator/templates/web-standard-roles.yaml`
around lines 16 - 18, The ClusterRole "flux-web-user" currently grants
cluster-wide read on all apiGroups/resources which exposes Secrets and other
sensitive objects; change the ClusterRole to restrict resources to only
non-sensitive types (e.g., "pods","services","configmaps" if acceptable) and
explicitly remove "secrets" and other sensitive resources from the resources
list, or replace the ClusterRole with a namespaced Role and update any bindings
to use Role/RoleBinding to scope permissions per-namespace; look for the
resource/role definition in web-standard-roles.yaml and update the
apiGroups/resources/verbs accordingly to follow least privilege.
| - apiGroups: ["*"] | ||
| resources: ["*"] | ||
| verbs: ["get", "list", "watch"] |
There was a problem hiding this comment.
Overly permissive RBAC grants cluster-wide read access to all resources including Secrets.
The flux-web-admin role also grants get/list/watch on apiGroups: ["*"] and resources: ["*"]. Same security concern as flux-web-user: any user with this role can read all Secrets and sensitive data cluster-wide.
Consider scoping the broad read permissions to non-sensitive resource types, or document that cluster admins should create namespace-scoped RoleBindings to limit exposure.
🤖 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/fluxcd-operator/charts/flux-operator/templates/web-standard-roles.yaml`
around lines 34 - 36, The RBAC block granting apiGroups: ["*"] and resources:
["*"] with verbs: ["get","list","watch"] in the flux-web-admin role is overly
permissive and allows cluster-wide read of sensitive objects (e.g., Secrets);
update the flux-web-admin (and flux-web-user if present) role definitions to
remove wildcard apiGroups/resources and instead enumerate only non-sensitive
resource kinds (e.g., pods, deployments, services, configmaps, ingresses) or
split into two roles (broad read for non-sensitive resources + a separate,
tightly-scoped role for anything sensitive), or convert the binding pattern to a
namespace-scoped Role/RoleBinding; locate and adjust the apiGroups/resources
block in web-standard-roles.yaml for the flux-web-admin role and ensure
documentation/comments instruct cluster admins to use namespace-scoped
RoleBindings if cluster-wide access is not intended.
| web: | ||
| # -- Enable the [Flux Status web server](https://fluxoperator.dev/web-ui/) on port 9080. | ||
| enabled: true |
There was a problem hiding this comment.
Default web UI enablement conflicts with opt-in rollout.
Line 19 sets web.enabled: true, which makes the web UI active by default. That contradicts the PR objective (“web UI opt-in”) and widens default exposure.
Suggested fix
web:
# -- Enable the [Flux Status web server](https://fluxoperator.dev/web-ui/) on port 9080.
- enabled: true
+ enabled: false📝 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.
| web: | |
| # -- Enable the [Flux Status web server](https://fluxoperator.dev/web-ui/) on port 9080. | |
| enabled: true | |
| web: | |
| # -- Enable the [Flux Status web server](https://fluxoperator.dev/web-ui/) on port 9080. | |
| enabled: false |
🤖 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/fluxcd-operator/charts/flux-operator/values.yaml` around
lines 17 - 19, The default enables the Flux Status web UI contrary to the PR's
opt-in requirement; change the value of web.enabled from true to false in
values.yaml (the web.enabled setting) so the web UI is disabled by default and
add or update a comment explaining it must be explicitly enabled by consumers.
| openshift.io/documentation-url: | | ||
| "https://github.com/kubevirt/common-instancetypes" | ||
| openshift.io/provider-display-name: KubeVirt | ||
| openshift.io/support-url: https://github.com/kubevirt/common-instancetypes/issues | ||
| openshift.io/support-url: | | ||
| "https://github.com/kubevirt/common-instancetypes/issues" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm that the |-block-scalar-with-quotes pattern is widespread in this file
# and inspect the regen pipeline that produced it.
set -euo pipefail
echo "=== Occurrences of '| "...URL..."' shape in preferences.yaml ==="
fd -t f 'preferences.yaml' -p 'kubevirt-instancetypes' \
--exec rg -nC1 -P '^\s*openshift\.io/(documentation|support)-url:\s*\|\s*$' {}
echo
echo "=== The very next non-empty line (the actual value) ==="
fd -t f 'preferences.yaml' -p 'kubevirt-instancetypes' \
--exec rg -nP '^\s*"https?://' {} \
| head -20
echo
echo "=== Regen pipeline (Makefile) for kubevirt-instancetypes ==="
fd -t f 'Makefile' -p 'kubevirt-instancetypes' --exec cat {}Repository: cozystack/cozystack
Length of output: 254
🌐 Web query:
kubevirt common-instancetypes openshift.io/documentation-url annotation format yaml
💡 Result:
The OpenShift annotation key openshift.io/documentation-url is used as a normal string value under metadata.annotations in YAML (typically for OpenShift Template objects, but the same annotation format applies anywhere you set it in an object's metadata). Example YAML value (as shown in KubeVirt’s OpenShift Templates user guide): metadata: annotations: openshift.io/documentation-url: "https://github.com/kubevirt/common-templates" [1] For KubeVirt common-instancetypes specifically, the instancetype resources live under API types like VirtualMachineInstancetype/VirtualMachineClusterInstancetype (and common-instancetypes are a set of those resources), and their spec has an optional spec.annotations map[string]string that is used by the instancetype to apply annotations to the VirtualMachineInstance. That map is also expressed in YAML as key/value pairs under annotations: [2] apiVersion: instancetype.kubevirt.io/v1beta1 kind: VirtualMachineInstancetype metadata: name: example-instancetype spec: annotations: some-annotation-key: "some-value" [2] Note: In the KubeVirt instancetype API, spec.annotations is declared as Annotations map[string]string (optional), so it is not free-form YAML text; it must be a string map. [2]
Citations:
- 1: https://kubevirt.io/user-guide/user_workloads/templates/
- 2: https://github.com/kubevirt/kubevirt/blob/main/staging/src/kubevirt.io/api/instancetype/v1beta1/types.go
🏁 Script executed:
#!/bin/bash
# Find the preferences.yaml file for kubevirt-instancetypes
echo "=== Finding preferences.yaml file ==="
find . -type f -name "preferences.yaml" -path "*/kubevirt-instancetypes/*"
echo
echo "=== Checking for Makefile in kubevirt-instancetypes ==="
find . -type f -name "Makefile" -path "*/kubevirt-instancetypes/*"Repository: cozystack/cozystack
Length of output: 276
🏁 Script executed:
#!/bin/bash
# Once we find the file, let's look at specific lines from the review comment
FILE=$(find . -type f -name "preferences.yaml" -path "*/kubevirt-instancetypes/*" | head -1)
if [ -n "$FILE" ]; then
echo "=== Content at lines 7-11 (first occurrence) ==="
sed -n '7,11p' "$FILE"
echo
echo "=== Content at lines 37-42 (second occurrence) ==="
sed -n '37,42p' "$FILE"
echo
echo "=== Sample of literal block scalar pattern (first 5 occurrences) ==="
rg -n 'openshift\.io/(documentation|support)-url:\s*\|' "$FILE" | head -5
echo
echo "=== File size and line count ==="
wc -l "$FILE"
fiRepository: cozystack/cozystack
Length of output: 1061
🏁 Script executed:
#!/bin/bash
# Check the Makefile for the regen pipeline
MAKEFILE=$(find . -type f -name "Makefile" -path "*/kubevirt-instancetypes/*" | head -1)
if [ -n "$MAKEFILE" ]; then
echo "=== Makefile for kubevirt-instancetypes ==="
cat "$MAKEFILE"
fiRepository: cozystack/cozystack
Length of output: 633
🌐 Web query:
kubevirt common-instancetypes repository raw manifest documentation-url annotation format
💡 Result:
The kubevirt/common-instancetypes repository is located at https://github.com/kubevirt/common-instancetypes. It provides a set of cluster-wide and namespaced VirtualMachineInstancetypes and VirtualMachinePreferences for KubeVirt VMs [1][2]. Deploy using kubectl apply -k https://github.com/kubevirt/common-instancetypes.git [2]. Latest release v1.6.0 as of 2026-01-28 [1]. Raw manifests are generated via kustomize from the repo's bases (e.g., for VirtualMachineInstancetypes: kubectl apply -k https://github.com/kubevirt/common-instancetypes.git/VirtualMachineInstancetypes) [2]. Example raw YAML snippet from KubeVirt bundles: - instancetype.kubevirt.io/common-instancetypes-version: v1.1.0 + instancetype.kubevirt.io/common-instancetypes-version: v1.2.0 name: cx1.2xlarge [3]. The key annotation in these manifests is instancetype.kubevirt.io/common-instancetypes-version: <version> (e.g., v1.2.0, v1.6.0), which identifies the common-instancetypes release/version used [3]. No documentation-url annotation is explicitly documented in sources for these manifests, but the repo homepage links to official docs: https://kubevirt.io/user-guide/virtual_machines/instancetypes/#common-instancetypes [1]. InstanceType specs support an optional annotations field for custom annotations applied to VMIs [4].
Citations:
- 1: https://github.com/kubevirt/common-instancetypes
- 2: https://kubevirt.io/user-guide/user_workloads/deploy_common_instancetypes/
- 3: kubevirt/kubevirt@bcee1cd
- 4: https://github.com/kubevirt/kubevirt/blob/main/staging/src/kubevirt.io/api/instancetype/v1beta1/types.go
🏁 Script executed:
#!/bin/bash
# Fetch the upstream manifest to see what format it uses before yq processing
echo "=== Fetching upstream preferences from kubevirt/common-instancetypes ==="
# Use kustomize to build the same upstream target
kustomize build https://github.com/kubevirt/common-instancetypes//preferences 2>/dev/null | head -100Repository: cozystack/cozystack
Length of output: 136
🏁 Script executed:
#!/bin/bash
# If kustomize is not available, try to check what the current regen would produce
# Let's compare: run kustomize, then show before and after yq
FILE="./packages/system/kubevirt-instancetypes/templates/preferences.yaml"
echo "=== Current file first occurrence (lines 7-11) ==="
sed -n '7,11p' "$FILE"
echo
echo "=== Check if yq is available and test the select behavior ==="
which yq && echo "yq found" || echo "yq not found"
echo
echo "=== Count how many resources match the filter that should be removed ==="
if command -v yq &> /dev/null; then
grep -c "^kind:" "$FILE" || true
fiRepository: cozystack/cozystack
Length of output: 567
🏁 Script executed:
#!/bin/bash
# Let's also check if the upstream source (kubevirt/common-instancetypes)
# has documentation on the annotation format by examining the repo
echo "=== Check if we can get upstream manifest info ==="
# Try to fetch raw content from the repo
curl -s https://raw.githubusercontent.com/kubevirt/common-instancetypes/main/preferences/CentOS-7.yaml | head -50Repository: cozystack/cozystack
Length of output: 128
🏁 Script executed:
#!/bin/bash
# Check the directory structure and look for Chart.yaml
echo "=== Directory structure of kubevirt-instancetypes ==="
ls -la packages/system/kubevirt-instancetypes/
echo
echo "=== Check for Chart.yaml ==="
find packages/system/kubevirt-instancetypes -name "Chart.yaml" -exec cat {} \;
echo
echo "=== Check if templates/ contains other files ==="
ls -la packages/system/kubevirt-instancetypes/templates/ 2>/dev/null | head -20Repository: cozystack/cozystack
Length of output: 959
🏁 Script executed:
#!/bin/bash
# Let's verify the actual YAML parsing outcome by checking how the annotation value
# would be interpreted. Count lines in a resource block to understand nesting.
FILE="./packages/system/kubevirt-instancetypes/templates/preferences.yaml"
echo "=== First resource with metadata/annotations (lines 1-20) ==="
sed -n '1,20p' "$FILE"
echo
echo "=== Check YAML structure: metadata.annotations block ==="
sed -n '1,35p' "$FILE" | cat -ARepository: cozystack/cozystack
Length of output: 1895
Fix annotation values: remove literal block scalars (|) to preserve bare URLs
The openshift.io/documentation-url and openshift.io/support-url annotations are using YAML literal block scalars (|), which preserve the embedded quotes and trailing newline. This produces malformed annotation values—for example, "https://github.com/kubevirt/common-instancetypes"\n instead of the bare URL. Any tooling that consumes these annotations as hyperlinks (dashboards, UIs, OperatorHub) will receive a malformed value.
This pattern occurs throughout the file at all indicated line ranges (7-11, 37-42, 69-74, and continuing through 2341-2345).
The issue likely originates from the regen pipeline in the Makefile (kustomize build followed by yq -i select). Verify the format of these annotations in the upstream kubevirt/common-instancetypes manifests. If upstream emits bare URLs without the literal block scalar syntax, update the regen pipeline to preserve that format rather than correcting this generated file directly.
🤖 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/kubevirt-instancetypes/templates/preferences.yaml` around
lines 7 - 11, The annotations openshift.io/documentation-url and
openshift.io/support-url currently use YAML literal block scalars (the "|" plus
quoted URL) which yields values like "\"https://...\"\n"; fix by emitting plain
scalar URLs (no | and no surrounding quotes/newline) for those keys across the
template (replace the block scalar nodes with bare string nodes for
openshift.io/documentation-url and openshift.io/support-url). Do not hard-edit
generated files long-term—update the regen pipeline instead (the kustomize build
+ yq -i select steps) to preserve upstream plain-scalar URLs from
kubevirt/common-instancetypes so future generations produce bare URLs rather
than block scalars.
There was a problem hiding this comment.
Code Review
This pull request implements an architectural split of the seaweedfs-system HelmRelease into seaweedfs-db and seaweedfs-system to resolve startup race conditions, utilizing HelmRelease.spec.healthCheckExprs for readiness gating. It includes the creation of a new chart, updates to existing templates, and a migration script for resource ownership. Additional changes include updates to vm-instance profiles, kubevirt-instancetypes, and various dependency versions. The review feedback identifies issues with POSIX shell compatibility in migration scripts, versioning logic conflicts, schema definition inaccuracies, and cleanup logic in E2E tests.
| # so the seaweedfs-system upgrade (which no longer renders the Cluster) does | ||
| # not delete it during the transition. | ||
|
|
||
| set -euo pipefail |
There was a problem hiding this comment.
set -o pipefail is a non-standard extension not supported by all POSIX-compliant shells (such as dash, often the default /bin/sh). Since the shebang is #!/bin/sh and the project guidelines specify POSIX shell for migrations, this will cause the script to fail with an 'Illegal option' error in environments where /bin/sh is not bash or zsh.
| set -euo pipefail | |
| set -eu |
| # Migration 40 --> 41 | ||
| # Adopt existing Cluster/seaweedfs-db resources into the new seaweedfs-db | ||
| # HelmRelease introduced in this release. | ||
| # | ||
| # Pre-split, the CNPG Cluster lived inside the seaweedfs-system Helm release. | ||
| # Splitting moves it to a new release named seaweedfs-db. We rewrite the | ||
| # helm ownership annotations so Helm adopts the existing Cluster instead of | ||
| # erroring on the next reconcile, and stamp helm.sh/resource-policy: keep | ||
| # so the seaweedfs-system upgrade (which no longer renders the Cluster) does | ||
| # not delete it during the transition. | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| # Iterate every namespace that has a Cluster named "seaweedfs-db". | ||
| for ns in $(kubectl get cluster.postgresql.cnpg.io -A \ | ||
| -o jsonpath='{range .items[?(@.metadata.name=="seaweedfs-db")]}{.metadata.namespace}{"\n"}{end}'); do | ||
| current=$(kubectl get cluster.postgresql.cnpg.io seaweedfs-db -n "$ns" \ | ||
| -o jsonpath='{.metadata.annotations.meta\.helm\.sh/release-name}' 2>/dev/null || true) | ||
| if [ "$current" = "seaweedfs-system" ]; then | ||
| echo "Re-annotating Cluster/seaweedfs-db in $ns: seaweedfs-system -> seaweedfs-db" | ||
| kubectl annotate cluster.postgresql.cnpg.io seaweedfs-db -n "$ns" \ | ||
| meta.helm.sh/release-name=seaweedfs-db \ | ||
| helm.sh/resource-policy=keep \ | ||
| --overwrite | ||
| # release-namespace stays the same (tenant namespace, e.g. tenant-root) | ||
| fi | ||
| done | ||
|
|
||
| # Stamp version | ||
| kubectl create configmap -n cozy-system cozystack-version \ | ||
| --from-literal=version=41 --dry-run=client -o yaml | kubectl apply -f- |
There was a problem hiding this comment.
There is an inconsistency in the migration versioning logic:
- The filename is
40. - The header says
Migration 40 --> 41. - The version stamp at the end sets
version=41.
If this migration is intended to follow migration 39 from main, it should be named 40, migrate 39 --> 40, and set version=40. If it is intended to be version 41 (to avoid a conflict with another migration 40 mentioned in the PR description), the file should be renamed to 41. Naming it 40 while setting version 41 skips a version in the state tracking and will likely overwrite an existing migration 40 during merge.
Additionally, the implementation plan in docs/superpowers/plans/2026-05-10-split-seaweedfs-system.md still refers to this as migration 39 (line 25), which should also be updated.
| ## @typedef {struct} DB - Database configuration. | ||
| ## @field {int} [replicas] - Number of database replicas. | ||
| ## @field {quantity} [size] - Persistent Volume size. | ||
| ## @field {string} [storageClass] - StorageClass used to store the data. | ||
|
|
||
| ## @param {DB} db - Database configuration. | ||
| db: | ||
| replicas: 2 | ||
| size: 10Gi | ||
| storageClass: "" |
There was a problem hiding this comment.
The Resources typedef is defined but not used in the DB struct. Furthermore, the HelmRelease in packages/extra/seaweedfs/templates/seaweedfs-db.yaml passes db.resources, which is not declared here. This results in an incomplete values.schema.json, preventing the dashboard from correctly validating or displaying these parameters.
## @typedef {struct} DB - Database configuration.
## @field {int} [replicas] - Number of database replicas.
## @field {Resources} [resources] - Resource configuration.
## @field {quantity} [size] - Persistent Volume size.
## @field {string} [storageClass] - StorageClass used to store the data.
## @param {DB} db - Database configuration.
db:
replicas: 2
resources: {}
size: 10Gi
storageClass: ""| openshift.io/documentation-url: | | ||
| "https://github.com/kubevirt/common-instancetypes" |
There was a problem hiding this comment.
The use of block scalars (|) with double quotes for URL fields (e.g., openshift.io/documentation-url) causes the quotes to be included as literal characters in the string value (e.g., "https://..."). This is likely an unintended side effect of the regeneration process and will break any tool or UI attempting to resolve these URLs. This pattern is repeated throughout the file.
| kubeovn_yaml=$(mktemp) | ||
| linstor_yaml=$(mktemp) | ||
| helm template packages/system/kubeovn > "$kubeovn_yaml" | ||
| helm template packages/system/linstor > "$linstor_yaml" |
There was a problem hiding this comment.
…or-vpa HR
The packages/system/vertical-pod-autoscaler chart's vpa-for-vpa.yaml template
emits an HR in cozy-vpa-for-vpa that the parent helm install applies and waits
on. That nested HR had `dependsOn: monitoring-agents`, which never resolves:
parent VPA helm install
waits for nested vpa-for-vpa HR Ready
waits for monitoring-agents HR Ready
waits for cozystack.vertical-pod-autoscaler PackageSource Ready
waits for parent VPA HR Ready <-- back to start
Symptom observed on PR #2619 e2e (cozyreport):
Helm upgrade failed for release cozy-vertical-pod-autoscaler/
vertical-pod-autoscaler with chart cozy-vertical-pod-autoscaler@...:
timeout waiting for: [HelmRelease/cozy-vpa-for-vpa/vpa-for-vpa
status: 'InProgress']
The recommender's /health-check readiness probe is served by the binary
itself and doesn't require Prometheus. Removing the dependsOn lets the
nested HR become Ready quickly; the recommender will log connection
errors against vmselect until monitoring-agents installs later in the
boot sequence, then start producing recommendations normally.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
…or-vpa HR
The packages/system/vertical-pod-autoscaler chart's vpa-for-vpa.yaml template
emits an HR in cozy-vpa-for-vpa that the parent helm install applies and waits
on. That nested HR had `dependsOn: monitoring-agents`, which never resolves:
parent VPA helm install
waits for nested vpa-for-vpa HR Ready
waits for monitoring-agents HR Ready
waits for cozystack.vertical-pod-autoscaler PackageSource Ready
waits for parent VPA HR Ready <-- back to start
Symptom observed on PR #2619 e2e (cozyreport):
Helm upgrade failed for release cozy-vertical-pod-autoscaler/
vertical-pod-autoscaler with chart cozy-vertical-pod-autoscaler@...:
timeout waiting for: [HelmRelease/cozy-vpa-for-vpa/vpa-for-vpa
status: 'InProgress']
The recommender's /health-check readiness probe is served by the binary
itself and doesn't require Prometheus. Removing the dependsOn lets the
nested HR become Ready quickly; the recommender will log connection
errors against vmselect until monitoring-agents installs later in the
boot sequence, then start producing recommendations normally.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
60aecd5 to
faa448a
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
packages/core/platform/images/migrations/migrations/40 (1)
1-1:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winChange shebang to
#!/bin/bashforpipefailcompatibility.Line 13 uses
set -euo pipefail, but/bin/shon Alpine (busybox) does not supportpipefail. Since the migration image includes bash, change the shebang to#!/bin/bash.🐛 Recommended fix
-#!/bin/sh +#!/bin/bash🤖 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/core/platform/images/migrations/migrations/40` at line 1, The script's shebang uses /bin/sh but later relies on "set -euo pipefail" which requires bash; update the shebang in the migration script (the line currently "#!/bin/sh") to "#!/bin/bash" so pipefail is supported, leaving the existing "set -euo pipefail" and rest of the script (migration file in packages/core/platform/images/migrations/migrations/40).
🤖 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.
Duplicate comments:
In `@packages/core/platform/images/migrations/migrations/40`:
- Line 1: The script's shebang uses /bin/sh but later relies on "set -euo
pipefail" which requires bash; update the shebang in the migration script (the
line currently "#!/bin/sh") to "#!/bin/bash" so pipefail is supported, leaving
the existing "set -euo pipefail" and rest of the script (migration file in
packages/core/platform/images/migrations/migrations/40).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d1924aed-1090-446d-b43b-aaffa71e5f63
📒 Files selected for processing (18)
hack/e2e-install-cozystack.batspackages/apps/vm-instance/values.schema.jsonpackages/core/platform/images/migrations/migrations/40packages/core/platform/sources/seaweedfs-application.yamlpackages/extra/seaweedfs/templates/seaweedfs-db.yamlpackages/extra/seaweedfs/templates/seaweedfs.yamlpackages/system/kubevirt-instancetypes/Makefilepackages/system/kubevirt-instancetypes/templates/instancetypes.yamlpackages/system/kubevirt-instancetypes/templates/preferences.yamlpackages/system/seaweedfs-db/Chart.yamlpackages/system/seaweedfs-db/Makefilepackages/system/seaweedfs-db/README.mdpackages/system/seaweedfs-db/templates/database.yamlpackages/system/seaweedfs-db/values.schema.jsonpackages/system/seaweedfs-db/values.yamlpackages/system/seaweedfs/values.yamlpackages/system/vertical-pod-autoscaler/templates/vpa-for-vpa.yamlpackages/system/vm-instance-rd/cozyrds/vm-instance.yaml
💤 Files with no reviewable changes (2)
- packages/system/kubevirt-instancetypes/Makefile
- packages/system/seaweedfs/values.yaml
✅ Files skipped from review due to trivial changes (4)
- packages/core/platform/sources/seaweedfs-application.yaml
- packages/system/seaweedfs-db/Chart.yaml
- hack/e2e-install-cozystack.bats
- packages/system/seaweedfs-db/README.md
🚧 Files skipped from review as they are similar to previous changes (9)
- packages/system/seaweedfs-db/values.schema.json
- packages/system/vm-instance-rd/cozyrds/vm-instance.yaml
- packages/system/vertical-pod-autoscaler/templates/vpa-for-vpa.yaml
- packages/system/seaweedfs-db/values.yaml
- packages/system/seaweedfs-db/Makefile
- packages/apps/vm-instance/values.schema.json
- packages/extra/seaweedfs/templates/seaweedfs.yaml
- packages/system/kubevirt-instancetypes/templates/instancetypes.yaml
- packages/system/kubevirt-instancetypes/templates/preferences.yaml
PR #2619 split seaweedfs into a serialized chain (seaweedfs-db -> seaweedfs-system -> seaweedfs) that needs ~5 min of wall-clock to install: CNPG bootstrap, master quorum, then the wrapper. With the prior 5m wait budget on the parent tenant HR, helm-controller would time out before the children reach Ready, rollback would delete the child HRs, and the upgrade would retry in a loop. The e2e bats step that patches the Tenant CR and waits 60s for child HRs to exist landed in the rollback gap and timed out. Two complementary changes: - tenant-root is created statically by cozystack-basics, so its HelmRelease spec.timeout is bumped 5m -> 15m directly. - Sub-tenants (Tenant CRs) get their HR built by cozystack-api from the tenant ApplicationDefinition. Add the release.cozystack.io/helm-install-timeout=15m annotation that kubernetes-rd already uses to opt the kind into the longer budget. Keeps both values in lockstep and documents the coupling inline. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
The bats step had two waits for tenant-root child HRs: kubectl wait hr/etcd hr/ingress hr/tenant-root hr/seaweedfs --timeout=4m kubectl wait hr/monitoring hr/seaweedfs-system --timeout=2m The second line was the residue of a flux-reconcile-force workaround removed in 7d292eb; the mechanical cleanup kept the same HRs on a separate 2m wait without revisiting whether the line still made sense. After PR #2509 fixed the underlying timing bug: - monitoring is a top-level tenant-root child, identical shape to etcd and ingress; its Ready is already implied by hr/tenant-root Ready on the first line. - seaweedfs-system is an internal HR of the seaweedfs umbrella chart; its Ready is already implied by hr/seaweedfs Ready on the first line. So the second wait was always tautologically true by the time it ran, and the naming inconsistency (top-level monitoring next to internal seaweedfs-system) was an accident of the historical workaround. Promote monitoring to the first line where it belongs and drop the redundant second wait. Also bump the wait from 4m to 10m. seaweedfs now installs as a serial chain seaweedfs-db (CNPG bootstrap) -> seaweedfs-system (raft quorum) -> seaweedfs wrapper, so the parent tenant-root HR's Ready flip lags ~5-6 min. The previous 4m budget was sized for the old single-HR seaweedfs and is the immediate cause of the e2e failure on PR #2619. The 10m budget stays inside tenant-root HR.spec.timeout (15m). Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Flux helm-controller v1.5.0 (shipped in Flux v2.8) replaced the legacy Helm readiness logic with kstatus-based health checking, which polls Deployment/StatefulSet/Service status and waits for kstatus to assess rollout-ready. This typically adds 10-30s of latency between resource apply and HR condition Ready=True compared to v2.7. Our per-app bats tests had `kubectl wait hr/... --for=condition=ready --timeout=` budgets of 20s, 30s, 60s, 100s — sized for v2.7's faster readiness flip and previously masked by the 3x retry on Run E2E tests (dropped in #2558). Under v2.8 with no retry, every app that runs after the first few hit its HR wait timeout exactly, surfacing as 13 of 16 test failures on PR #2619. Standardise on 5m for HR Ready across all app tests. Tight enough to catch genuine bring-up failures within the per-app job budget, loose enough to absorb kstatus dispatch jitter on a management cluster that is concurrently reconciling multiple tenant-test HRs. Post-HR-Ready checks for app-specific resources (StatefulSet/Service/ PVC/operator CRs) remain — for CR-based apps kstatus only observes that the chart applied, not that the operator finished. Audit of which of those are actually redundant under v2.8 kstatus is queued as a follow-up. Also bumps the 10s "kamajicontrolplane appears" wait in run-kubernetes.sh to 2m, and the kubernetes-addon HR Ready loop from 1m to 5m for the same reason. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Five PackageSources whose charts apply cert-manager Certificate CRs and mount the resulting Secret on a webhook Deployment lacked an explicit dependsOn: cozystack.cert-manager. Under Flux v2.8 helm-controller v1.5.0 kstatus, the dependent Deployment trips progressDeadlineSeconds (10m default) when cert-manager controller isn't running yet, and the HR is failed early. Repeatedly observed on PR #2619 with capi-operator, kamaji, rabbitmq-operator, cozystack-api (cozystack-engine), and ingress-nginx all cascading to InstallFailed at ~12-15m into a fresh install. The mariadb-operator, kubeovn-webhook, snapshot-controller, etcd-operator, postgres-operator, mongodb-operator, victoria-metrics-operator, linstor, and linstor-scheduler PackageSources already had the dependency, which is why they weren't in the failure set. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
…afka WorkloadMonitor replicas paths Flux v2.8 / helm-controller v1.5.0 embeds Helm v4, which renamed --force to --force-replace and rejects combining it with SSA's --force-conflicts. Existing HelmReleases with spec.upgrade.force: true fail every upgrade with "cannot use force conflicts and force replace together", looping upgrade -> rollback -> upgrade and blocking dependants. Observed on PR #2619 CI for tenant-root/{ingress-nginx-system,seaweedfs-db}, tenant-test/info, and others. Per Flux docs, upgrade.force has been a no-op since v2.8 anyway, so removing it is safe on green clusters and unblocks broken ones. Also fix packages/apps/kafka/templates/workloadmonitor.yaml: it referenced .Values.replicas (no such field; values.yaml has kafka.replicas and zookeeper.replicas). Flux v2.7 silently dropped the null; v2.8 SSA forwards it, and the WorkloadMonitor CRD rejects "spec.replicas: null" as not type:integer, which blocks every kafka-test install. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
Bump flux-operator and flux-instance vendored charts from v0.33.0 to v0.48.0, moving the Flux distribution from 2.7.x to 2.8.x. This brings helm-controller v1.5.x, which exposes spec.install.healthCheckExprs on HelmRelease — a prerequisite for adding real readiness gating to dependency-target packages (postgres, mongodb, kafka, etc.). The new flux-operator chart defaults web.enabled=true; override it to false in packages/system/fluxcd-operator/values.yaml so the Flux Status Web UI stays opt-in. Operators wanting it can set web.enabled=true and configure web.config / web.configSecretName / web.ingress per the upstream chart values. Patches reapplied: - kubernetesEnvs.diff: matched cleanly (offset shift only) - networkPolicy.diff: extended to also restrict port 9080 (web UI port); hunk count updated 20 -> 22 Pre-flight: no references to the v0.39-removed --disable-wait-interruption flag anywhere in packages/ or internal/. Verified locally: - helm template renders both packages without errors - web.enabled=false (default): no web Deployment/Service/NetworkPolicy - web.enabled=true: renders web NetworkPolicy on port 9080 - CiliumClusterwideNetworkPolicy lists 8080/8081/9080 - FluxInstance distribution.version: "2.8.x", all 7 components present - Cozystack kustomize patches (concurrent, requeue, storage-adv-addr, events-addr) intact Notable upstream changes between v0.33 and v0.48: - Flux 2.8.x with HelmRelease inventory format change (auto-migrated) - Reliability fixes for stuck FluxInstance/ResourceSet on health-check cancellation (v0.39, v0.46) - New CLI: flux-operator migrate, diff, patch instance, distro mirror - ResourceSetInputProvider: GitLab Environments, GitHub App, Gitea/Forgejo - CVE-2026-23990 (Web UI OIDC impersonation bypass) — N/A while web is off Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
… 2.8.0 Re-render internal/fluxinstall/manifests/fluxcd.yaml via `make update` in packages/core/flux-aio (timoni bundle build against oci://ghcr.io/stefanprodan/modules/flux-aio at the latest tag) so the cozystack-operator binary embeds Flux 2.8.0 instead of 2.7.3. Auto-syncs the helm-controller image into fluxcd-tenants.yaml. Embedded versions now match the chart bump in the prior commit: flux: v2.7.3 -> v2.8.0 helm-controller: v1.4.3 -> v1.5.0 (enables healthCheckExprs) source-controller: v1.7.3 -> v1.8.0 kustomize-controller: v1.7.2 -> v1.8.0 notification-controller:v1.7.4 -> v1.8.0 source-watcher: v2.0.2 -> v2.1.0 Verified by rebuilding cmd/cozystack-operator and running `strings` on the binary -- the expected v1.5.0 / v1.8.0 / v2.1.0 image strings are now embedded in place of the v1.4.x / v1.7.x ones. Structure preserved: - single AIO Deployment named "flux" in namespace cozy-fluxcd - all 5 controllers + source-watcher as containers in one pod - custom tolerations from flux-aio.cue intact - Namespace pod-security label still "privileged" via the Makefile yq post-processing step Net diff is -3664 lines (mostly CRD schema simplification in 2.8). Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
|
Split into 8 review-friendly PRs. All branches rebased onto fresh main; all commits GPG-signed + DCO-signed-off; duplicate signoff trailers de-duped. Numbering follows the proposal we agreed on: Chain (B stacks on A):
Independent of #2602:
Dropped (already merged separately on main):
Dropped (not re-proposed):
Closing this PR. All review activity should move to the split PRs. |
) ## What this PR does Adds `startupProbe` to two operator deployments whose readiness probes fail repeatedly during a cold cluster install, generating noise and (for CDI) blocking dependants on slow leader-election: - **`kubevirt-cdi-operator`** — leader-election against a slow `kube-apiserver` (Kamaji control plane bringup) consistently takes >30s on a cold install. The default readinessProbe with 1s `periodSeconds` / 3 `failureThreshold` fires the first time election times out, the operator pod gets marked NotReady, and dependants block on it. - **`grafana-operator`** — bootstrap CRD discovery + Helm-managed Dashboard reconcile loop spikes startup duration past readinessProbe's default budget under load. `startupProbe` gives each operator a longer one-time window to reach steady state; the regular `readinessProbe` then takes over with its tight per-second cadence to detect genuine ongoing failures. ## Origin Both commits lifted unchanged from #2619. ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Configuration Updates** * Added startup health checks to Grafana operator container * Added startup health checks to KubeVirt CDI operator container <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2725?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What this PR does Pre-pulls every image referenced by `packages/system/kubeovn`, `packages/system/linstor`, and `packages/system/cert-manager` onto every node before those HelmReleases install. Cluster-member workloads (OVN raft, LINSTOR, cert-manager webhook) fail when replicas start at different times due to per-node image-pull stagger; pre-pulling means all replicas start with images already cached. ## Mechanics Renders each chart with `helm template`, then runs a `yq` filter that walks every PodSpec-shaped object and emits the images of each container — scoping the output to images the kubelet actually pulls (skips configmap fields and CRD examples that happen to contain an `image:` key). Each render is staged through a tmp file so a helm-template failure trips `set -e` cleanly (cozytest.sh runs `@test` bodies under `/bin/sh`, which is dash on Ubuntu CI — no `pipefail`). The pre-pull DaemonSet itself is the hard part: distroless images (cert-manager and friends) ship no shell and no `/bin/sleep`, so the obvious `command: ["sleep", "infinity"]` fails with `exec: ENOENT`. The script stages a statically-linked `busybox:musl` into a shared `emptyDir` from an initContainer; every prepull container then execs `/shared/sleep` regardless of what the image itself ships. The glibc `busybox` tag is unusable — it needs `/lib64/ld-linux-x86-64.so.2` which distroless lacks. ## Origin Lifted from #2619 — squash of `test(e2e): pre-pull cert-manager images` → POSIX rewrite → cert-manager removal (failed on distroless) → reintroduction with the busybox helper that solves the distroless problem. Final state only — the four iterative commits aren't review-friendly individually. ## Verification - `sh -n hack/e2e-prepull-images.sh` clean - All chart-referenced images held Ready under the DaemonSet on local kind v1.33.1 single-node ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Improved end-to-end test reliability for platform image pre-pulling by rendering charts separately and consolidating extracted images. * Simplified and consolidated readiness waits during tenant configuration for more robust application readiness checks. * **Chores** * Enhanced image pre-pulling to reliably handle distroless images using a staged helper binary and shared volume approach. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2724?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Five PackageSources whose charts apply cert-manager Certificate CRs and mount the resulting Secret on a webhook Deployment lacked an explicit dependsOn: cozystack.cert-manager. Under Flux v2.8 helm-controller v1.5.0 kstatus, the dependent Deployment trips progressDeadlineSeconds (10m default) when cert-manager controller isn't running yet, and the HR is failed early. Repeatedly observed on PR #2619 with capi-operator, kamaji, rabbitmq-operator, cozystack-api (cozystack-engine), and ingress-nginx all cascading to InstallFailed at ~12-15m into a fresh install. The mariadb-operator, kubeovn-webhook, snapshot-controller, etcd-operator, postgres-operator, mongodb-operator, victoria-metrics-operator, linstor, and linstor-scheduler PackageSources already had the dependency, which is why they weren't in the failure set. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> (cherry picked from commit 0fc0796)
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)
…2726) ## What this PR does Adds `cert-manager` as a `dependsOn` entry to the five PackageSources whose charts apply `cert-manager.io/v1` `Certificate` CRs and need the webhook ready before their first reconcile. Without this, the helm install renders Certificate manifests, the cert-manager webhook isn't admitting requests yet (cold cluster), the apply fails, and helm-controller retries until the webhook eventually comes up — burning ~2-3 minutes per affected package on cold installs. The five PackageSources: `capi-operator`, `cozystack-engine`, `ingress-nginx`, `kamaji`, and `rabbitmq-operator` (the platform `cozy-system` set with webhook-cert consumers; not the apps layer). In `cozystack-engine`, the dependency is added to both the `default` and `oidc` variants — the `oidc` variant installs the same `cozystack-api` and `lineage-controller-webhook` components that render Certificate resources, so it had the same race. ## Origin First commit lifted unchanged from #2619. Second commit (`oidc` variant) added in response to review feedback. ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Chores** * Updated package source dependencies across multiple components to ensure proper installation sequencing. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2726?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…rl (#2728) ## 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 #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 ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Integrated Ouroboros validations into the main Kubernetes end-to-end flow (removed separate standalone Ouroboros test) * Added hairpin-NAT and in-tenant DNS resolution checks for Ouroboros scenarios * Improved Keycloak OIDC test by configuring an in-cluster internal URL * Increased various timeouts and readiness waits and added tenant CSI readiness gating to improve test reliability <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2728?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…afka WorkloadMonitor replicas paths Flux v2.8 / helm-controller v1.5.0 embeds Helm v4, which renamed --force to --force-replace and rejects combining it with SSA's --force-conflicts. Existing HelmReleases with spec.upgrade.force: true fail every upgrade with "cannot use force conflicts and force replace together", looping upgrade -> rollback -> upgrade and blocking dependants. Observed on PR #2619 CI for tenant-root/{ingress-nginx-system,seaweedfs-db}, tenant-test/info, and others. Per Flux docs, upgrade.force has been a no-op since v2.8 anyway, so removing it is safe on green clusters and unblocks broken ones. Also fix packages/apps/kafka/templates/workloadmonitor.yaml: it referenced .Values.replicas (no such field; values.yaml has kafka.replicas and zookeeper.replicas). Flux v2.7 silently dropped the null; v2.8 SSA forwards it, and the WorkloadMonitor CRD rejects "spec.replicas: null" as not type:integer, which blocks every kafka-test install. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> (cherry picked from commit 7e286cf)
…or-vpa HR
The packages/system/vertical-pod-autoscaler chart's vpa-for-vpa.yaml template
emits an HR in cozy-vpa-for-vpa that the parent helm install applies and waits
on. That nested HR had `dependsOn: monitoring-agents`, which never resolves:
parent VPA helm install
waits for nested vpa-for-vpa HR Ready
waits for monitoring-agents HR Ready
waits for cozystack.vertical-pod-autoscaler PackageSource Ready
waits for parent VPA HR Ready <-- back to start
Symptom observed on PR #2619 e2e (cozyreport):
Helm upgrade failed for release cozy-vertical-pod-autoscaler/
vertical-pod-autoscaler with chart cozy-vertical-pod-autoscaler@...:
timeout waiting for: [HelmRelease/cozy-vpa-for-vpa/vpa-for-vpa
status: 'InProgress']
The recommender's /health-check readiness probe is served by the binary
itself and doesn't require Prometheus. Removing the dependsOn lets the
nested HR become Ready quickly; the recommender will log connection
errors against vmselect until monitoring-agents installs later in the
boot sequence, then start producing recommendations normally.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit 08433dc)
Flux helm-controller v1.5.0 (shipped in Flux v2.8) replaced the legacy Helm readiness logic with kstatus-based health checking, which polls Deployment/StatefulSet/Service status and waits for kstatus to assess rollout-ready. This typically adds 10-30s of latency between resource apply and HR condition Ready=True compared to v2.7. Our per-app bats tests had `kubectl wait hr/... --for=condition=ready --timeout=` budgets of 20s, 30s, 60s, 100s — sized for v2.7's faster readiness flip and previously masked by the 3x retry on Run E2E tests (dropped in #2558). Under v2.8 with no retry, every app that runs after the first few hit its HR wait timeout exactly, surfacing as 13 of 16 test failures on PR #2619. Standardise on 5m for HR Ready across all app tests. Tight enough to catch genuine bring-up failures within the per-app job budget, loose enough to absorb kstatus dispatch jitter on a management cluster that is concurrently reconciling multiple tenant-test HRs. Post-HR-Ready checks for app-specific resources (StatefulSet/Service/ PVC/operator CRs) remain — for CR-based apps kstatus only observes that the chart applied, not that the operator finished. Audit of which of those are actually redundant under v2.8 kstatus is queued as a follow-up. Also bumps the 10s "kamajicontrolplane appears" wait in run-kubernetes.sh to 2m, and the kubernetes-addon HR Ready loop from 1m to 5m for the same reason. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> (cherry picked from commit 5ef02ee)
PR #2619 split seaweedfs into a serialized chain (seaweedfs-db -> seaweedfs-system -> seaweedfs) that needs ~5 min of wall-clock to install: CNPG bootstrap, master quorum, then the wrapper. With the prior 5m wait budget on the parent tenant HR, helm-controller would time out before the children reach Ready, rollback would delete the child HRs, and the upgrade would retry in a loop. The e2e bats step that patches the Tenant CR and waits 60s for child HRs to exist landed in the rollback gap and timed out. Two complementary changes: - tenant-root is created statically by cozystack-basics, so its HelmRelease spec.timeout is bumped 5m -> 15m directly. - Sub-tenants (Tenant CRs) get their HR built by cozystack-api from the tenant ApplicationDefinition. Add the release.cozystack.io/helm-install-timeout=15m annotation that kubernetes-rd already uses to opt the kind into the longer budget. Keeps both values in lockstep and documents the coupling inline. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> (cherry picked from commit cc9da3a)
…edfs-system (#2601) ## What this PR does Splits the `seaweedfs-system` HelmRelease into two: the CNPG `Cluster/seaweedfs-db` moves to its own HR (`seaweedfs-db`), and the application HR (`seaweedfs-system`) `dependsOn` it. The new HR uses Flux v2 `HelmRelease.spec.healthCheckExprs` with a CEL expression on `Cluster.status.conditions[type=Ready]` plus `waitStrategy.name: poller`, so its `Ready=True` only flips after the postgres primary is actually serving connections — not just after `helm install` applied the `Cluster` CR. This eliminates the `seaweedfs-filer` CrashLoopBackOff race on a fresh tenant install. With Cilium `kubeProxyReplacement: true`, socket-LB returns `EPERM` from `connect(2)` to ClusterIPs with no Ready endpoints. Pre-split, the filer StatefulSet scheduled concurrently with the CNPG bootstrap (~55–70s of unavailable postgres), each `connect()` failed `EPERM`, kubelet exponential restart backoff pushed past the e2e bats `kubectl wait hr/seaweedfs-system --timeout=2m` window, and the "Configure Tenant and wait for applications" test failed. ## Stacked on #2602 This PR depends on **#2602** (Flux v2.8.0 upgrade) — `healthCheckExprs` is a helm-controller v1.5.0 feature. GitHub base set to `flux-bump-v048` so the diff cleanly shows only this PR's changes; will auto-rebase onto `main` once #2602 merges. ## Commits 1. **`refactor(seaweedfs)`** — the split itself. Squash of the three iterative commits from the consolidated branch (#2619): the initial split, a `dependsOn` merge-collision fix (collapses unconditional `seaweedfs-db` dependency with the namespace-guarded ingress dependency into one list), and the `healthCheckExprs` three-predicate form (route CNPG's `ClusterIsNotReady` bootstrap condition to `inProgress`, reserve `failed` for other `Ready=False` reasons, lean on the HR `timeout: 10m` as the real backstop). 2. **`fix(tenant)`** — bump parent HR `spec.timeout` from 5m → 15m so the serialized `seaweedfs-db → seaweedfs-system → seaweedfs` chain has enough wall-clock budget. Two complementary changes: the static `tenant-root` HR (created by `cozystack-basics`) gets its `spec.timeout` bumped directly; sub-tenants (Tenant CRs whose HR is built by `cozystack-api` from the `tenant` ApplicationDefinition) get the `release.cozystack.io/helm-install-timeout=15m` annotation that `kubernetes-rd` already uses to opt into the longer budget. 3. **`test(e2e)`** — consolidate two redundant child-HR waits in `hack/e2e-install-cozystack.bats` into one budgeted assert. The second `kubectl wait` (`hr/monitoring hr/seaweedfs-system --timeout=2m`) was a residue of a `flux-reconcile-force` workaround removed in #2509; `monitoring`'s Ready is already implied by `hr/tenant-root` Ready and `seaweedfs-system`'s by `hr/seaweedfs` Ready, so the line was tautologically true by the time it ran. ## Migration `packages/core/platform/images/migrations/migrations/42` adopts existing `Cluster/seaweedfs-db` resources into the new release on upgrade — rewrites `meta.helm.sh/release-name: seaweedfs-system → seaweedfs-db` and stamps `helm.sh/resource-policy: keep` so the `seaweedfs-system` upgrade (which no longer renders the Cluster) does not delete it during the transition. Renumbered from the consolidated branch's slot 40 to fit fresh main (last migration is 41). `targetVersion` bumped 42 → 43. The new HR's `upgrade.force: true` was dropped to match #2602's platform-wide cleanup (Helm v4 in helm-controller v1.5.0 rejects combining `--force-replace` with SSA's `--force-conflicts`). ## Verification - `helm template` renders `seaweedfs-db` HR cleanly with `healthCheckExprs`, `waitStrategy: poller`, and `upgrade: { remediation: { retries: -1 } }` (no `force: true`). - Migration 42 syntax-checks under `sh -n`. - All four PR commits GPG-signed + DCO-signed-off. ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * SeaweedFS database is now available as a separate, independently configurable component with customizable replicas, storage size, and storage class options. * **Chores** * Restructured database configuration from the main application into a dedicated component for improved modularity and initialization order. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2601?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…(folds #2612) (#2602) ## What this PR does Upgrades Flux v2.7.3 → v2.8.0 across both the vendored tenant chart and the embedded management-cluster manifests, and folds in the chart fixes that become hard errors under the new strict helm-controller v1.5. Flux v2.8's helm-controller v1.5.0 ships: - **Server-Side Apply with `--force-conflicts`** — strict CRD schema enforcement; misplaced fields (silently dropped on v2.7) now fail the apply. - **kstatus-based health checking** by default — parent HR waits for every applied resource (including child HRs) to be Ready before flipping its own Ready, surfacing latent ordering deadlocks. - **Helm v4 embedded** — `upgrade.force: true` is deprecated and now conflicts with SSA. - **`HelmRelease.spec.healthCheckExprs`** — prerequisite for proper readiness gating (used in PR #2601 split). Folds in PR #2612 (kubevirt-instancetypes null TPM fix) since the same Flux upgrade triggers it. ## Commits **Flux upgrade itself:** - `feat(fluxcd)`: bump `flux-operator` / `flux-instance` vendored charts to v0.48.0; web UI opt-in. - `feat(flux)`: regenerate embedded management-cluster manifests via `make update` in `packages/core/flux-aio` (timoni bundle build). **Chart fixes for strict SSA — fields the chart sent that v2.7 silently dropped, v2.8 rejects:** - `fix(kubevirt-instancetypes)`: drop persistent strip that produced null `preferredTPM` (folds #2612). - `fix(foundationdb)`: relocate `faultDomain`, `imageType`, `labels`, `minimumUptimeSecondsForBounce` from inside `automationOptions` to direct children of `spec`. - `fix(kafka)`: place `enableServiceLinks` under `template.pod`, not a phantom `template.spec`. - `fix(vm-instance)`: emit `disk: {}` (not `disk:`/null) when no bus is set. - `fix(platform)`: drop deprecated `upgrade.force: true` from HelmReleases; fix `kafka` WorkloadMonitor `replicas` paths. **Ordering / deadlock fixes under v2.8 kstatus:** - `fix(vpa)`: break circular wait between parent install and nested `vpa-for-vpa` HR. - `fix(kubernetes)`: drop lookup-guarded parent-HR `dependsOn` on tenant addon child HRs (parent waits on child via kstatus, child waited on parent — deadlock). **E2E waits for v2.8 kstatus timing:** - `test(e2e)`: bump app HR-Ready waits to 5m (was 20s–100s under v2.7's faster dispatch). - `test(e2e)`: wait for parent HR Ready before downstream asserts in `run-kubernetes.sh` and `vminstance.bats`. ## Scope discipline This PR is part of the split of #2619 (the consolidated CI fixes branch) into review-friendly pieces. Companion PRs: - **PR #2601** (seaweedfs split) — folded into this PR (commits `29c6afc8`, `0e8b46d7`, `7157158c`, `dccdeb52`, `f880b324`): the seaweedfs-system → seaweedfs-db + seaweedfs-system split, its adoption migration 43 (targetVersion 44), and the configurable db resources all land here, because the strict-SSA `upgrade.force` removal and the kstatus parent-HR timeout bump only make sense together with the split. #2601 is superseded. - **PR #2558** (drop 3× retry on `Run E2E` + `Install Cozystack`) — independent, lands separately. - Several smaller standalone fixes lifted out of #2619 (startup probes, cert-manager `dependsOn`, prepull machinery, CSI HR timeout, NFS/OIDC test improvements) — opened as separate PRs. ## Verification - `helm template` renders cleanly for both `fluxcd` and `fluxcd-operator` packages with `web.enabled=false` (default) and `web.enabled=true`. - Embedded `cmd/cozystack-operator` binary contains the v1.5.0 / v1.8.0 / v2.1.0 controller image strings. - No references to the v0.39-removed `--disable-wait-interruption` flag anywhere in `packages/` or `internal/`. ### Release note ```release-note Flux upgraded to v2.8.0 (helm-controller v1.5 — Helm v4 Server-Side Apply with --force-conflicts, kstatus health checking). When upgrading existing clusters: - Kubernetes 1.33+ is now required for the platform (management) cluster, and for any tenant cluster that enables the optional (default-off) Flux addon — that addon ships the bumped Flux too. - HelmReleases no longer set `upgrade.force: true`. Helm v4 SSA resolves field-ownership conflicts automatically (`--force-conflicts`), but that is not the old client-side replace: immutable-field changes (e.g. StatefulSet volumeClaimTemplates/serviceName) no longer self-heal and require manual recreation — delete the object (e.g. `kubectl delete sts <name> --cascade=orphan`) and let Flux recreate it. - KubeVirt: persistent TPM/EFI is re-enabled for the Windows 11/2k22/2k25 preferences (KubeVirt 1.8 VMPersistentState); each affected VM provisions an extra RWO backend-storage PVC from the default StorageClass. - KubeVirt: the EOL centos.7*/centos.stream8* preferences are retained as deprecated, hidden aliases (`tags: hidden`, `instancetype.kubevirt.io/deprecated: "true"`) — existing VMInstances on these profiles keep rendering and need no action on upgrade, but the profiles are no longer offered for new VMs; repoint to centos.stream9/10 when convenient. The gn1.* GPU instancetypes are likewise retained. - FoundationDB: imageType now reaches the operator (silently dropped pre-SSA); it is pinned to `split` to match the value existing clusters effectively ran, so upgrades stay non-disruptive. Set `imageType: unified` to migrate deliberately. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Flux Status web UI: optional web server, config secret, service port, HTTPRoute/Ingress, network policy, and RBAC roles. * New SeaweedFS DB Helm chart and optional managed DB release. * **Improvements** * CRD/schema enhancements: new provider kinds, validations, variant option, and external checksum refs. * Raised Kubernetes prerequisite to 1.30+; extended e2e timeouts for reliability. * **Chores** * Bumped Flux Operator and Flux versions; documentation links updated to fluxoperator.dev. * **Bug Fixes** * Removed aggressive HelmRelease force-upgrade/install flags. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2602?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Aligns kubevirt-csi-node HR with every other tenant addon HR in packages/apps/kubernetes/templates/helmreleases/ (cilium, coredns, ingress-nginx, etc.) — all set timeout: 10m, csi.yaml was the only exception. 9f9d8f8 ("Allign timeouts for HelmReleases") missed it. Symptom: e2e NFS test (hack/e2e-apps/run-kubernetes.sh) times out waiting for nfs-test-pod to reach Succeeded. Cozyreport events show the tenant csi HR running Install -> Uninstall -> Install remediation cycles. With install.remediation.retries: -1 and the default 5m Helm timeout, kstatus marks the kubevirt-csi-node DaemonSet 'InProgress' past 5m on a slow tenant control-plane bringup (Kamaji APIs flapping, VM image pulls), helm-controller times out, the remediation uninstalls the DaemonSet, then reinstalls. Any volume mount in flight at that moment is wedged. Observed on PR #2619 CI run 26142986969: csi HR remediation at ~07:07 happened ~10 min into the nfs-test-pod wait, killing the mount and timing out the pod-Succeeded condition. 10m matches the surrounding HRs and gives the DaemonSet headroom without changing remediation semantics on truly-broken installs. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> (cherry picked from commit 866588f)
|
Closing this because it was preview of changes, actual progress here #2397 |
Aligns kubevirt-csi-node HR with every other tenant addon HR in packages/apps/kubernetes/templates/helmreleases/ (cilium, coredns, ingress-nginx, etc.) — all set timeout: 10m, csi.yaml was the only exception. 9f9d8f8 ("Allign timeouts for HelmReleases") missed it. Symptom: e2e NFS test (hack/e2e-apps/run-kubernetes.sh) times out waiting for nfs-test-pod to reach Succeeded. Cozyreport events show the tenant csi HR running Install -> Uninstall -> Install remediation cycles. With install.remediation.retries: -1 and the default 5m Helm timeout, kstatus marks the kubevirt-csi-node DaemonSet 'InProgress' past 5m on a slow tenant control-plane bringup (Kamaji APIs flapping, VM image pulls), helm-controller times out, the remediation uninstalls the DaemonSet, then reinstalls. Any volume mount in flight at that moment is wedged. Observed on PR #2619 CI run 26142986969: csi HR remediation at ~07:07 happened ~10 min into the nfs-test-pod wait, killing the mount and timing out the pod-Succeeded condition. 10m matches the surrounding HRs and gives the DaemonSet headroom without changing remediation semantics on truly-broken installs. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> (cherry picked from commit 866588f)
…ay.bats tenant teardown (#2558) ## What this PR does Drops the 3× retry loop on `Run E2E tests` and `Install Cozystack into sandbox`. `Prepare environment` keeps its 3× retry — that step is pure infrastructure (Talos image download, sandbox VM boot, network) where transient runner hiccups warrant a retry. On failure, the test step now captures `kubectl get hr -A -o wide` and `kubectl get events -A` under a collapsible group so triage starts with the actual broken-state snapshot. > [!NOTE] > An earlier revision of this PR also doubled every bats timeout. That commit was dropped in a rebase and is intentionally **not restored**: the timeout class that actually matters (per-app HR-Ready waits) has since been standardized at 5m on `main` (7b9f286), making a blanket 2× redundant. **Fixes gateway.bats teardown leakage.** The nested-tenant tests deleted tenants fire-and-forget, parent and child back-to-back. The leftover uninstalls (each blocked on a cleanup Job, parents wedged on still-terminating child namespaces) plus one mid-install child HR occupied exactly 5 workers on the `--concurrent=5` tenants helm-controller shard, starving whichever app test ran next — observed as the harbor HR sitting unreconciled for its whole 5m HR-Ready budget in [run 27020081550](https://github.com/cozystack/cozystack/actions/runs/27020081550), surfaced by this PR's own retry removal + diagnostics dump. Teardown now deletes child→parent with hard `wait hr --for=delete` between, so a wedged tenant uninstall fails gateway.bats itself, not an innocent neighbor. ## Why Audit of 30 successful PR runs found that across 5 sampled failure attempts, **25/25 retries** on `Run E2E tests` failed — the retry loop never recovered a flake, only stretched deterministic failures and tripled diagnostic wall-time. Same data shape on `Install Cozystack`. Beyond wasted CI time, the retry was hiding ~10 deterministic bugs (Helm namespace-ownership conflict, seaweedfs HR timeout, harbor BucketInfo wiring, vminstance disk race, etc.). Each failure looked like a "flake" because the retry sometimes coincided with whatever transient state had cleared — the retry never fixed the bug, just delayed surfacing. ## Dependencies The deterministic bugs the retry was masking are now fixed on `main`: - ✅ **#2508** — installer namespace bootstrap (Helm namespace-ownership conflict on cold install) — merged - ✅ **#2509** — operator HelmRelease config knobs (`seaweedfs-system` 2-min wait race within Flux's 5-min reconcile windows) — merged - ✅ **#2528** — harbor bucket-secret + BucketInfo gating (harbor `ValuesError` on first install) — merged - ✅ **#2529** — objectstorage-controller BucketAccess conflict retry — merged Companion PRs in the #2619 split (independent of this PR, ordering-wise): - **#2602** — Flux v2.8.0 + chart fixes - **#2601** — seaweedfs-system split This PR does NOT depend on #2602/#2601 — it now touches only the workflow file and gateway.bats teardown, both on top of fresh `main`. Surfaced from #2500. ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * CI prepare-environment step now reports plain attempt counts with clear success/failure messages. * Install and per-app test steps no longer retry; each runs once and fails immediately on error. Failed apps log diagnostics and job proceeds to remaining apps while overall job fails. * **Tests** * End-to-end tests and install/prepare flows use longer, more tolerant timeouts and added existence polling to reduce flakiness and improve diagnostics. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2558?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Aligns kubevirt-csi-node HR with every other tenant addon HR in packages/apps/kubernetes/templates/helmreleases/ (cilium, coredns, ingress-nginx, etc.) — all set timeout: 10m, csi.yaml was the only exception. 9f9d8f8 ("Allign timeouts for HelmReleases") missed it. Symptom: e2e NFS test (hack/e2e-apps/run-kubernetes.sh) times out waiting for nfs-test-pod to reach Succeeded. Cozyreport events show the tenant csi HR running Install -> Uninstall -> Install remediation cycles. With install.remediation.retries: -1 and the default 5m Helm timeout, kstatus marks the kubevirt-csi-node DaemonSet 'InProgress' past 5m on a slow tenant control-plane bringup (Kamaji APIs flapping, VM image pulls), helm-controller times out, the remediation uninstalls the DaemonSet, then reinstalls. Any volume mount in flight at that moment is wedged. Observed on PR #2619 CI run 26142986969: csi HR remediation at ~07:07 happened ~10 min into the nfs-test-pod wait, killing the mount and timing out the pod-Succeeded condition. 10m matches the surrounding HRs and gives the DaemonSet headroom without changing remediation semantics on truly-broken installs. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> (cherry picked from commit 866588f)
Aligns kubevirt-csi-node HR with every other tenant addon HR in packages/apps/kubernetes/templates/helmreleases/ (cilium, coredns, ingress-nginx, etc.) — all set timeout: 10m, csi.yaml was the only exception. 9f9d8f8 ("Allign timeouts for HelmReleases") missed it. Symptom: e2e NFS test (hack/e2e-apps/run-kubernetes.sh) times out waiting for nfs-test-pod to reach Succeeded. Cozyreport events show the tenant csi HR running Install -> Uninstall -> Install remediation cycles. With install.remediation.retries: -1 and the default 5m Helm timeout, kstatus marks the kubevirt-csi-node DaemonSet 'InProgress' past 5m on a slow tenant control-plane bringup (Kamaji APIs flapping, VM image pulls), helm-controller times out, the remediation uninstalls the DaemonSet, then reinstalls. Any volume mount in flight at that moment is wedged. Observed on PR #2619 CI run 26142986969: csi HR remediation at ~07:07 happened ~10 min into the nfs-test-pod wait, killing the mount and timing out the pod-Succeeded condition. 10m matches the surrounding HRs and gives the DaemonSet headroom without changing remediation semantics on truly-broken installs. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> (cherry picked from commit 866588f)
## What this PR does Adds `spec.timeout: 10m` to the `kubevirt-csi-node` HelmRelease template in `packages/apps/kubernetes/templates/helmreleases/csi.yaml`, aligning it with every other tenant addon HR in the same directory (cilium, coredns, ingress-nginx, etc. — all set `timeout: 10m`). `csi.yaml` was the only one missing it; commit 9f9d8f8 ("Align timeouts for HelmReleases") missed this template. ## Symptom E2E NFS test times out waiting for `nfs-test-pod` to reach `Succeeded`. Cozyreport events show the tenant `csi` HR running an Install → Uninstall → Install remediation cycle. With `install.remediation.retries: -1` and the default 5m Helm timeout, kstatus marks the `kubevirt-csi-node` DaemonSet `InProgress` past 5m on a slow tenant control-plane bringup (Kamaji APIs flapping, VM image pulls), helm-controller times out, the remediation uninstalls the DaemonSet, then reinstalls. Any volume mount in flight at that moment is wedged. ## Origin Single commit lifted unchanged from #2619. ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated the Container Storage Interface (CSI) Helm release settings to include a `spec.timeout` of **10 minutes** when the etcd namespace value is set (keeping the existing `spec.interval` at **5 minutes**). <!-- end of auto-generated comment: release notes by coderabbit.ai -->
What this PR does
Consolidates four open PRs into a single branch so CI can run them together. Each individual PR fails CI on its own because the others' fixes are missing:
sedthat produced nullpreferredTPMand brokeVirtualMachineClusterPreferenceunder KubeVirt v1.8HelmRelease.spec.healthCheckExprs.seaweedfs-db+seaweedfs-systemwithhealthCheckExprson the CNPG Cluster Ready condition. Requires feat(flux): upgrade to v2.8.0 + chart fixes for strict SSA & kstatus (folds #2612) #2602.Original commits preserved via
--no-ffmerges, so authorship/signoffs are intact and the per-PR review history is recoverable. Once CI is green here, the four upstream PRs can be closed (or this PR can be split-merged in dependency order).Conflict resolution
One conflict during the #2601 merge:
packages/core/platform/images/migrations/migrations/39was added on both sides — main's #2607 (instance-type resourcesPreset migration, lands at v40) and #2601's seaweedfs adopt migration. Kept main's 39, renumbered seaweedfs to migration 40 (header: `Migration 40 --> 41`, version stamp: 41). No other conflicts.Verification
Release note
```release-note
NONE
```
Summary by CodeRabbit
New Features
Updates
Bug Fixes