mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-04 02:57:27 +09:00
fix/vm-instance-disk-null
3687
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0f3d2fa3a6 |
fix(vm-instance): emit empty disk object so KubeVirt accepts disks without bus
When a disk entry has no bus set (the schema default), the previous
template rendered `disk:` with no value — YAML parses that as
`disk: null` and KubeVirt's virtualmachines-mutator webhook denies the
request with: "spec.template.spec.domain.devices.disks.disk in body
must be of type object: null".
Restructure the disk loop so the disk/cdrom value is always a valid
object: `disk: {}` when bus is empty, `disk: {bus: <x>}` when set.
Mirrors how `cloudinitdisk` already does it in the same template.
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
|
||
|
|
70693ff35e |
feat(platform): add foundationdb backups (#2606)
<!-- Thank you for making a contribution! Here are some tips for you: - Use Conventional Commits for the PR title: `type(scope): description` - Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore - Scopes are not an exhaustive list — pick the most specific scope for the change and extend the list when a genuinely new area appears. Examples: - System components: dashboard, platform, operator, cilium, kube-ovn, linstor, fluxcd, cluster-api - Managed apps: postgres, mariadb, redis, kafka, clickhouse, virtual-machine, kubernetes - Development and maintenance: api, hack, tests, ci, docs, maintenance - Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or add a `BREAKING CHANGE:` footer - If it's a work in progress, consider creating this PR as a draft. - Don't hesistate to ask for opinion and review in the community chats, even if it's still a draft. - Add the label `backport` if it's a bugfix that needs to be backported to a previous version. --> ## What this PR does ### Screenshots <!-- REQUIRED for UI changes: attach screenshots or screen recordings demonstrating the visual impact of your changes. PRs with UI changes without screenshots will not be merged. --> ### Release note <!-- Write a release note: - Explain what has changed internally and for users. - Start with the same `type(scope):` prefix as in the PR title - Follow the guidelines at https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md. --> ```release-note implement backup controller for foundationdb backups ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added FoundationDB backup & restore support via a new FoundationDB backup strategy and controller; controller now handles FoundationDB backup/restore jobs. * **Examples** * Added a complete FoundationDB backup/restore demo with helper scripts, step-by-step step scripts, run-all, and cleanup tooling. * **Documentation** * New admin and tenant guides plus a README explaining the example workflow and verification steps. * **Deprecations** * In-chart FoundationDB backup configuration marked DEPRECATED—migrate to BackupClass + FoundationDB strategy. [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2606) <!-- end of auto-generated comment: release notes by coderabbit.ai -->api/apps/v1alpha1/v1.4.0-rc.1 |
||
|
|
92930ad1aa |
feat(platform): add implementation of backup-strategy controller for foundationdb
Signed-off-by: Andrey Kolkov <androndo@gmail.com> |
||
|
|
5f83ae72a8 |
feat(platform): implement backup strategy for mariadb (#2605)
<!-- Thank you for making a contribution! Here are some tips for you: - Use Conventional Commits for the PR title: `type(scope): description` - Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore - Scopes are not an exhaustive list — pick the most specific scope for the change and extend the list when a genuinely new area appears. Examples: - System components: dashboard, platform, operator, cilium, kube-ovn, linstor, fluxcd, cluster-api - Managed apps: postgres, mariadb, redis, kafka, clickhouse, virtual-machine, kubernetes - Development and maintenance: api, hack, tests, ci, docs, maintenance - Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or add a `BREAKING CHANGE:` footer - If it's a work in progress, consider creating this PR as a draft. - Don't hesistate to ask for opinion and review in the community chats, even if it's still a draft. - Add the label `backport` if it's a bugfix that needs to be backported to a previous version. --> ## What this PR does ### Screenshots <!-- REQUIRED for UI changes: attach screenshots or screen recordings demonstrating the visual impact of your changes. PRs with UI changes without screenshots will not be merged. --> ### Release note <!-- Write a release note: - Explain what has changed internally and for users. - Start with the same `type(scope):` prefix as in the PR title - Follow the guidelines at https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md. --> ```release-note implement backup strategy for MariaDB ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added native MariaDB backup/restore strategy using the operator-native BackupClass/Plan/RestoreJob flow with example manifests for end-to-end workflows. * **Documentation** * Added MariaDB how‑to and examples; marked legacy restic/chart-side backup parameters as DEPRECATED and documented migration guidance. * **Tests** * Added unit tests covering MariaDB backup/restore reconciliation, templating, storage handling, idempotency, URIs, and deadlines. * **Chores** * Extended controller RBAC to allow observing MariaDB operator resources. [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2605) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f38a047aa6 |
feat(kilo): add patched image build with cross mesh granularity (#2604)
## What this PR does Adds infrastructure for building a patched kilo image from upstream `main` branch source, following the same pattern as the kamaji package. The patch introduces a new `cross` mesh granularity mode — WireGuard tunnels are created only between nodes in different locations, while intra-location traffic stays on the CNI overlay. Changes: - `images/kilo/Dockerfile` — multi-stage build: fetches upstream tarball, applies patches, builds `kg`/`kgctl` binaries with CNI plugins and iptables-wrapper - `images/kilo/patches/feat-add-cross-mesh-granularity.diff` — adds `CrossGranularity` to the kilo binary - `Makefile` — new `image:` target for building the patched image, updated `update:` target to pin upstream commit SHA ### Screenshots N/A — no UI changes. ### Release note ```release-note feat(kilo): add patched image build with cross mesh granularity support ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added "cross" mesh granularity mode for finer topology grouping, adjusted routing/encryption behavior * Added e2e tests covering cross-mode scenarios for improved reliability * **Chores** * Build automation now tracks latest main commit and derives image digests from build metadata * Introduced multi-stage container build and runtime packaging for kilo, including required networking tooling * **Configuration** * Updated default image reference to a new repository and digest [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2604) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
92d128e8ff |
feat(keycloak): support extraEnv values and userProfile customization (#2613)
## What this PR does Two related quality-of-life additions to the Keycloak system component: 1. **`keycloak` chart now accepts `extraEnv`.** Operators can append extra `EnvVar` entries to the Keycloak StatefulSet container without forking the chart. Useful when a custom theme needs runtime configuration via `kcContext.properties`, or when an extension expects environment variables. 2. **`keycloak-configure` chart now exposes a top-level `userProfile` value** that is mirrored verbatim into `ClusterKeycloakRealm.spec.userProfileConfig`. This lets operators declare custom user-profile attributes (required fields, validators, permissions, ...) declaratively, alongside the existing `login` and `smtp` blocks. Both values default to empty, so existing deployments are unaffected. ### Release note ```release-note feat(keycloak): support extraEnv values and userProfile customization ``` |
||
|
|
62605a198b |
feat(platform): implement backup strategy for mariadb
Signed-off-by: Andrey Kolkov <androndo@gmail.com> |
||
|
|
c247bf48e5 |
feat(apps): instance-type resource presets with five series (#2607)
## What this PR does Closes #1959. Continuation of @matthieu-robin's instance-type resource presets work, addressing the migration gaps and resource regressions surfaced during the review of #1959. Resource presets now follow a cloud-style `<series>.<size>` naming convention. Five series cover the full CPU-to-memory ratio range, each with eight sizes (`nano` through `4xlarge`): | Series | Ratio | Use case | | ------ | ----- | -------- | | `t1` | 1:0.5 | Tiny / burstable, low memory | | `c1` | 1:1 | Compute-balanced | | `s1` | 1:2 | Standard — proxies, caches | | `u1` | 1:4 | Universal — databases, messaging | | `m1` | 1:8 | Memory — search, analytics | 40 instance-type presets in total. The seven legacy flat names (`nano`, `micro`, `small`, `medium`, `large`, `xlarge`, `2xlarge`) remain accepted as deprecated aliases. ### Upgrade path The combination of three mechanisms makes the rename a no-op for existing deployments: 1. **`cozy-lib` legacy aliases** — preserve the exact pre-rename CPU and memory for every legacy name. `helm template ... --set resourcesPreset=small` continues to render `1 CPU / 512Mi`, identical to before. No HelmRelease that already lives on the cluster breaks. 2. **Migration 39** — a pre-upgrade hook walks every `HelmRelease.spec.values` and every app CR under `apps.cozystack.io/v1alpha1`, rewriting legacy values to their 1:1 instance-type equivalents (`nano → t1.nano`, `medium → c1.small`, etc). Idempotent, best-effort, dry-runnable via `MIGRATION_DRY_RUN=1`, distinguishes "no items" from "kubectl errored" so a broken cluster cannot silently stamp the version. 3. **`cozystack-api` deprecation warning** — every `Create` and `Update` on an app CR with a legacy value emits a `klog` warning naming the JSON path and the 1:1 replacement, so operators discover any remaining legacy data after the platform upgrade. The legacy-to-instance-type mapping is 1:1 by CPU and memory: | Legacy | CPU | Memory | Instance-type | | -------- | ---- | ------ | ------------- | | `nano` | 250m | 128Mi | `t1.nano` | | `micro` | 500m | 256Mi | `t1.micro` | | `small` | 1 | 512Mi | `t1.small` | | `medium` | 1 | 1Gi | `c1.small` | | `large` | 2 | 2Gi | `c1.medium` | | `xlarge` | 4 | 4Gi | `c1.large` | | `2xlarge`| 8 | 8Gi | `c1.xlarge` | Mirrored in four places (cozy-lib template, Go package, migration jq, docs) with cross-reference comments so drift is visible. ### Why not just #1959 The implementation in #1959 had three blockers that motivated this rewrite: - **`cozy-lib` lost the legacy names entirely**, so any existing HelmRelease with `resourcesPreset: small` failed render with `Preset key 'small' invalid`. Aliases close this hole. - **Migration only touched HelmReleases**, leaving app CRs unmigrated; the next `kubectl edit` would fail enum validation. The new migration walks both. - **Defaults silently inflated memory**, e.g. Redis `nano → m1.nano` jumped from 128Mi to 2Gi (×16). With two replicas plus sentinel the e2e VM ran out of memory, producing the Redis 90s timeout that blocked the original PR. New defaults preserve resources 1:1. ### Deprecation timeline Legacy aliases are scheduled for removal in a future cozystack release. The combination of migration + operator warnings is expected to converge production clusters before then. Removal will land as a separate PR with its own migration cleanup pass. ### Test plan - `make unit-tests` — Go tests for the preset walker + warning helper, `helm unittest` legacy↔instance-type parity suites for `postgres`/`clickhouse`/`opensearch`, RD schema invariance check via `hack/check-rd-presets.sh`. - `make generate` is idempotent. - `helm template ./packages/apps/redis` with the new default renders 250m / 128Mi (matches pre-rename Redis exactly — closes the e2e blocker). - `helm template ./packages/apps/postgres --set resourcesPreset=small` renders 1 / 512Mi (legacy alias works). - Migration dry-run is exercised via `MIGRATION_DRY_RUN=1`. ### Documentation See [`docs/operations/resource-presets.md`](docs/operations/resource-presets.md) for the full size matrix and migration table. ### Release note ```release-note feat(cozy-lib): introduce `<series>.<size>` instance-type resource presets (t1/c1/s1/u1/m1 × 8 sizes). Legacy flat names (nano…2xlarge) remain accepted as deprecated 1:1 aliases; migration 39 rewrites stored values to the new form. CPU and memory are preserved exactly across the rename. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Expanded resource preset options to instance-style names (e.g., t1.*, c1.*, m1.*); legacy flat names remain supported as deprecated aliases. * Deprecation warnings now surface when legacy presets are detected. * **Documentation** * Added a comprehensive resource-presets guide and updated chart/app docs to the new naming convention. * **Tests** * Added compatibility tests ensuring legacy ↔ instance-type presets render identical resources. * **Chores** * Migration and CI checks to detect/upgrade legacy preset values. [](https://app.coderabbit.ai/change-stack/cozystack/cozystack/pull/2607) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
3e5b370f74 |
chore(keycloak): use generic example values in chart comments
Replace deployment-specific examples in the new extraEnv and userProfile docs with generic placeholders so the chart comments do not lean on any particular downstream use case. Assisted-By: Claude AI Signed-off-by: Kirill Ilin <stitch14@yandex.ru> |
||
|
|
2261ef7e25 |
feat(keycloak-configure): plumb userProfile into ClusterKeycloakRealm
Operators can now declare custom user-profile attributes (required fields, validators, permissions, ...) via a new top-level userProfile value. The value is mirrored verbatim into the ClusterKeycloakRealm.spec.userProfileConfig managed by the EDP keycloak-operator. The default remains empty, so realms that don't need custom user profile configuration are unaffected. Assisted-By: Claude AI Signed-off-by: Kirill Ilin <stitch14@yandex.ru> |
||
|
|
6413052abc |
feat(keycloak): expose extraEnv values to the StatefulSet
Custom themes (Keycloakify, FTL) often need runtime values from the deployment environment via kcContext.properties. Adding an extraEnv list to the chart lets operators inject those values per cluster without forking the chart. The new field appends verbatim to the container env list and accepts the full corev1.EnvVar schema, including valueFrom for secret or configMap-backed values. Assisted-By: Claude AI Signed-off-by: Kirill Ilin <stitch14@yandex.ru> |
||
|
|
55a98b8815 |
docs(apps): point seven app README preset tables at canonical docs
Address review feedback from coderabbitai across: - packages/apps/kubernetes/README.md - packages/apps/mariadb/README.md - packages/apps/nats/README.md - packages/apps/qdrant/README.md - packages/apps/redis/README.md - packages/apps/tcp-balancer/README.md - packages/apps/vpn/README.md Each of these READMEs left an inline 7-row preset table listing only the legacy flat names after the parameters block above already defaulted to an instance-type value (e.g. `t1.nano`). cozyvalues-gen only regenerates the `## Parameters` block, so the hand-written section drifted. Replace the inline tables with the same short paragraph already used by postgres and kafka READMEs: name the five series, note that the seven legacy names remain accepted as deprecated aliases, and link to the canonical reference at docs/operations/resource-presets.md so the full size matrix and legacy mapping live in exactly one place. Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
e90736ed5f |
test(presets): surface diff on FormatDeprecationMessages mismatch
Address review feedback from coderabbitai on pkg/apis/apps/presets/legacy_test.go:151. Replace the index-by-index loop over `got` with a single t.Fatalf that prints both slices via %#v. The previous loop iterated only across `got`, so extra entries in `want` would slip past unreported when `got` was shorter than `want`; t.Fatalf with full slice representations names both sides regardless of length. Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
af46317d16 |
fix(api): log JSON parse error on deprecation walk
Address review feedback from gemini-code-assist on pkg/registry/apps/application/rest.go:1777. When app.Spec.Raw cannot be unmarshalled to map[string]any the deprecation walker now logs a klog.V(2) line naming the kind, name, namespace and the underlying error before returning. Upstream validation still owns rejecting invalid specs (this hook is purely informational), so the log stays at debug verbosity rather than surfacing as a warning that would fire on transient inputs the caller is about to reject anyway. Helper signature changed to (kind, namespace, name string, raw []byte) so the malformed-input path is reachable from existing unit tests without forcing a fake Application wrapper. Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
9d9750e736 |
fix(hack): tighten resourcesPreset enum check
Address review feedback from gemini-code-assist on hack/check-rd-presets.sh:26
and coderabbitai on hack/check-rd-presets.sh:37.
- Switch the jq enum extractor from a description-substring heuristic
(test("preset"; "i")) to a JSON path-suffix selector that matches
fields literally named resourcesPreset. Eliminates false positives
from unrelated fields whose descriptions happen to mention "preset".
- Use grep -F for literal enum membership so the "." in entries like
t1.nano cannot accidentally match arbitrary characters (e.g. a typo
t1xnano would have satisfied t1.nano under basic regex).
Signed-off-by: Aleksei Sviridkin <f@lex.la>
|
||
|
|
cca54d876a |
docs(operations): resource presets reference
Document the five instance-type series (t1/c1/s1/u1/m1) introduced alongside the legacy preset deprecation, the per-size CPU and memory matrix, and the 1:1 legacy-to-instance-type mapping table that powers cozy-lib aliases, migration 39, and the operator-side deprecation warning. Single source of truth referenced from: - packages/library/cozy-lib/templates/_resourcepresets.tpl - packages/core/platform/images/migrations/migrations/39 - pkg/apis/apps/presets/legacy.go Includes an explicit callout that legacy `medium` (1 CPU / 1Gi) and instance-type `*.medium` (2 CPU) are not the same — same word, different resources. Replace inline preset tables in packages/apps/postgres/README.md and packages/apps/kafka/README.md with a short paragraph that names the five series and points at the canonical doc, since the per-app inline tables listed only the legacy seven and would drift further as the canonical matrix evolves. Co-authored-by: Matthieu ROBIN <matthieu@hidora.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
55850aa3d8 |
test(apps): backward-compat helm-unittest and CI invariants
Pin the 1:1 equivalence between legacy flat preset names and their
instance-type counterparts in helm-unittest for three charts that
exercise different preset shapes:
- postgres — top-level only
- clickhouse — top + nested clickhouseKeeper preset
- opensearch — top + nested dashboards preset
Each case asserts that nano <-> t1.nano, small <-> t1.small,
medium <-> c1.small, large <-> c1.medium, and micro <-> t1.micro
render the same CPU and memory.
packages/apps/{clickhouse,opensearch}/Makefile gain a `test:` target
that calls helm unittest so hack/helm-unit-tests.sh actually runs the
new suites in CI; without it the suites would land as dead weight.
hack/check-rd-presets.sh enforces two invariants in `make unit-tests`:
- every packages/system/*-rd/cozyrds/*.yaml openAPISchema carries
the canonical 47-preset enum (40 instance-type + 7 legacy);
- no chart template carries a hardcoded legacy preset literal in
a defaultingSanitize (list "<legacy>" ...) form.
Both turn an accidental drop of a per-chart Makefile step or an
accidental legacy hardcode into a CI failure rather than silent
production-time validation rejection.
Co-authored-by: Matthieu ROBIN <matthieu@hidora.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
|
||
|
|
f18ce1974e |
feat(platform): migration 39 converts legacy resourcesPreset values
Add a new pre-upgrade hook migration that walks every HelmRelease
spec.values and every app CR spec under apps.cozystack.io/v1alpha1, and
rewrites legacy flat resourcesPreset values (nano/micro/small/medium/
large/xlarge/2xlarge) to their instance-type equivalents (t1/c1).
Mapping is 1:1 by CPU and memory — the migration never bumps resource
usage. The same table lives in cozy-lib (legacy aliases) and in
pkg/apis/apps/presets/legacy.go.
Properties:
- Idempotent: re-running on a converted cluster is a no-op because
non-legacy values fall through the jq map_legacy else arm.
- Best-effort: a single failed patch logs a warning and continues;
cozy-lib legacy aliases keep charts rendering with identical CPU
and memory even if the migration is incomplete. kubectl patch
stderr is captured and surfaced in the WARN line so operators see
why a patch was rejected.
- Distinguishes "no items" from "kubectl errored" (RBAC stripped,
network down, CRD missing) so a broken cluster cannot look
identical to a clean no-op run and stamp the version
unconditionally.
- Dry-run: MIGRATION_DRY_RUN=1 prints the would-be patches and
leaves the version stamp at 39.
- Final summary echoed to both stdout and stderr.
- Version stamp only advances to 40 on a fully successful real run.
Bump migrations.targetVersion 39 -> 40 so the hook executes on the
next platform upgrade.
Co-authored-by: Matthieu ROBIN <matthieu@hidora.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
|
||
|
|
3a922f654e |
feat(api): warn on deprecated flat resourcesPreset values
cozystack-api now scans each app CR Create and Update for the legacy flat resourcesPreset names (nano, micro, small, medium, large, xlarge, 2xlarge) and emits a klog warning per occurrence with the dotted JSON path inside the spec and the suggested 1:1 instance-type replacement. Example log line: Postgres/foo in tenant-x uses deprecated resourcesPreset "small" at spec.resourcesPreset; migrate to "t1.small" (1:1 equivalent CPU and memory) Warnings are non-blocking. Legacy values still render correctly through the cozy-lib legacy alias table; the warning helps operators discover remaining legacy data after the platform upgrade. The mapping table lives in pkg/apis/apps/presets/legacy.go and is the single Go-side source of truth. The walker handles top-level, nested, in-array, non-string and malformed-spec inputs. The wrapper warns are emitted via a pure helper deprecationMessagesFor so the message format is unit-testable without intercepting klog. Co-authored-by: Matthieu ROBIN <matthieu@hidora.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
fdffedbd4b |
feat(apps): instance-type resourcesPreset across apps and extras
Rewrite resourcesPreset values in every apps/* and extras/* chart from the legacy flat names to the new instance-type form, using the 1:1 mapping: nano -> t1.nano micro -> t1.micro small -> t1.small medium -> c1.small large -> c1.medium xlarge -> c1.large 2xlarge -> c1.xlarge Each affected values.yaml carries the canonical 47-value enum (40 instance-type names plus 7 legacy aliases) so the schema accepts both forms during the deprecation window. cozyvalues-gen regenerates the matching api/apps/v1alpha1/*/types.go kubebuilder enum and defaults, the chart values.schema.json, the README parameter table, and the ApplicationDefinition openAPISchema in packages/system/*-rd/cozyrds. Three hardcoded legacy literals in chart templates migrated: - packages/apps/harbor/templates/harbor.yaml:121 (portal) - packages/apps/opensearch/templates/opensearch.yaml:43 (dashboards) - packages/system/keycloak/templates/sts.yaml:115 (heap fallback) packages/apps/foundationdb/Makefile gains the missing hack/update-crd.sh call. Without it, every regen left foundationdb-rd cozyrds stale and new FoundationDB app CRs through cozystack-api were rejected at validation for any non-legacy resourcesPreset value. Every default-rendered chart produces identical CPU and memory to the value applied before the rename, courtesy of the legacy alias table in cozy-lib and the 1:1 default mapping. Co-authored-by: Matthieu ROBIN <matthieu@hidora.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
af86c9d5b8 |
feat(cozy-lib): instance-type preset names with five series and legacy aliases
Restructure the resource preset table into a flat <series>.<size> naming convention inspired by KubeVirt and cloud-provider instance types. Five series cover the full CPU-to-memory ratio range: t1 (Tiny, 1:0.5) — burstable, low memory c1 (Compute, 1:1) — CPU-balanced, CPU-bound workloads s1 (Standard, 1:2) — proxies, caches, lightweight services u1 (Universal, 1:4) — databases and messaging m1 (Memory, 1:8) — search and analytics Each series provides eight sizes (nano, micro, small, medium, large, xlarge, 2xlarge, 4xlarge), yielding 40 presets in total. Ephemeral storage remains 2Gi for every preset. The seven legacy flat names (nano, micro, small, medium, large, xlarge, 2xlarge) are retained as backward-compatibility aliases returning their original CPU and memory values. Existing HelmReleases and app CRs continue to render identical resources without a migration step. The legacy block is deprecated and will be removed in a future release; the 1:1 conversion table is: nano -> t1.nano (250m / 128Mi) micro -> t1.micro (500m / 256Mi) small -> t1.small (1 / 512Mi) medium -> c1.small (1 / 1Gi) large -> c1.medium (2 / 2Gi) xlarge -> c1.large (4 / 4Gi) 2xlarge -> c1.xlarge (8 / 8Gi) Also fix the preset helper docstring to pass the preset string straight to unsanitizedPreset, replacing the prior list applied-to-tuple form that silently invoked the dot value as a function. Co-authored-by: Matthieu ROBIN <matthieu@hidora.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
0be25ce59e |
build(kilo): pin patched image to cozystack registry
Point values.yaml to ghcr.io/cozystack/cozystack/kilo with the freshly built image digest, replacing the upstream ghcr.io/squat/kilo reference. Signed-off-by: Arsolitt <arsolitt@gmail.com> |
||
|
|
e9c3817f4f |
fix(kilo): remove stale Alpine repo override in runtime stage
Address review feedback from gemini-code-assist on Dockerfile:36: Remove custom Fastly CDN repo pinned to v3.20 while base image is alpine:3.23 — use default repos from the base image instead. Signed-off-by: Arsolitt <arsolitt@gmail.com> |
||
|
|
86f5267dd1 |
feat(platform): implement backup strategy for clickhouse app (#2598)
<!-- Thank you for making a contribution! Here are some tips for you: - Use Conventional Commits for the PR title: `type(scope): description` - Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore - Scopes are not an exhaustive list — pick the most specific scope for the change and extend the list when a genuinely new area appears. Examples: - System components: dashboard, platform, operator, cilium, kube-ovn, linstor, fluxcd, cluster-api - Managed apps: postgres, mariadb, redis, kafka, clickhouse, virtual-machine, kubernetes - Development and maintenance: api, hack, tests, ci, docs, maintenance - Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or add a `BREAKING CHANGE:` footer - If it's a work in progress, consider creating this PR as a draft. - Don't hesistate to ask for opinion and review in the community chats, even if it's still a draft. - Add the label `backport` if it's a bugfix that needs to be backported to a previous version. --> ## What this PR does ### Screenshots <!-- REQUIRED for UI changes: attach screenshots or screen recordings demonstrating the visual impact of your changes. PRs with UI changes without screenshots will not be merged. --> ### Release note <!-- Write a release note: - Explain what has changed internally and for users. - Start with the same `type(scope):` prefix as in the PR title - Follow the guidelines at https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md. --> ```release-note ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Altinity-based ClickHouse backup/restore flow: cluster-scoped strategy, injected sidecar when enabled, optional referencing of existing S3 credential Secrets with per-key mapping, s3PathOverride, and API auth secret. * **Documentation** * Complete ClickHouse demo scripts, scenario guides, and updated backup configuration docs clarifying legacy vs Altinity behavior. * **Tests** * New unit and E2E coverage for Altinity flows, ownership, namespace invariants, and parameter round-trips. * **Chores** * RBAC extended for job lifecycle and added image build/publish step. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
250e1b3376 |
feat(platform): implement backup strategy for clickhouse application
Signed-off-by: Andrey Kolkov <androndo@gmail.com> |
||
|
|
269fe97e34 |
feat(kilo): add patched image build infrastructure
Add Dockerfile for building kilo from upstream main branch source with patch support, CNI plugins, and iptables-wrapper. Update Makefile with `image:` target for building the patched image and an updated `update:` target that pins the upstream commit SHA. Signed-off-by: Arsolitt <arsolitt@gmail.com> |
||
|
|
b810dbdfa1 |
feat(ouroboros): v0.7.2 + bats fix for kubectl jsonpath bracket-notation silent-empty on dotted keys (#2596)
## What this PR does
Bumps the vendored cozy-ouroboros chart to v0.7.2 and lands the
ouroboros e2e bats hardening that finally drives the addon test green on
the cozystack tenant runner.
The v0.7.2 release of lexfrei/ouroboros adds a `--log-level` flag,
plants Debug logs at every informer event handler
(`AddFunc`/`UpdateFunc`/`DeleteFunc` with kind+namespace/name) and at
reconcile entry/exit, wires `SetWatchErrorHandler` on
Ingress/Gateway/HTTPRoute informers, and surfaces cache-sync elapsed at
Info. The cozystack-side default is `info` (upstream chart default); a
tenant operator who needs debug verbosity can opt in via
`addons.ouroboros.valuesOverride.ouroboros.controller.logLevel: debug`.
## Root cause of the test flake
The ouroboros bats was failing on `kubectl --namespace kube-system get
configmap coredns-custom --output
"jsonpath={.data['ouroboros.override']}"`. The jsonpath bracket-notation
`[ 'key' ]` for a ConfigMap data key that contains a literal dot
(`ouroboros.override`) is a silent-empty kubectl trap: the parser treats
the bracket as an array index, the single-quoted string is not a valid
numeric index, and rather than erroring the result is `""`. The original
comment in the bats source claimed the bracket form "tolerates dotted
keys" — "tolerates" turned out to mean "does not crash, returns empty
without error", not "extracts the value".
Reproduced standalone on kind v1.35.0 against a ConfigMap whose only
data key is literally `ouroboros.override`:
```
$ kubectl -n default get configmap test --output 'jsonpath={.data}'
{"ouroboros.override":"rewrite name foo bar."}
$ kubectl -n default get configmap test --output "jsonpath={.data['ouroboros.override']}"
# ← empty string, exit 0
$ kubectl -n default get configmap test --output 'jsonpath={.data["ouroboros.override"]}'
error: error parsing jsonpath {.data["ouroboros.override"]}, invalid array index "ouroboros.override"
```
The fix is to dump the whole `.data` map (`jsonpath={range
.items[*]}…{.data}`) and let `grep -q "rewrite name <host>"` find the
entry. This is the same shape that `dump_tenant_state` had been using
successfully all along — the failure dumps consistently showed the
up-to-date ConfigMap while the bats poll was reporting empty.
This is a known kubectl jsonpath limitation, not a kamaji /
kube-apiserver issue. Two earlier diagnostic runs (replicas=1,
replicas=2 with apiserver logs piped into `dump_host_state`) were
chasing the wrong hypothesis; the kubectl test reproduces in any
cluster.
## Changes
- `packages/system/ouroboros/`: vendored chart bumped 0.7.0 → 0.7.2;
controller image digest + chart manifest digest updated in lockstep;
helm-unittest assertions updated for new image pin and chart-default
`--resync=30s` / `--log-level=info`.
- `packages/apps/kubernetes/templates/helmreleases/ouroboros.yaml`:
`cozystack.defaultOuroborosValues` pins `controller.clusterDomain:
cluster.local` (auto-detect path returns `cozy.local` on cozystack
tenants and the proxy `/readyz` NXDOMAINs forever).
- `packages/apps/kubernetes/tests/ouroboros_test.yaml`: new fixtures pin
the clusterDomain default and the tenant escape-hatch override paths
(clusterDomain override, logLevel opt-in-to-debug).
- `hack/e2e-apps/ouroboros.bats`: poll switched off jsonpath
bracket-notation (silent-empty trap) onto a whole-`.data`-map dump,
`dump_host_state` helper added with Kamaji apiserver +
konnectivity-server logs, `dump_tenant_state` now calls
`dump_host_state` first, and the rewrite-poll deadline raised 180s →
900s.
- `.github/workflows/pull-requests.yaml`: E2E job timeout 120m → 180m to
cover the long tail (full-matrix e2e on this branch ran 2h05m).
## Companion docs
cozystack/website#534 (draft) updates
`content/en/docs/next/networking/hairpin-proxy-protocol.md` to reflect
the new `clusterDomain` pin and drops stale 0.7.0 / digest hardcodes
from the air-gapped operators section.
## Release note
```release-note
NONE
```
|
||
|
|
6f83d9a794 |
feat(ouroboros): bump to v0.7.2 with debug logging on tenants
The v0.7.2 ouroboros release adds --log-level / OUROBOROS_CONTROLLER_LOG_LEVEL, plants Debug logs at every informer event handler (AddFunc/UpdateFunc/ DeleteFunc with kind+namespace/name via describeObj) and at reconcile entry/exit, wires SetWatchErrorHandler on Ingress / Gateway / HTTPRoute informers, and surfaces cache-sync elapsed at Info. The diagnostic surface targets the kamaji-tenant-via-konnectivity flake where bats sees a fresh Ingress create succeed against the tenant apiserver but the controller's coredns-custom rewrite lands roughly 7-10 minutes later — without per-event visibility the failure mode is indistinguishable between 'watch never fires', 'reconcile silently errors', and 'API list returns empty until reflector reconnect'. Bumps the chart-manifest digest, the controller-image digest, and the cozystack-side image-pin assertion in lockstep. The bats deadline for the coredns-custom rewrite check rises from 180s to 900s — even on the broken-watch path the reflector eventually reconnects within that budget, so the test stops failing on the symptom while we keep the diagnostic on to learn what the symptom actually is. cozystack tenants force controller.logLevel: debug via the defaultOuroborosValues helper; operators that want quieter logs can override through addons.ouroboros.valuesOverride. Two helm-unittest fixtures pin both the default and the override path. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
315802d8fc |
ci(pull-requests): raise E2E job timeout from 120m to 180m
The 2-hour ceiling on the E2E job was clipping otherwise-working runs on the oracle-vm-24cpu-96gb-x86-64 runners: image pulls, multi-stage Talos bootstrap, full helm-release fan-out plus the post-install bats matrix routinely consume 100-180 minutes of wall-clock, and runs that would have eventually gone green were getting cancelled by GitHub at the timeout. Recent successful E2E runs on the same runner pool sit between 60 and 184 minutes; lift the cap to 180m to cover the long tail without inviting truly-stuck jobs to linger forever. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
d6bcb27c53 |
test(ouroboros): dump tenant state on every assertion failure, not just HR wait
The CI run after pinning controller.clusterDomain showed the test was finally getting past the helm-controller wait — the proxy /readyz unblocked, the HR reaches Ready, and the controller pod becomes Ready — but the next assertion (the rewrite snippet appearing in kube-system/coredns-custom within 180s of creating the probe Ingress) is still failing on every retry. Without a dump on this assertion the failure surfaces only as `❌ Test failed (exit 1)` with the polled `snippet=` empty lines preceding it; the controller logs that would explain why the reconciler skipped the Ingress are nowhere visible. Refactor the existing inline diagnostic block into a `dump_tenant_state` helper that is invoked on every assertion's failure path. Wrap the rewrite-snippet check, the proxy ClusterIP non-empty check, and the dnscheck pod-phase check in `if ! ...; then dump_tenant_state; exit 1; fi` so each failure dumps the same set of host/tenant pods, events, controller and proxy logs, ingress-nginx Service+endpoints, and tenant CoreDNS Corefile that the original HR-wait failure path already covered. Also append a `kubectl get ingress -n default -o yaml` dump of the probe Ingress so a controller log line like "skipped Ingress without TLS host" is correlatable against the actual rendered manifest at the time of failure. The follow-up fix for whatever the next CI run surfaces will land on this same branch. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
d6c24dd078 |
fix(ouroboros): pin tenant clusterDomain to cluster.local
The cozystack tenant ouroboros wrapper deliberately left `controller.clusterDomain` empty so the upstream chart's per-pod `/etc/resolv.conf` auto-detect could pick up whatever the tenant CoreDNS actually serves. In a cozystack tenant that auto-detect resolves to the host platform's `cozy.local` rather than the tenant's `cluster.local`: the cozystack tenant kubelet injects the host's cluster-domain into pod search lists, but Kamaji's TenantControlPlane is configured with `networkProfile.clusterDomain: cluster.local` and the tenant CoreDNS Corefile serves only that domain. The mismatch makes the proxy compose its `BackendHost` as `ingress-nginx-controller.cozy-ingress-nginx.svc.cozy.local`, which NXDOMAINs against tenant CoreDNS — `/readyz` returns 503 forever, the proxy Deployment never reaches Ready, helm install times out at 10 minutes, and the e2e job hits the 2h cancel without `ouroboros.bats` ever progressing past the first kubectl wait. Pin `controller.clusterDomain: cluster.local` in `defaultOuroborosValues` so the chart bakes the resolved BackendHost against the domain tenant CoreDNS actually serves. This is the contract Kamaji TCP defines for every cozystack tenant; operators on a non-default tenant CoreDNS can still override via `addons.ouroboros.valuesOverride.ouroboros.controller.clusterDomain`. The underlying tenant kubelet injecting the wrong cluster-domain into pod resolv.conf is a separate bootstrap concern that should be addressed on its own track; pinning the chart input here keeps ouroboros operational on the default cozystack tenant topology in the meantime. Update the corresponding helm-unittest to assert the new contract. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
89aab4459b |
test(ouroboros): port-forward + super-admin.conf for tenant kubectl path
Every tenant-side kubectl call in hack/e2e-apps/ouroboros.bats was failing inside the e2e sandbox container with `dial tcp: lookup kubernetes-${cluster}.${ns}.svc on 169.254.169.254:53: no such host`. The bats test pulled the `super-admin.svc` variant of the tenant admin-kubeconfig, which points at the in-cluster Service DNS name `<release>.<ns>.svc:6443` — a name only host-cluster CoreDNS can resolve. The sandbox container's resolver is the Docker/QEMU host link-local 169.254.169.254, not the host-cluster CoreDNS, so every `KUBECONFIG=$kubeconfig kubectl ...` invocation in the test was returning NXDOMAIN.
The check that gated whether the test even reached its assertions (the `kubectl wait helmrelease kubernetes-${cluster}-ouroboros`) ran against the host kube-context, which masked the broken kubeconfig path until the helmrelease itself failed to reconcile and the diagnostic block fired — at which point every dump command returned only NXDOMAIN errors instead of actionable tenant-cluster state.
Switch to `super-admin.conf` (the operator-facing kubeconfig variant), rewrite `clusters[0].cluster.server` to `https://localhost:${pf_port}`, and run a `kubectl port-forward service/kubernetes-${cluster} ${pf_port}:6443` in the background — the same pattern hack/e2e-apps/run-kubernetes.sh already uses for tenant-cluster reachability. Replace the inline trap RM with a `cleanup_kubeconfig` helper that also kills the port-forward process so retries don't leak listeners.
This is a test infrastructure fix; the underlying ouroboros HelmRelease install timeout itself is a separate root cause that the next CI run, with usable diagnostics, will surface.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
|
||
|
|
c99be232ad |
test(ouroboros): dump tenant-side state on bats wait failure
The smoke test at hack/e2e-apps/ouroboros.bats waits for the kubernetes-${cluster}-ouroboros HelmRelease to reach Ready and exits with `wait: timed out` on failure. cozyreport collects host-cluster state only — a tenant-side proxy or controller failure surfaces as opaque "0 of 2 pods ready" with no actionable signal, so every retry is fully blind.
Extract the tenant admin-kubeconfig before the wait (gated on the parent kubernetes HR being Ready, which is the precondition for the secret existing) and, on wait failure, dump the host HelmRelease describe, cozy-ouroboros pods, pod descriptions, recent events, controller and proxy logs (200 lines each), the upstream cozy-ingress-nginx Service and endpoints used as the proxy backend, and the tenant kube-system Corefile plus the coredns-custom ConfigMap data.
Drops the ouroboros-HR wait timeout from 25m to 20m to leave room for the diagnostic block within the bats test budget.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
|
||
|
|
99e7070e4e |
fix(seaweedfs): wait for ingress-nginx-system before creating Ingress (#2406)
## What this PR does Stacks on top of #2258. Adds `dependsOn: ingress-nginx-system` to the inner `seaweedfs-system` HelmRelease so flux blocks its install until the ingress chart is Ready. ## Why In #2258's E2E run (and the `cozyreport-2258` bundle from this morning), `seaweedfs-system` failed to install with: ``` Helm install failed for release tenant-root/seaweedfs-system: 1 error occurred: * Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": failed to call webhook: Post "https://root-ingress-controller-admission.tenant-root.svc:443/networking/v1/ingresses?timeout=10s": dial tcp 10.96.33.42:443: connect: operation not permitted ``` ### Root cause class The outer tenant HelmReleases (`apps/tenant/templates/*.yaml`) render one inner HR per subsystem and let flux reconcile them. Both `seaweedfs` and `ingress` outer HRs get applied in parallel, and each of them spawns its own inner HR — which flux then installs in parallel too. When `seaweedfs-system` gets to the `creating 39 resource(s)` step, it tries to create the tenant Ingress. The apiserver calls the ingress-nginx `ValidatingWebhookConfiguration` (which uses `failurePolicy: Fail` by default). If the nginx controller pod/Service/endpoint state hasn't finished reconciling on the CNI yet, the connect to the ClusterIP fails with `EPERM`, the webhook errors, Helm aborts, and flux rolls back. E2E recovers via the `flux reconcile --force` retry loop in `hack/e2e-install-cozystack.bats`, but it's flaky and adds minutes. ### Fix Introduce an explicit ordering dependency at the inner HR layer: ```yaml {{- if $ingress }} dependsOn: - name: ingress-nginx-system {{- end }} ``` Flux waits for `ingress-nginx-system` to reach `Ready=true` before installing seaweedfs — which, under Flux's wait semantics, means the ingress-nginx Deployment is Available and its webhook endpoint is routable. The race disappears. Guarded by `{{- if $ingress }}` so this only kicks in for tenants that actually have ingress enabled. ## Test plan - [ ] Rerun E2E on #2258 — `seaweedfs-system` should install on the first try without a `Retry install` iteration. - [ ] Verify rendered template still matches expectations when `$ingress` is unset (no `dependsOn` block). ### Release note ```release-note [seaweedfs] Make tenant seaweedfs wait for ingress-nginx to be Ready before creating its Ingress resource, avoiding a webhook race that intermittently failed install on fresh clusters. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved deployment sequencing so the system now waits for the Ingress controller to be ready before creating or updating resources that include Ingress. This prevents premature deployments and related failures, reduces rollout errors, and provides more reliable, predictable deployments for applications relying on Ingress resources. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
45e21a330f |
feat(networking): add ouroboros for hairpin-NAT under PROXY-protocol (#2561)
## What this PR does Adds [`lexfrei/ouroboros@v0.7.0`](https://github.com/lexfrei/ouroboros/releases/tag/v0.7.0) — a Go reimplementation of [`compumike/hairpin-proxy`](https://github.com/compumike/hairpin-proxy) — and wires it into cozystack as a *conditional default*: a single `publishing.proxyProtocol: true` switch turns PROXY-protocol on at the host ingress-nginx **and** auto-deploys ouroboros to fix the resulting hairpin-NAT problem (intra-cluster traffic to the cluster's own public hostnames arriving at ingress-nginx without the PROXY header it now requires). Default stays `false` — clusters that do not run PROXY-protocol get zero new resources, zero RBAC delta, zero behaviour change. The chart is platform-agnostic at v0.7.0: the controller and proxy binaries auto-detect the cluster's DNS domain from `/etc/resolv.conf` inside the pod and compose the rewrite target FQDN and the backend host at runtime as `<svc>.<ns>.svc.<cluster-domain>`. Cozystack tenants on `cozy.local`, kubeadm-bootstrapped clusters on `cluster.local`, federations on `k8s.example.com`, custom-domain RKE2/k3s — all work without operator override. Verified end-to-end on a `cozy.local` cluster: controller logs `cluster-domain=cozy.local` at startup, chart emits `--proxy-service-name + --proxy-service-namespace` (no chart-baked `--proxy-fqdn`), Corefile picks up the rewrite block between BEGIN/END markers, in-pod `dig <ingress-host>` returns the ouroboros-proxy ClusterIP. Operators that prefer a chart-baked FQDN can still set `controller.clusterDomain` explicitly — the explicit-override path is preserved for non-Service backends and for split-horizon DNS topologies. The chart runs in `coredns` mode for the host (the host CoreDNS is Talos-managed and does not carry an `import` directive, so the alternative would silently no-op there) and in `coredns-import` mode for tenant deployments (tenants run cozystack-coredns, which carries the import directive and ships an empty `kube-system/coredns-custom` ConfigMap; ouroboros writes plugin-only `rewrite name` snippets into the `ouroboros.override` data key without ever touching the chart-rendered Corefile, so it does not race the chart that re-templates `data.Corefile` on every Flux reconcile). ### Layout * `packages/system/ouroboros/` — vendored chart from `oci://ghcr.io/lexfrei/charts/ouroboros@0.7.0`. Cozystack-side defaults pinned in `values.yaml`: `controller.mode=coredns` (host scenario), `proxy.target.namespace=cozy-ingress-nginx` (override the chart-default `ingress-nginx` namespace; chart-default `serviceName=ingress-nginx-controller` matches as-is), Gateway-API watching left at upstream's default of `false`. `proxy.target.host` is left empty so the proxy composes the backend host at runtime. Image is digest-pinned at `0.7.0@sha256:478665e05dd0ffc4c1f7764320ea24b52251781884ddfd668d93a03e39d9094c` and pulled directly from `ghcr.io/lexfrei/ouroboros` — this package is intentionally not mirrored under `ghcr.io/cozystack/*`. The chart manifest itself is also digest-pinned via `OUROBOROS_CHART_DIGEST=sha256:f28bfac9fd7070b1f3357983ff5aad28c16115e7de1cfc16ee568a3b4cfc9d7e` in the package Makefile, with a Chart.yaml-version vs. Makefile-version assert that aborts the update target on lockstep drift. Helm-unittest in `tests/` covers controller args, RBAC narrowing per mode, Gateway-API gating, runtime-composition flag emission in both `coredns` and `coredns-import` modes, image pin drift. * `packages/system/coredns/templates/coredns-custom.yaml` + `values.yaml` — empty `coredns-custom` ConfigMap as the chart-managed `import` prerequisite, plus the `import /etc/coredns/custom/*.override` plugin in the `.:53` server block + `extraVolumes`/`extraVolumeMounts` mount at `/etc/coredns/custom/`. Same package serves host and tenant CoreDNS, so this covers both layers without duplication. Helm-unittest pins the rendered Corefile via a snapshot so future `make update` does not silently drop the import directive. The empty rendered ConfigMap deliberately omits `data:` — Helm three-way merge has no template-side keys to compare against, so apiserver-side runtime writes (the `ouroboros.override` data key) survive every chart upgrade. The `notExists: data` assertion in `tests/coredns_custom_test.yaml` pins the invariant. * `packages/core/platform/sources/ouroboros.yaml` — new `cozystack.ouroboros` PackageSource for the host install (`dependsOn: cozystack.networking, cozystack.ingress-application`). * `packages/core/platform/sources/kubernetes-application.yaml` — `kubernetes-ouroboros` component registered against `system/ouroboros` so the tenant HelmRelease can reference it. * `packages/apps/kubernetes/templates/helmreleases/ouroboros.yaml` — tenant-side HelmRelease deployed via the tenant admin-kubeconfig, mirroring the cert-manager pattern. A `cozystack.defaultOuroborosValues` helper flips `mode` back to `coredns-import` for tenants and mirrors per-tenant `addons.gatewayAPI.enabled` into the controller (forcing `--gateway-api` on a tenant without Gateway-API CRDs CrashLoops the controller on `WaitForCacheSync`). `controller.clusterDomain` is intentionally NOT pre-set — chart 0.7.0 auto-detects per-pod from `/etc/resolv.conf` and composes the rewrite target at runtime, so the same wrapper renders correctly on `cluster.local`, `cozy.local`, or any custom tenant cluster-domain. Operators on a non-default cluster-domain can still override via `valuesOverride.ouroboros.controller.clusterDomain`. `dependsOn` grows a conditional `gateway-api-crds` entry on the same gate. If `addons.ouroboros.enabled` is true while `addons.ingressNginx.enabled` is false, the HelmRelease fails the render with a clear error rather than silently skipping — the hairpin fix has nothing to fix against without ingress-nginx, and a no-op addon that quietly does nothing is harder to debug than an explicit render-time error. The valuesOverride gateway-api guard accepts every truthy spelling Helm/YAML emit (bool `true`, string `"true"`/`"True"`/`"TRUE"`, numeric `1`, YAML `yes`/`Yes`/`YES`/`on`/`On`/`ON`/`y`/`Y`) via `toString`-then-`lower`-then-string-compare; direct bool `eq` would error on type mismatch when an operator passes the value as a string from `--set`, and case-insensitive folding catches `--set ...=On` / `--set ...=True` that pure-lowercase comparison would miss. Tenant disable is single-step: flipping `addons.ouroboros.enabled: false` deletes the rendered HelmRelease, helm-controller runs `helm uninstall` on the tenant, and the chart's pre-delete cleanup hook (`coredns-cleanup-hook.yaml`, vendored at 0.7.0) nulls the `ouroboros.override` key on the tenant's `kube-system/coredns-custom` ConfigMap automatically. No render-time guard is wired on the tenant side — gating on a `lookup` for the leftover HelmRelease would deadlock the routine disable (the parent render runs before helm-controller applies the missing-child diff, so the lookup would always find the leftover at the moment of the flag flip). If the chart's hook fails to land (controller pod stuck CrashLooping, ConfigMap RBAC drift, Job timeout), operators recover manually via the documented tenant cleanup recipe. * `packages/apps/kubernetes/values.yaml` — new `OuroborosAddon` typedef with `enabled` + `valuesOverride`. `make generate` re-emitted README, JSON schema, the Go struct + deepcopy, and the kubernetes-rd ApplicationDefinition openAPISchema in lockstep. * `packages/core/platform/values.yaml` — new `publishing.proxyProtocol` flag with extensive comment covering the upstream-LB precondition (the L4 LB in front of ingress-nginx must already be injecting PROXY-v1 headers before the flag flips on, otherwise external traffic breaks), the host-vs-tenant fan-out (the flag does not cascade into tenants), the Talos re-render flap window, and the asymmetric disable path. The host disable path: flipping back to `false` reverts ingress-nginx PROXY-protocol config (flip the LB off first), but the host ouroboros itself stays installed because its Package CR carries `helm.sh/resource-policy: keep` — an explicit `kubectl delete package.cozystack.io cozystack.ouroboros` (or `bundles.disabledPackages` entry) actually triggers helm uninstall, at which point the chart's pre-delete cleanup hook fires and patches the host Corefile automatically. The values comment ships a manual `sed`-based cleanup recipe as a fallback for the rare case where the chart's hook fails to land (controller stuck in CrashLoop, ConfigMap RBAC drift, hook timeout); the `publishing.proxyProtocolAcknowledgeUnclean` gate keys off a `lookup` against the leftover Package CR to catch operators who flip the flag back without confirming the cleanup landed. * `packages/core/platform/templates/bundles/system.yaml` — flips between the default-form and explicit-form `cozystack.ingress-application` Package emission so the host ingress-nginx gets `use-proxy-protocol` + `real-ip-header=proxy_protocol` injected only when the flag is true (`use-forwarded-headers` and `compute-full-forwarded-for` are deliberately *not* on the list — they would let any upstream proxy spoof `X-Forwarded-For`); the same conditional emits `cozystack.ouroboros`. Host Gateway-API watching is left at the upstream chart's default of `false` because cozystack does not install Gateway-API CRDs cluster-wide on the host. * `hack/e2e-apps/ouroboros.bats` — auto-discovered smoke test for the tenant addon (HelmRelease ready, `coredns-custom` ConfigMap present in tenant, controller pod running, and after creating a TLS Ingress the rewrite snippet shows up in the import ConfigMap; an in-tenant `dig` from a netshoot pod also confirms CoreDNS actually serves the rewrite — pod-readiness alone passes vacuously since the upstream chart ships no readiness probes). ### Why not KEP-1860 `ipMode=Proxy` Cilium's `kubeProxyReplacement: true` (cozystack default) drops the LB frontend entirely when `ipMode != VIP`, breaking Service ingress for L2/BGP-announced IPs. KEP-1860's Proxy mode is reserved for clusters fronted by an external CCM-managed proxy LB. ouroboros is the correct fix for L2/BGP-announce topologies that cozystack ships by default. ### Coverage Covered by helm-unittest (host chart, coredns wrapper, tenant addon — including the `kubernetesProvider` mock that exercises the lookup-driven `proxyProtocolAcknowledgeUnclean` gate, the lookup-returns-nil CI/dry-run path, the gateway-api truthy-spelling acceptance across `true`/`"true"`/`"True"`/`"TRUE"`/`1`/`yes`/`on`, the assertion that `--proxy-service-name` + `--proxy-service-namespace` are emitted instead of a chart-baked `--proxy-fqdn` in both `coredns` and `coredns-import` modes, the assertion that `--target-service-name` + `--target-service-namespace` are emitted for the proxy backend, and the `_namespace.etcd`-empty render gate) and a tenant e2e bats test that creates a real Ingress, asserts the rewrite snippet lands in the import ConfigMap, and confirms in-tenant DNS serves it (with an in-pod retry loop tolerating CoreDNS reload latency). The host-level `publishing.proxyProtocol: true` path is not e2e-tested in this PR — it requires a PROXY-protocol-aware upstream LB, which the cozystack e2e harness does not stand up. That path is exercised manually and by docs review. End-to-end runtime auto-detect was verified manually on a `cozy.local` cluster (dev17): chart deployed at v0.7.0, controller logged `cluster-domain=cozy.local`, the rewrite block landed in `kube-system/coredns` Corefile pointing at `test-ouroboros-proxy.test-ouroboros.svc.cozy.local.`, an in-pod `dig <ingress-host>` resolved to the ouroboros-proxy ClusterIP on the first attempt, and the chart's pre-delete hook restored the Corefile cleanly on `helm uninstall`. ### Supply-chain note Image and chart are pulled from a contributor's personal namespace (`ghcr.io/lexfrei/...`). Existing precedent (`packages/system/etcd-operator/Makefile` pulls from `ghcr.io/aenix-io/...`) is similar but `aenix-io` is the cozystack-adjacent org while `lexfrei` is one human. Worth a maintainer call. Pairs with cozystack/website#527 (operator docs). ### Release note ```release-note feat(networking): add `publishing.proxyProtocol: true` to enable PROXY-protocol on host ingress-nginx and auto-deploy ouroboros (a Go reimplementation of compumike/hairpin-proxy) to solve the resulting hairpin-NAT problem; tenants can opt in per-cluster via `addons.ouroboros.enabled` (requires `addons.ingressNginx.enabled`). Default behaviour unchanged. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Ouroboros addon to address hairpin‑NAT for ingress‑nginx with configurable enablement and tenant overrides. * Added a packaged Ouroboros chart providing proxy, controller, CoreDNS integration, external‑DNS and etc‑hosts modes. * Introduced PROXY‑protocol gating with an explicit acknowledgement flag. * **Documentation** * Expanded addon reference and platform docs with detailed Ouroboros/PROXY‑protocol configuration and defaults. * **Tests** * Added extensive unit and e2e tests covering rendering, RBAC, uninstall cleanup, and DNS behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8da1e7a40a |
feat(platform): implement backup strategy for postgres (#2552)
<!-- Thank you for making a contribution! Here are some tips for you: - Use Conventional Commits for the PR title: `type(scope): description` - Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore - Scopes are not an exhaustive list — pick the most specific scope for the change and extend the list when a genuinely new area appears. Examples: - System components: dashboard, platform, operator, cilium, kube-ovn, linstor, fluxcd, cluster-api - Managed apps: postgres, mariadb, redis, kafka, clickhouse, virtual-machine, kubernetes - Development and maintenance: api, hack, tests, ci, docs, maintenance - Breaking changes: append `!` after type/scope (`feat(api)!: ...`) or add a `BREAKING CHANGE:` footer - If it's a work in progress, consider creating this PR as a draft. - Don't hesistate to ask for opinion and review in the community chats, even if it's still a draft. - Add the label `backport` if it's a bugfix that needs to be backported to a previous version. --> ## What this PR does ### Screenshots <!-- REQUIRED for UI changes: attach screenshots or screen recordings demonstrating the visual impact of your changes. PRs with UI changes without screenshots will not be merged. --> ### Release note <!-- Write a release note: - Explain what has changed internally and for users. - Start with the same `type(scope):` prefix as in the PR title - Follow the guidelines at https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md. --> ```release-note Implemented CNPG-strategy controller for postgres backups with supporting in-place and to-copy restores. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * CNPG-based backup strategy for PostgreSQL with S3-backed object store and controller support * Option to reference existing Kubernetes Secret for S3 credentials (configurable key names) * Controller supports scheduled/ad-hoc backups and both in-place and to-copy restores; safer credential handling (no inline keys) * **Examples** * Complete manifests: bucket, credentials, CNPG strategy, BackupClass, Plan, BackupJob, RestoreJob, Postgres source/target * **Security/RBAC** * Controller RBAC expanded for CNPG resources; tests enforce no cluster-wide Secret read * **Documentation** * README, chart values/schema and UI schema updated to document secret-reference workflow and restore guidance * **Tests** * New end-to-end and unit tests covering CNPG flows, restore semantics, cleanup behavior and RBAC constraints <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
653519a472 |
fix(coredns): sanitize Chart.Version build metadata in coredns-custom label
The cozystack build pipeline tags chart versions as `0.0.0+<git-sha>`. The new coredns-custom ConfigMap interpolated `.Chart.Version` directly into the `helm.sh/chart` label, producing `cozy-coredns-0.0.0+<sha>` which the apiserver rejects: label values follow RFC 1123 and `+` is not a legal character. The chart never installed, kube-system/coredns inside tenant clusters never came up, every dependent HelmRelease stalled, and the e2e suite hit the 2h job timeout without reaching the bulk of the bats tests. Apply the standard `replace "+" "_" | trunc 63 | trimSuffix "-"` sanitization, matching the pattern the vendored upstream coredns chart already uses in its own `helm.sh/chart` helper a few directories down. Add a helm-unittest case that overrides the chart version to a build- metadata form (`0.0.0+abc1234567`) and asserts the rendered label both matches the sanitized literal and conforms to the RFC 1123 label-value regex. Without the version override the bug is invisible to the test suite — Chart.yaml ships the bare `0.0.0` placeholder and helm-unittest defaults to that, so any future template that interpolates `.Chart.Version` into a label value cannot regress past CI silently. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la> |
||
|
|
026581e0e9 |
fix(seaweedfs): only depend on ingress-nginx-system when tenant owns its ingress
Address review blocker on #2406: gate the dependsOn on `eq $ingress .Release.Namespace` so sub-tenants inheriting ingress from a parent namespace don't deadlock waiting for an HR that doesn't exist locally. Also add explicit `namespace:` to match repo convention. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
43c76fd8f3 |
fix(seaweedfs): wait for ingress-nginx-system before creating Ingress
Without this, the outer tenant HelmReleases apply both seaweedfs and
ingress in parallel, which in turn creates their inner HelmReleases
(seaweedfs-system and ingress-nginx-system) in parallel too. When
seaweedfs-system tries to create its Ingress before the nginx admission
webhook's Service/endpoint state has finished reconciling on the CNI,
the apiserver's webhook call fails with:
failed calling webhook "validate.nginx.ingress.kubernetes.io":
dial tcp ...:443: connect: operation not permitted
and flux rolls back the install. E2E recovers via the "Retry install"
loop but it's flaky and adds minutes to every run.
Adding dependsOn: ingress-nginx-system on the inner seaweedfs HR makes
flux block the install until the ingress chart is Ready, which means
the controller Deployment is Available and its webhook endpoint is
routable before the first Ingress is created.
Guarded by {{- if \$ingress }} so this only kicks in for tenants that
have ingress enabled (i.e. tenant-root in the default topology).
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
|
||
|
|
a7a09ff5b2 |
docs(release): add changelog for v1.3.3 (#2594)
This PR adds the changelog for release `v1.3.3`.
✅ Changelog has been automatically generated in
`docs/changelogs/v1.3.3.md`.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Added v1.3.3 release notes documenting PostgreSQL backup recovery
improvements, Kafka and MongoDB managed application fixes, resource
preset updates, and a new vGPU setup guide.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
bc19eae311 |
docs: add changelog for v1.3.3
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
c22d6661ad |
fix(kafka): create LoadBalancer service when external flag is enabled (#2578)
## What this PR does When `external: true` is set in the Kafka chart, Strimzi creates a LoadBalancer service named `<release>-kafka-external-bootstrap` for external client access. However, two issues prevented this from working correctly: 1. **Unconditional listener definition**: the `external` listener was always present in the Kafka CR (as `type: internal` when disabled), instead of being omitted entirely when `external: false`. 2. **Missing dashboard RBAC**: the dashboard role only granted access to `<release>-kafka-bootstrap` (internal ClusterIP). The Strimzi-managed external bootstrap service was not included, making it invisible to tenant users even when it was created. **Changes:** - Make the external listener conditional — added only when `external: true` - Add `<release>-kafka-external-bootstrap` to dashboard RBAC rules when `external: true` - Add helm-unittest tests covering listener and RBAC behavior for both `external: true` and `external: false` ### Screenshots N/A — no UI changes. ### Release note ```release-note fix(kafka): external listener is now correctly created as a LoadBalancer and exposed in the tenant dashboard when `external: true` is set ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * External Kafka listener and external bootstrap service in dashboard resource mapping are now conditionally enabled based on configuration settings. * **Tests** * Added comprehensive test suites validating Kafka configuration rendering and dashboard resource mapping across internal and external deployment variations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ed5ae16e36 |
feat(platform): implement backup strategy for postgres application
Signed-off-by: Andrey Kolkov <androndo@gmail.com> |
||
|
|
a9c1298b42 |
[gpu-operator] Update to v26.3.1 and add experimental vGPU variant (#2323)
## What this PR does Updates the NVIDIA GPU Operator from v25.3.0 to v26.3.1 and adds an **experimental** `vgpu` variant for SR-IOV vGPU on Ada Lovelace and newer GPUs. Changes: - Update vendored upstream chart to v26.3.1 (CDI enabled by default, component version bumps). - Pin chart version in Makefile for reproducibility. - Add `values-vgpu.yaml` for the vGPU variant with `defaultWorkload: vm-vgpu` so the chart activates the vGPU Manager DaemonSet without per-node labelling. - Add `vgpu` variant to PackageSource alongside the existing `default` (passthrough). - Rename `values-talos.yaml` → `values-passthrough.yaml` and pin `defaultWorkload: vm-passthrough` for symmetry with the vgpu variant. The overrides apply to any host OS using vfio-pci, not Talos specifically. - Refresh `hack/dcgm-default-counters.csv` to match the new dcgm-exporter image tag (`4.5.1-4.8.0`) — adds `DCGM_FI_DEV_FB_RESERVED` and other fields introduced upstream. `hack/check-gpu-recording-rules.bats` passes against the new fixture. - Add `hack/check-gpu-operator-variants.bats` that renders both variants via `helm template` and asserts the pinned ClusterPolicy values, so the next chart bump cannot silently un-pin them. - Add internal documentation for the vGPU bring-up. The `vgpu` variant assumes the user supplies a proprietary vGPU Manager image via Package CR component values — the .run cannot be redistributed. ### `vgpu` variant is experimental NVIDIA's `vgpu-device-manager` walks `/sys/class/mdev_bus/`, which does not exist on Ada Lovelace and Blackwell — the DaemonSet errors with "no parent devices found" and is disabled by default. Until an SR-IOV-aware controller is shipped, profile assignment is an out-of-band step (`echo <id> > /sys/.../current_vgpu_type` per VF) that must be re-applied after every node reboot. Without it, `permittedHostDevices.pciHostDevices` reports zero allocatable resources. The variant ships so the chart bump and the underlying skeleton (DaemonSet + image plumbing + docs) land together; production deployments need an automated profile-assignment mechanism in addition to this PR. ### KubeVirt requirement KubeVirt advertises VFs via `permittedHostDevices.pciHostDevices` rather than `mediatedDevices`. This requires kubevirt/kubevirt#16890 ("vGPU: SRIOV support", merged 2026-04-10) which is `main`-only — released tags `v1.6.x` / `v1.7.x` / `v1.8.x` do not include it. The patch is targeted at the next minor KubeVirt release (v1.9.0); track the PR for the actual release tag. Backports to released branches are not planned. ### Behavior changes inherited from upstream chart v25 → v26 The upstream chart flipped two defaults that are pinned back to `false` here, so `default` (passthrough) deployments do not silently change footprint on upgrade: - `ccManager.enabled` was flipped to `true` upstream — would auto-enable Confidential Computing on Hopper hardware (H100/H200/B100) after upgrade. - `vgpuDeviceManager.enabled` was flipped to `true` upstream — DaemonSet would render even in passthrough mode. Both stay opt-in via Package CR overrides. The new bats test guards the pin. Other inherited changes that are user-visible and worth pinning down before upgrade: - `driver.licensingConfig.configMapName` is deprecated upstream in favour of `driver.licensingConfig.secretName`. The deprecation marker lives in the CRD's `description` field (visible via `kubectl explain`) — there is no helm-render-time warning, the chart template silently prefers `secretName` and falls back to `configMapName`. Operators with existing licensing overrides should migrate the key on the next chart upgrade. - `driver.version` upstream default jumped from `570.x` to `580.x`. Invisible on the `default` variant (which sets `driver.enabled: false`), user-visible for anyone running the upstream Ubuntu driver path. - `vfioManager.image` switched from `nvcr.io/nvidia/cuda:12.8.1-base-ubi9` to `nvcr.io/nvidia/cloud-native/k8s-driver-manager:v0.10.0`. Affects every `default` (passthrough) deployment on upgrade — different image, different layer, different image-pull surface. Worth pre-mirroring for air-gapped clusters. - `dcgmExporter.image` switched to the `-distroless` flavour. Smaller surface, fewer base-image CVEs, but no shell — operators who used to `kubectl exec` into the exporter for ad-hoc debugging will need to switch to `kubectl debug` or container ephemeral images. - `CDI` (Container Device Interface) is enabled by default in v26.3.1; this is upstream's recommended setting and is left as-is. - `node-feature-discovery` subchart source switched from the GitHub Pages Helm repo to `oci://registry.k8s.io/nfd/charts`. Air-gapped installations need to mirror the new OCI URL. ### Talos Talos is **not recommended** for the vGPU variant. NVIDIA does not publicly distribute the vGPU guest driver — it requires NVIDIA Enterprise Portal access — and Sidero closed siderolabs/extensions#461 noting that they cannot support vGPU "unless NVIDIA changes their licensing terms or provides us a way to obtain, test, and distribute the software". Building a Talos system extension that bakes in the vGPU driver is therefore not feasible without a private fork that violates the EULA. Passthrough (`default` variant) on Talos is unaffected. ### Release note ```release-note [gpu-operator] Update NVIDIA GPU Operator to v26.3.1 and add experimental `vgpu` variant for SR-IOV vGPU on Ada Lovelace / Blackwell (L4, L40, L40S, B100; Ubuntu host; requires KubeVirt v1.9.0+ for `pciHostDevices` advertising). The variant ships skeleton support — profile assignment (`current_vgpu_type` per VF) is currently out of band and must be automated by the operator before production use. On the existing `default` variant: `ccManager` and `vgpuDeviceManager` upstream defaults are pinned back to `false` to preserve prior behavior on chart upgrade; `defaultWorkload` is now pinned to `vm-passthrough` (was unset, falling back to `container`); `driver.licensingConfig.configMapName` is deprecated by upstream in favour of `secretName`; `driver.version` upstream default moves 570 → 580; `vfioManager.image` switches from CUDA UBI9 to k8s-driver-manager (relevant for air-gapped mirrors); `dcgmExporter` image switched to the `-distroless` flavour. NFD subchart source switched to `oci://registry.k8s.io/nfd/charts`. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced vGPU support variant with end-to-end configuration guide, validation procedures, and troubleshooting documentation * **Updates** * Upgraded GPU Operator to v26.3.1 and Node Feature Discovery to v0.18.3 * Improved component health checks and added PodDisruptionBudget availability controls <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
6cc9013085 |
docs: add changelog for v1.3.2 (#2550)
This PR adds the changelog for release `v1.3.2`.
✅ Changelog has been automatically generated in
`docs/changelogs/v1.3.2.md`.
untagged-34c5e929a0cb9154bef0
|
||
|
|
61de813613 |
feat(e2e): parallel post-install prep (#2557)
## What this PR does ### Parallel post-install prep LINSTOR / StorageClass / MetalLB setup, previously sequential `@test` cases after the 15 m platform HR wait, now run as a background prep that completes during the platform reconcile. None of them gates platform HR reconcile, so they can move out of the critical path. New helper `hack/e2e-post-install-prep.sh` polls for its prerequisites and is awaited at the end of the `Install Cozystack` test so failures still surface deterministically. ### T2-race fix Wait on the LINSTOR HR being `Ready` before polling for `deploy/linstor-controller`. The old 5-min hard timeout fired during cold installs where the LINSTOR HR's dependency chain (cert-manager → piraeus-operator-crds → piraeus-operator → linstor) takes longer than 5 min to resolve. ### E2E uses helmReleaseInterval=30s E2E install passes `--set cozystackOperator.helmReleaseInterval=30s` to eliminate the 8–10 min Flux dead zone where dependency-blocked HRs are requeued only every 5 min. Operator-side flag and chart value landed in #2509; production defaults are unchanged. Surfaced from #2500. ### Release note ``` NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** - Improved end-to-end test initialization to run concurrent post-install preparation, wait for cluster release reconciliation, verify component readiness, and validate automated storage configuration. * **Chores** - Added background post-install setup and logging to increase test reliability and speed up cluster initialization and teardown diagnostics. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5096e3bf9c |
fix(ci): stop backport workflow from cascading on its own PRs (#2584)
## What this PR does Fix the cascade where merging a backport PR (e.g. #2579) spawns another backport (e.g. #2581 `[Backport release-1.2] [Backport release-1.3] …`). Two compounding issues: 1. `pr-labeler.yaml` auto-added the `backport` label to any PR whose title started with `[Backport release-X.Y]` — exactly the prefix `korthout/backport-action` puts on every backport PR. Introduced in `c8ed1c65` (CNCF/k8s label conventions). Fixed by dropping that `toAdd.add('backport')` line. 2. `dosubot[bot]` independently re-applies `backport-previous` to backport PRs based on similarity to the parent PR; it cannot be controlled from this repo. Fixed by gating both jobs in `backport.yaml` on `pull_request.base.ref == 'main'`, so backport PRs (which target `release-X.Y`) cannot trigger the workflow regardless of labels. Verified pre-fix behaviour by inspecting the label-event timeline of #2580 (dosubot adds `backport-previous` 47s after PR open) and the diff of `c8ed1c65` adding `pr-labeler.yaml`. ### Release note ```release-note fix(ci): backport automation no longer creates duplicate backport PRs when a backport PR is merged. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Enhanced backport automation workflow with additional safety checks to ensure operations only process pull requests targeting the main branch. * Simplified pull request labeling workflow to streamline label assignment logic. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
3e9e393b7f |
fix(virtual-machine): vminstance disk race + bump VM IP/ready timeouts (#2555)
## What this PR does Three fixes for `hack/e2e-apps/vminstance.bats`, surfaced once the 3x retry was dropped from `Run E2E tests`: 1. **Disk delete-recreate race.** The teardown used `kubectl delete vmdisk … || true` and immediately created a new disk; sometimes the new disk reconciled before the old finalizer completed, leaving a duplicate PVC and the new VM stuck. Drop the `|| true`, block until the old disk is gone, then create. 2. **VM IP wait timeout 20s → 120s.** Under nested-virt + concurrent runner load, a fresh VM sometimes takes 60–90 s to acquire its IP via DHCP. The 20 s bound was tripping deterministically. 3. **VM ready timeout 20s → 60s.** Same root cause; the readiness probe needs the IP to be reachable, so the lower bound has to grow alongside the IP wait. Existence backstop on the `vm-instance-$name` HR is added here too (it touches the same hunk as the timeout fix; cleaner to land them together). Surfaced from #2500. ### 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 VM instance and disk flows. * Replaced short sleeps with explicit waits for upstream and downstream deployment artifacts. * Extended polling windows and timeouts for IP assignment and readiness checks. * Strengthened cleanup to reliably remove prior VM and disk resources before and after tests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9d7941b9ec |
docs: add changelog for v1.3.2
Signed-off-by: cozystack-ci[bot] <274107086+cozystack-ci[bot]@users.noreply.github.com> |
||
|
|
32e75ab183 |
Merge branch 'main' into daniil/split-vminstance
Signed-off-by: myasnikovdaniil <60174387+myasnikovdaniil@users.noreply.github.com> |