## What this PR does Bumps the ouroboros chart and controller image to 0.8.1, which fixes a latent upgrade break in the controller Deployment's rollout strategy, and pins the fixed contract from the cozystack side. Up to chart 0.8.0 the controller Deployment rendered a rollout strategy **only** in `external-dns` mode, as `type: Recreate`, and rendered no strategy block at all in the other modes. The apiserver defaults a `rollingUpdate` block onto any Deployment created without one, so switching a live release into `external-dns` laid `Recreate` on top of that defaulted block, and the apiserver rejected the object: ``` spec.strategy.rollingUpdate: Forbidden: may not be specified when strategy `type` is 'Recreate' ``` 0.8.1 renders the same `RollingUpdate` block, with no surge, in every mode. The strategy no longer changes when `controller.mode` does, so the rejected combination cannot arise on any transition. Rendering `Recreate` unconditionally would not have worked: existing `coredns`-mode releases already carry the defaulted `rollingUpdate` block and would hit the identical rejection on their first upgrade. Always-`RollingUpdate` is upgrade-safe from both existing states, and rollback works for the same reason. **Reachability, stated plainly:** this is a latent break, not an active one. The host pins `coredns` and tenants pin `coredns-import`, neither of which rendered a strategy in 0.8.0, and no shipped configuration selects `external-dns`. But `controller.mode` is a documented, user-settable value that the tenant wrapper exposes through `valuesOverride`, so the transition is reachable by configuration rather than only in theory. **Why it went unnoticed:** the break only surfaces under server-side apply, which helm-controller uses by default. `DeploymentSpec.Strategy` carries `patchStrategy:"retainKeys"`, so a client-side strategic merge clears `rollingUpdate` on the way through and a plain `helm upgrade` never reproduces it. Only the upgrade breaks, never the install, so nothing catches it at render time either. **Why no surge, in every mode:** the controller has no leader-election in any mode and no serving path — no ports, no probes — so surging a second pod buys no availability anywhere. In `external-dns` mode it also removes a real hazard: that reconciler `Update`s DNSEndpoints with no conflict retry, so two overlapping reconcilers race on Get→Update. The `coredns` paths wrap Get→Update in `RetryOnConflict` and converge instead, which is why only `external-dns` rejects `replicaCount > 1`; that asymmetry is deliberate and is now called out in the template so it does not get tidied away later. The upstream comment is explicit that `maxSurge: 0` is *not* Recreate-equivalent exclusivity — the surge budget counts desired replicas, not live pods — and rests the argument on what is actually guaranteed: the old pod's SIGTERM precedes the new pod's creation, and SIGTERM cancels the reconciler context. The proxy Deployment is untouched and keeps its default rolling surge, as the data-path component. The fix was made upstream in `lexfrei/ouroboros` and released as v0.8.1 rather than patched into the vendored tree here, since `make update` regenerates `charts/` wholesale. The vendored chart in this PR is a verbatim `make update` pull of the published 0.8.1 artifact, byte-identical to the registry. Chart manifest digest and controller image digest are bumped in lockstep with the version, as the package Makefile requires. 0.8.1 also carries an upstream Renovate bump of the cleanup-hook kubectl image to 1.36.1 (verified to resolve, multi-arch). The `update` target additionally drops the empty digest-named directory that `helm pull` leaves beside the untarred chart when pulling by digest. Git ignores empty directories, which is exactly why it lingered unnoticed. ### Testing `make -C packages/system/ouroboros test` → 17/17 pass. The three new cases pin the rendered strategy on `coredns`, `coredns-import` and `external-dns`. `external-dns` is included deliberately: it is the only mode that ever rendered `Recreate`, so a future bump that re-gated the block would slip past a coredns-only suite. Verified by re-gating the bug surgically against the new suite — it fails on exactly that case, and passes without it. Upstream additionally tests this contract across every mode in its own suite. ### Screenshots Not applicable — no UI change. ### Downstream repositories Walked the trigger map in `docs/agents/contributing.md` against the diff file by file. The diff touches only `packages/system/ouroboros/`: the package Makefile's version and digest pins, the vendored chart (regenerated), the image pin in `values.yaml`, and the package's own tests. It adds, renames and removes no package under `packages/apps/` or `packages/extra/`; touches no `packages/core/platform/values.yaml` key, no platform variant, bundle or component; changes no `ApplicationDefinition`, no `values.schema.json`, no version enum, no `release.prefix`; touches nothing under `hack/`, no namespace, and no node prerequisite. No trigger matches. - [x] No downstream repository is affected by this change - [ ] [cozystack/website](https://github.com/cozystack/website) - follow-up: - [ ] [cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack) - follow-up: - [ ] [cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack) - follow-up: - [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up: - [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up: - [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) - follow-up: - [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) - follow-up: - [ ] [cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server) - follow-up: - [ ] [cozystack/external-apps-example](https://github.com/cozystack/external-apps-example) - follow-up: - [ ] [cozystack/examples](https://github.com/cozystack/examples) - follow-up: ### Release note ```release-note fix(ouroboros): render the controller rollout strategy in every controller.mode. Up to chart 0.8.0 the strategy was rendered only in external-dns mode, as type: Recreate, so switching a live release into that mode applied Recreate on top of the rollingUpdate block the apiserver defaults onto a Deployment created without one, and the upgrade was rejected with "spec.strategy.rollingUpdate: Forbidden: may not be specified when strategy `type` is 'Recreate'". The rejection only occurs under server-side apply, which helm-controller uses by default. The strategy is now identical across all modes, so a mode switch changes no strategy field. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Updated Ouroboros to version 0.8.1 with refreshed, pinned images. * Improved controller rollouts using a consistent rolling-update strategy across supported modes. * Updated cleanup hook tooling to version 1.36.1. * **Bug Fixes** * Prevented leftover chart directories from accumulating during chart updates. * Improved deployment behavior by limiting rollout disruption while maintaining controller availability. * **Tests** * Added coverage validating rollout behavior across all supported controller modes. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Cozystack
Cozystack is a free platform and framework for building clouds.
Cozystack is a CNCF Sandbox Level Project that was originally built and sponsored by Ænix.
With Cozystack, you can transform a bunch of servers into an intelligent system with a simple REST API for spawning Kubernetes clusters, Database-as-a-Service, virtual machines, load balancers, HTTP caching services, and other services with ease.
Use Cozystack to build your own cloud or provide a cost-effective development environment.
Use-Cases
-
Using Cozystack to build a public cloud
You can use Cozystack as a backend for a public cloud -
Using Cozystack to build a private cloud
You can use Cozystack as a platform to build a private cloud powered by Infrastructure-as-Code approach -
Using Cozystack as a Kubernetes distribution
You can use Cozystack as a Kubernetes distribution for Bare Metal
Documentation
The documentation is located on the cozystack.io website.
Read the Getting Started section for a quick start.
If you encounter any difficulties, start with the troubleshooting guide and work your way through the process that we've outlined.
Versioning
Versioning adheres to the Semantic Versioning principles.
A full list of the available releases is available in the GitHub repository's Release section.
Contributions
Contributions are highly appreciated and very welcomed!
In case of bugs, please check if the issue has already been opened by checking the GitHub Issues section. If it isn't, you can open a new one. A detailed report will help us replicate it, assess it, and work on a fix.
You can express your intention to on the fix on your own. Commits are used to generate the changelog, and their author will be referenced in it.
If you have a concrete feature request, open an issue. For a cross-cutting or architectural change, open a design proposal in the community repo. For questions or early ideas, use GitHub Discussions. See CONTRIBUTING.md for the full routing.
Community
You are welcome to join our Telegram group and come to our weekly community meetings. Add them to your Google Calendar or iCal for convenience.
License
Cozystack is licensed under Apache 2.0.
The code is provided as-is with no warranties.
Commercial Support
A list of companies providing commercial support for this project can be found on official site.
