Skip to content

fix(examples): make prepare and k3s.orchestration runnable as separate invocations#52

Open
Aleksei Sviridkin (lexfrei) wants to merge 10 commits into
mainfrom
fix/split-invocation-k3s-flags
Open

fix(examples): make prepare and k3s.orchestration runnable as separate invocations#52
Aleksei Sviridkin (lexfrei) wants to merge 10 commits into
mainfrom
fix/split-invocation-k3s-flags

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #43.

examples/{ubuntu,rhel,suse}/ pass the Cozystack-tuned k3s configuration into the k3s.orchestration collection through in-process state only: group_by creates the k3s_cluster group and two set_fact tasks set extra_server_args / server_config_yaml. site.yml chains everything with import_playbook, so it works — but running prepare-<distro>.yml and k3s.orchestration.site as separate ansible-playbook commands starts a fresh process where that state is gone. The k3s install then silently falls back to upstream defaults (traefik, servicelb, local-storage, metrics-server, flannel, kube-proxy all enabled; wrong CIDRs; no cozy.local domain), and before that the second run fails outright with 'ansible_hostname' is undefined because the group is empty.

This moves the configuration to inventory scope so it survives across separate invocations, fixing both the silent misconfiguration and the hard failure. Applied to all three example distros (the bug was identical in each).

Changes

  • Move the cozystack k3s flags and CIDRs from play-level vars + set_fact into examples/*/group_vars/all.yml (inventory scope); extra_server_args / server_config_yaml are composed there, still appending the operator's cozystack_k3s_extra_args.
  • Remove the now-redundant set_fact tasks from the prepare playbooks; keep group_by as a fallback for custom inventories run chained via site.yml.
  • Declare the k3s_cluster group statically in each inventory.yml (children: server, agent) so it exists in any process.
  • Document the split-vs-chained run modes in the README and add a CHANGELOG bugfix entry.

Test plan

  • ansible-lint passes (production profile, 0 failures on the changed files)
  • ansible-test sanity passes (not run locally — examples-only change outside the collection sanity surface; CI covers it)
  • Tested on a live cluster (describe environment)
  • Idempotency verified (second run: changed=0)

Verified without a live cluster:

  • ansible-inventory --graph shows k3s_cluster populated with server + agent in all three dirs.
  • An ad-hoc local play renders extra_server_args to the full --disable=… set ending in the inventory's --tls-san, and server_config_yaml to the cluster/service CIDRs — a standalone k3s.orchestration.site process now sees the tuned values.
  • --syntax-check passes for all prepare playbooks; hack/check-versions.sh + hack/test-check-versions.sh pass (no version drift).

Summary by CodeRabbit

  • New Features

    • Added CI validation to ensure k3s example configurations remain consistent.
  • Documentation

    • Updated README with clarified guidance on k3s defaults, configuration persistence across playbook runs, and recommended practices for customizing k3s settings.
    • Updated release notes documenting changes to k3s cluster configuration structure.
  • Chores

    • Restructured k3s configuration to persist across multiple Ansible playbook invocations.

The cozystack-tuned k3s flags and CIDRs were set via set_fact in the
prepare playbooks, so they only existed inside a single ansible-playbook
process. Running prepare-<distro>.yml and k3s.orchestration.site as
separate invocations dropped them and produced an upstream-default k3s
(traefik, servicelb, flannel, kube-proxy all enabled; wrong CIDRs).

Move the settings to examples/*/group_vars/all.yml (inventory scope) so
they survive across separate invocations, and remove the now-redundant
set_fact tasks and play vars. The group_by task stays as a fallback for
custom inventories run via the chained site.yml.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
The k3s_cluster group was created only at runtime by group_by in the
prepare playbooks, so a standalone 'ansible-playbook
k3s.orchestration.site' invocation found it empty and failed with
'ansible_hostname is undefined'.

Declare it statically (children: server, agent) in each example
inventory so it is present in any ansible-playbook process. The
group_by fallback remains for custom inventories run via the chained
site.yml. Also refresh the cozystack_k3s_extra_args comment to point at
group_vars/all.yml, where it is now consumed.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@lexfrei, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 6 minutes and 8 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6dfc3c40-997f-4cc6-89a4-d963b18eed90

📥 Commits

Reviewing files that changed from the base of the PR and between a57c925 and 3de8996.

📒 Files selected for processing (6)
  • .github/workflows/test.yml
  • CHANGELOG.rst
  • README.md
  • examples/rhel/prepare-rhel.yml
  • examples/suse/prepare-suse.yml
  • examples/ubuntu/prepare-ubuntu.yml
📝 Walkthrough

Walkthrough

Cozystack-tuned k3s variables (extra_server_args, server_config_yaml) are relocated from runtime set_fact in per-distro prepare playbooks into static group_vars/all.yml files for Ubuntu, RHEL, and SUSE. Each example inventory gains a statically declared k3s_cluster group. A new CI guard script (hack/check-examples-k3s.sh) and its test harness enforce the resulting contract; both are wired into the GitHub Actions workflow.

Changes

k3s Split-Invocation Contract

Layer / File(s) Summary
New group_vars/all.yml k3s configuration
examples/ubuntu/group_vars/all.yml, examples/rhel/group_vars/all.yml, examples/suse/group_vars/all.yml
Three new files define cozystack_k3s_server_args, cozystack_k3s_server_config_yaml, extra_server_args, and server_config_yaml at inventory group scope so they are loaded by every separate ansible-playbook invocation.
Static k3s_cluster group in inventories
examples/ubuntu/inventory.yml, examples/rhel/inventory.yml, examples/suse/inventory.yml
Each distro inventory now declares k3s_cluster with empty server and agent children; cozystack_k3s_extra_args is repositioned into a consistent vars block.
Remove set_fact and inline vars from prepare playbooks
examples/ubuntu/prepare-ubuntu.yml, examples/rhel/prepare-rhel.yml, examples/suse/prepare-suse.yml
Inline cozystack_k3s_server_args and cozystack_k3s_server_config_yaml definitions removed; set_fact tasks for extra_server_args and server_config_yaml deleted; group_by backward-compat task retained with updated comments.
hack/check-examples-k3s.sh: split-invocation contract guard
hack/check-examples-k3s.sh
New bash script validates static k3s_cluster group in inventories, required variables in group_vars/all.yml with correct flag/CIDR content, and absence of those variables from prepare playbooks; exits nonzero on any failure.
hack/test-check-examples-k3s.sh: guard test harness
hack/test-check-examples-k3s.sh
Bash test script runs the guard on a clean tree (expecting exit 0) and on multiple mutated trees (expecting nonzero), including a regression case for reintroducing extra_server_args in a prepare playbook.
CI workflow, docs, and changelog
.github/workflows/test.yml, README.md, CHANGELOG.rst, tests/ci-inventory.yml
Both guard scripts added as lint steps in CI; README updated with split-invocation CLI guidance and variable precedence rules; changelog entries added; tests/ci-inventory.yml annotated with usage warning.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #43 (examples/ubuntu: splitting prepare-ubuntu.yml and k3s.orchestration.site silently drops cozystack k3s flags): This PR directly resolves the root cause described in that issue by moving extra_server_args and server_config_yaml from set_fact into group_vars/all.yml and declaring k3s_cluster statically in inventories, enabling split invocation to work correctly.

Suggested reviewers

  • androndo

Poem

🐇 Hopping 'cross playbooks, one run or three,
The k3s flags now live where all can see —
In group_vars/all, they persist with grace,
No silent drop-off when switching the space.
The guard script watches, the tests all pass,
Split invocations work at last! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: enabling prepare and k3s.orchestration playbooks to run as separate invocations by restructuring k3s configuration from in-process state to inventory scope.
Description check ✅ Passed The PR description comprehensively covers the problem, solution, and verification steps; it includes checkbox test items and explicitly documents what was verified without a live cluster.
Linked Issues check ✅ Passed The PR fully addresses issue #43 by implementing core solutions: moving k3s config to group_vars, declaring k3s_cluster statically, keeping group_by/set_fact as fallbacks, documenting split-vs-chained modes, and adding CI guards to prevent regressions.
Out of Scope Changes check ✅ Passed All changes are directly aligned with fixing split-invocation support: k3s config migration, inventory restructuring, prepare playbook cleanup, documentation updates, CHANGELOG entry, and CI guards—no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/split-invocation-k3s-flags

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the Cozystack-tuned k3s configuration by moving settings from dynamic set_fact calls in the prepare playbooks to static declarations in group_vars/all.yml and inventory.yml across the example environments. This ensures that the configuration persists when running the playbooks in separate invocations. The review feedback suggests updating the Quick start section in the README.md to include the new group_vars directory, and recommends using default("", true) in the group_vars/all.yml files to safely handle cases where cozystack_k3s_extra_args is defined as null.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread README.md
ansible.builtin.import_playbook: cozystack.installer.site
```

The Cozystack-tuned k3s flags (component disables, CIDRs, cluster domain) live in each example's `group_vars/all.yml`, and the `k3s_cluster` group is declared statically in each `inventory.yml`. Both therefore exist in every `ansible-playbook` process, so the steps can be run chained through `site.yml` or as separate invocations:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since the Cozystack-tuned k3s flags have been moved to group_vars/all.yml, the Quick start section earlier in this README (around line 280) should be updated to include the group_vars/ directory (or group_vars/all.yml) in the example file tree. Otherwise, users following the Quick start instructions literally will miss copying this file, resulting in an upstream-default k3s installation.

# Composed from the Cozystack defaults above plus any operator-supplied
# extra flags (cozystack_k3s_extra_args from inventory, e.g. --tls-san).
extra_server_args: >-
{{ cozystack_k3s_server_args }} {{ cozystack_k3s_extra_args | default("") }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If cozystack_k3s_extra_args is defined as null (e.g., left blank in the inventory like cozystack_k3s_extra_args:), the default("") filter will not be triggered because the variable is technically defined. This can result in the literal string None being appended to extra_server_args, which will cause k3s to fail to start.

Using default("", true) ensures that the default value is used if the variable is undefined or evaluates to a falsy value (such as null or None).

  {{ cozystack_k3s_server_args }} {{ cozystack_k3s_extra_args | default("", true) }}

# Composed from the Cozystack defaults above plus any operator-supplied
# extra flags (cozystack_k3s_extra_args from inventory, e.g. --tls-san).
extra_server_args: >-
{{ cozystack_k3s_server_args }} {{ cozystack_k3s_extra_args | default("") }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If cozystack_k3s_extra_args is defined as null (e.g., left blank in the inventory like cozystack_k3s_extra_args:), the default("") filter will not be triggered because the variable is technically defined. This can result in the literal string None being appended to extra_server_args, which will cause k3s to fail to start.

Using default("", true) ensures that the default value is used if the variable is undefined or evaluates to a falsy value (such as null or None).

  {{ cozystack_k3s_server_args }} {{ cozystack_k3s_extra_args | default("", true) }}

# Composed from the Cozystack defaults above plus any operator-supplied
# extra flags (cozystack_k3s_extra_args from inventory, e.g. --tls-san).
extra_server_args: >-
{{ cozystack_k3s_server_args }} {{ cozystack_k3s_extra_args | default("") }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If cozystack_k3s_extra_args is defined as null (e.g., left blank in the inventory like cozystack_k3s_extra_args:), the default("") filter will not be triggered because the variable is technically defined. This can result in the literal string None being appended to extra_server_args, which will cause k3s to fail to start.

Using default("", true) ensures that the default value is used if the variable is undefined or evaluates to a falsy value (such as null or None).

  {{ cozystack_k3s_server_args }} {{ cozystack_k3s_extra_args | default("", true) }}

Document that the Cozystack k3s settings now live in group_vars/all.yml
and the k3s_cluster group is declared statically, so prepare-<distro>.yml
and k3s.orchestration.site can be run as separate invocations or chained
through site.yml. Record the fix as a CHANGELOG bugfix entry.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
@lexfrei Aleksei Sviridkin (lexfrei) force-pushed the fix/split-invocation-k3s-flags branch from 069ea32 to a43b4a8 Compare June 18, 2026 03:52
Add hack/check-examples-k3s.sh: assert each example declares the
k3s_cluster group statically and resolves extra_server_args /
server_config_yaml to the Cozystack-tuned values in a fresh process
(no prepare run, no set_fact) — the split-invocation path. A companion
hack/test-check-examples-k3s.sh self-tests it by perturbing each
invariant and asserting a nonzero exit. Both run in the Lint job.

Without this guard, a change that moves the flags back into set_fact,
drops the static group, or adds a distro example without group_vars
would silently reintroduce the upstream-default k3s install with no
failing test.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
The changelog had two Unreleased headings — one without an RST underline
(it rendered as body text) and one properly underlined. Merge them into
a single underlined Unreleased section so every pending entry renders
under one heading.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
The prepare playbooks no longer set the k3s server arguments — those
moved to group_vars/all.yml. Update the header comment to match rather
than describe the removed behavior.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
Extend hack/check-examples-k3s.sh to fail if a prepare playbook
references extra_server_args / server_config_yaml. A play-scoped value
outranks group_vars on the chained site.yml path while leaving the
split-invocation path broken, silently reintroducing the bug. The
self-test covers the reintroduction case.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
The pod/service CIDRs are now defined in
examples/<distro>/group_vars/all.yml, not set inside the prepare
playbooks. Update the network-configuration note to reference the file
that actually carries them.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
tests/ci-inventory.yml carries no static k3s_cluster group and no
cozystack k3s flags because it is run only through the chained
examples/ubuntu/site.yml: the group_by task creates k3s_cluster and
examples/ubuntu/group_vars/all.yml supplies extra_server_args /
server_config_yaml as playbook-adjacent group_vars, all in one process.
Document this so the inventory is not mistaken for a standalone target.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
@lexfrei Aleksei Sviridkin (lexfrei) marked this pull request as ready for review June 18, 2026 04:54
Signed-off-by: Aleksei Sviridkin <f@lex.la>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

examples/ubuntu: splitting prepare-ubuntu.yml and k3s.orchestration.site silently drops cozystack k3s flags

1 participant