Commit 99dd57c
authored
feat: Ubuntu 26.04 support and cozy-system namespace adoption (#37)
* fix(examples/ubuntu): allow opting out of linux-modules-extra for 26.04+
Ubuntu 26.04 LTS bundles openvswitch and vport-geneve into the main
linux-image-generic and has no linux-modules-extra-* split package
for kernel 7.x. Without an opt-out, the apt task fails with
'No package matching linux-modules-extra-7.x.x-generic available'.
Add a length-zero guard on cozystack_ubuntu_extra_packages and
document the override path in the vars block, so 26.04 inventories
can simply set the list to [] without forking the playbook.
Existing 22.04 / 24.04 inventories keep working with the default
list — behaviour unchanged.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* fix(examples/ubuntu): work around sudo-rs default on Ubuntu 26.04
Ubuntu 26.04 LTS ships sudo-rs (Rust rewrite) as the default
/usr/bin/sudo alternative. sudo-rs does not honour ansible's
privilege-escalation pseudo-tty: every task with become: true on a
password-protected user hangs and fails with
'Timeout (12s) waiting for privilege escalation prompt'.
The classical sudo binary is co-installed at /usr/bin/sudo.ws on
26.04 hosts. Add prepare-sudo.yml that switches the sudo alternative
to it via a raw command (which does not depend on ansible become and
works even when become is broken). Wire it into site.yml so the
full pipeline keeps working out of the box on 26.04, with no
behavioural change for earlier Ubuntu / Debian targets — the play
is a no-op when sudo-rs is not the active alternative.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* fix(role): adopt cozy-system namespace into helm release on reinstall
The cozy-installer chart renders the target namespace (cozy-system by
default) as a templated resource, so a fresh install fails when that
namespace already exists out of band — manual kubectl create ns,
remnant from a previous failed install, or a different chart that
shares the namespace name. The error surfaces as
Namespace "cozy-system" exists and cannot be imported into the
current release: invalid ownership metadata
Add a pre-task that looks up the namespace and stamps the helm
ownership label and annotations expected by the chart. The task is a
no-op when the namespace is absent or already carries matching
metadata, so first-install and idempotent re-runs are unchanged.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* docs: README and CHANGELOG entries for Ubuntu 26.04 + namespace adoption
Document the two Ubuntu 26.04 opt-ins (sudo-rs alternative switch +
empty cozystack_ubuntu_extra_packages list) under Known limitations
in the README, and add the matching CHANGELOG entries for the
sudo workaround playbook, the linux-modules-extra guard, and the
helm namespace adoption pre-task in the role.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* ci: cover sudo workaround syntax + namespace adoption regression
Two test additions for the Ubuntu 26.04 / namespace-adoption changes:
1. Lint job runs --syntax-check on examples/ubuntu/prepare-sudo.yml,
matching the existing checks for the prepare-* playbooks.
2. E2E job adds a third pipeline run that simulates an orphan
cozy-system namespace: strip the helm release storage Secret and
the namespace's helm labels and annotations, then re-run
examples/ubuntu/site.yml. This is the failure mode the role's
namespace adoption pre-task fixes — without it, helm install
would error with 'invalid ownership metadata'. After the run the
step verifies the namespace carries the expected managed-by label
and meta.helm.sh/release-name annotation again.
A 26.04-specific e2e for the sudo-rs alternative switch is not
included: GitHub-hosted runners are still on 24.04 and there is no
26.04 image yet. The syntax check plus ansible-lint are the most
that fits on the current runner pool.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* fix(examples/ubuntu): harden prepare-sudo.yml secret handling and binary path
Two issues raised in review of the original prepare-sudo.yml:
1. Without no_log: true, ansible_become_password is interpolated
directly into the rendered raw command and would leak into ansible
output on task failure or with -vv verbosity, surfacing the user's
sudo password in CI logs and on-call screenshots.
2. The original code piped the password to bare `sudo`, which on
26.04 resolves to sudo-rs — the very binary the workaround exists
to circumvent — and depends on sudo-rs supporting --stdin/--prompt
in a backwards-compatible way with classical sudo. sudo-rs is a
partial reimplementation and its CLI surface is not stable.
Switch both the password-piped and the passwordless branches to call
/usr/bin/sudo.ws directly (the classical sudo binary co-installed on
26.04 hosts), and add no_log: true to the switch task. The detection
heuristic remains gated on 'sudo-rs' appearing in the active sudo
alternative target, so /usr/bin/sudo.ws is only invoked when we have
already verified sudo-rs is in the picture and sudo.ws is therefore
present.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* fix(role): patch literal cozy-system in adoption pre-task
The cozy-installer chart hardcodes `name: cozy-system` in
templates/cozystack-operator.yaml — there is no values key for the
operator namespace. The role's cozystack_namespace variable is
documented but the chart does not actually honour it (a foot-gun
that pre-dates this change).
The adoption pre-task introduced in 02975ad used the variable, so a
user who set cozystack_namespace to a non-default value would have
the pre-task patch the wrong namespace while helm install still
fails on the literal cozy-system. Patch the literal cozy-system
directly, with a comment pointing at the chart hardcoding so a
future chart change makes the lookup easy to fix back.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* fix(examples/ubuntu): auto-skip linux-modules-extra on 26.04+, doc clarity
Two follow-ups from review of the Ubuntu 26.04 changes:
- Auto-skip the linux-modules-extra-* apt install on Ubuntu 26.04+
by adding 'ansible_distribution_version is version("26.04", "<")'
to the task's when clause. Earlier code required users to set
cozystack_ubuntu_extra_packages: [] in inventory, which is an
unnecessary cliff: ansible_distribution_version is gathered
automatically and the playbook already auto-detects CPU vendor and
distribution elsewhere. Manual override is still respected for
hosts where the fact is unreliable.
- Rephrase the Ubuntu 26.04 note in README from 'two opt-ins' to
'two changes to be aware of'. The sudo-rs alternative switch is
applied automatically by examples/ubuntu/site.yml — a user does
not opt in, they get it for free unless they bypass site.yml.
Clarify that and document the bypass case.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* test(unit): structural invariants for examples/ubuntu/ playbooks
Three regression checks paired with the recent prepare-sudo.yml and
prepare-ubuntu.yml changes:
1. examples/ubuntu/prepare-sudo.yml: the 'Switch sudo alternative'
task carries no_log: true, so ansible_become_password cannot leak
into ansible output if the raw command fails or is run with -vv.
2. The same task invokes /usr/bin/sudo.ws directly in both branches
(password and passwordless). Bare 'sudo' would resolve to sudo-rs
on 26.04 and re-introduce the bug the playbook exists to fix.
3. examples/ubuntu/prepare-ubuntu.yml: the linux-modules-extra task
carries an ansible_distribution_version < 26.04 gate so 26.04
users do not need to set cozystack_ubuntu_extra_packages: [] by
hand.
These run under ansible-test units alongside the existing IP plugin
tests and use only PyYAML, which ansible-core already requires.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* fix(role): refuse to hijack cozy-system from another helm release
Two safety fixes to the namespace-adoption pre-task introduced in
02975ad / b8fc0a3:
1. Foreign-owner refusal. The previous when: clause fired the patch
whenever the namespace's helm metadata did not match this role's
release_name / release_namespace. That includes the case where
cozy-system is legitimately owned by a *different* helm release —
silently overwriting meta.helm.sh/release-name in that case is
data-loss-class: the original owner's next reconcile breaks with
'invalid ownership metadata' and the operator has no signal that
this role flipped the bits. Add an explicit fail task that
triggers when managed-by=Helm and either annotation points
elsewhere, with a message naming the conflicting release. The
adopt task only runs when the managed-by label is missing or
already ours.
2. cozystack_namespace assert. The cozy-installer chart hardcodes
'name: cozy-system' in templates/cozystack-operator.yaml — there
is no values key for the operator namespace. The role used to
document cozystack_namespace as a configurable variable, but
overriding it silently broke the wait/patch tasks in this role
(the operator deploys to cozy-system regardless, while the role
waits in the override). Assert at validation time that the
variable still equals cozy-system, with a clear fail_msg pointing
at the chart constraint. Drop the variable from the user-facing
README table to stop advertising a non-functional knob.
Also: README chart_version drift fix (1.2.2 -> 1.3.1) since the
table is in the same file area touched by this PR.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* test: cover foreign-owner refusal and cozystack_namespace assert
Three new test cases for the safety fixes in ff4b3a3:
- Unit (tests/unit/playbooks/): assert that the role contains a
validation task pinning cozystack_namespace to 'cozy-system', and
a fail-not-patch task gated on managed-by=Helm + release-name
mismatch. Future edits that reintroduce silent re-adoption will
trip these.
- E2E (.github/workflows/test.yml): after the existing adoption
scenario succeeds, re-stamp cozy-system as owned by a fictional
'some-other-release' and run the pipeline again. The role must
fail with 'owned by helm release some-other-release' in the
output. The cleanup step restores ownership so subsequent CI
steps see a healthy cluster.
Also document in prepare-sudo.yml that the password-stdin path
reads only the first line, so a password containing a literal
newline is unsupported. Edge case unlikely in practice but worth
naming since the play's headers describe the password contract.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* docs: move Unreleased to top of CHANGELOG, add Ubuntu 26.04 to supported targets
Two documentation alignments flagged in review:
- CHANGELOG.rst: move Unreleased section to immediately after the
title, ahead of all tagged versions. The previous file order had
Unreleased sandwiched between v1.1.3 and v1.1.2, which is
chronologically nonsensical and contradicts the convention
documented in the contributor guidelines.
- README.md: add Ubuntu 26.04 to the Supported targets table at
top-of-file. The PR adds 26.04 support end-to-end (prepare-sudo
workaround, linux-modules-extra auto-skip, Known limitations
subsection) but the headline distribution table still listed only
22.04 / 24.04 / Debian 12 — readers scanning the table would
conclude 26.04 is unsupported and never reach the limitations.
Mark 26.04 as best-effort with a pointer to Known limitations.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* fix(role): drop cozystack_namespace variable, hardcode literal cozy-system
The cozy-installer chart hardcodes 'name: cozy-system' in
templates/cozystack-operator.yaml and exposes no values key for the
operator namespace. The role's cozystack_namespace variable was
therefore a phantom: documented as configurable, defaulted to
cozy-system, and silently broke the wait/patch tasks if anyone
overrode it (operator deployed to cozy-system regardless, while the
role waited in the override and timed out).
Remove the variable from defaults/main.yml. Replace its remaining
references with the literal 'cozy-system' in the wait task and the
platform-package template. The validation block now asserts the
variable is *unset* — any inventory still defining it (even at the
old default value) fails fast with a clear upgrade message rather
than silently inheriting the typo. Strip cozystack_namespace from
the test fixtures that explicitly set it, since they would now hit
the assert.
Also strengthen the foreign-owner refusal check so a partial-write
state (release-name annotation set without managed-by label, or
vice versa) is still detected as a conflict, instead of slipping
into the adopt branch and stamping our annotations on top.
Add unit tests covering: the rejection assert content, the absence
of any remaining {{ cozystack_namespace }} references in role
files, and the strengthened ownership-indicator coverage in the
foreign-owner fail task. Document the breaking-but-rare variable
removal in CHANGELOG Unreleased.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
* fix(role): drive namespace lookup via kubectl, not kubernetes.core.k8s_info
The k8s_info module requires the optional Python 'kubernetes'
package on the controller, which is not installed in the project's
CI environment (and is not a documented prerequisite for users
either). The rest of this role already drives the cluster via
`kubectl ... --output=json` for the same reason.
Switch the cozy-system lookup to `kubectl get namespace ... \
--ignore-not-found --output=json` and parse the result with
from_json. `--ignore-not-found` returns an empty stdout (rather
than a non-zero exit) when the namespace is absent, so the same
length-check gate as before keeps the foreign-owner and adopt
tasks no-op'd on first install.
The unit tests are unchanged because they check task names and
when-clause structure, not the lookup module's internals.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
---------
Signed-off-by: Aleksei Sviridkin <f@lex.la>1 parent 62e6635 commit 99dd57c
15 files changed
Lines changed: 598 additions & 47 deletions
File tree
- .github/workflows
- examples/ubuntu
- roles/cozystack
- defaults
- tasks
- templates
- tests
- unit/playbooks
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
40 | 43 | | |
41 | 44 | | |
42 | 45 | | |
| |||
230 | 233 | | |
231 | 234 | | |
232 | 235 | | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | 5 | | |
38 | 6 | | |
39 | 7 | | |
40 | 8 | | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
41 | 53 | | |
42 | 54 | | |
43 | 55 | | |
| |||
100 | 112 | | |
101 | 113 | | |
102 | 114 | | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
103 | 148 | | |
104 | 149 | | |
105 | 150 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| |||
167 | 167 | | |
168 | 168 | | |
169 | 169 | | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
170 | 173 | | |
171 | 174 | | |
172 | 175 | | |
| |||
310 | 313 | | |
311 | 314 | | |
312 | 315 | | |
313 | | - | |
| 316 | + | |
314 | 317 | | |
315 | | - | |
316 | 318 | | |
317 | 319 | | |
318 | 320 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
36 | 43 | | |
37 | 44 | | |
38 | 45 | | |
| |||
127 | 134 | | |
128 | 135 | | |
129 | 136 | | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
130 | 140 | | |
131 | 141 | | |
132 | 142 | | |
133 | 143 | | |
134 | | - | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
135 | 148 | | |
136 | 149 | | |
137 | 150 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
10 | 16 | | |
11 | 17 | | |
12 | 18 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | 18 | | |
22 | | - | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| |||
0 commit comments