Skip to content

Add non-mutating --dry-run preflight and testable installer parameters - #12

Merged
xnoto merged 5 commits into
mainfrom
feature/dry-run-installer-tests
Sep 2, 2026
Merged

Add non-mutating --dry-run preflight and testable installer parameters#12
xnoto merged 5 commits into
mainfrom
feature/dry-run-installer-tests

Conversation

@xnoto

@xnoto xnoto commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a non-mutating --dry-run preflight mode to set_dns.py and makes install.py testable, per the authorized task design:

  • set_dns.py gains argparse-based CLI parsing with optional --dry-run and --config PATH. Dispatcher positional arguments (interface/action) are preserved and normal behavior is unchanged when --dry-run is omitted. Dry run validates root-volume config selection/parsing, the local IPv4, dispatcher arguments, and the derived FQDN, prints the intended reconciliation, and returns success without constructing a Cloudflare client or making any API call.
  • install.py install() gains optional source_dir, dispatcher_path, and config_files parameters. Production constants, default paths, root check, alias priority, ownership (0:0), and modes (0700/0600) are unchanged.
  • Tests prove dry-run avoids client construction, reports the intended action, honors --config, preserves dispatcher arguments, and that the installer prefers cflan_-prefixed config, keeps legacy aliases valid, applies expected ownership/modes, and fails on missing dispatcher directory or non-root execution — all with tmp_path and mocks.
  • README/CONTRIBUTING document --dry-run precisely: it never constructs a Cloudflare client or calls the Cloudflare API; for an encrypted selected config (cflan_sops_vars.yaml/sops_vars.yaml) it does invoke SOPS locally, exercising SOPS/key availability without writing plaintext to disk; and it does not install or execute the actual NetworkManager dispatcher hook.

Type of change

  • Feature / enhancement
  • Documentation

Validation

  • Required pull-request checks pass (lint/test matrix 3.10–3.13, mypy, wheel build — reported on this PR)
  • Generated or centrally distributed files were regenerated by their owning automation, not hand-edited (no generated files touched)

Intentionally not validated: live host installation, NetworkManager dispatcher execution, and Cloudflare API behavior — out of scope and unchanged.

Impact and rollout

None beyond this repository. Source-only change; no version bump, no release, no GitOps or runtime impact. Existing installations are unaffected until they choose to upgrade. --dry-run never contacts the Cloudflare API and does not install or execute the NetworkManager dispatcher hook; for an encrypted selected config it invokes SOPS locally (in-process plaintext only, never written to disk).

Safety and secrets

  • Contains no plaintext secrets, decrypted SOPS values, state files, kubeconfigs, tokens, or private endpoints (all test fixtures use placeholder values such as test-token; changed content was inspected for secrets before commit)
  • No local OpenTofu init/plan/apply/destroy/import/state operations were run or claimed — plans come from pull-request checks
  • Breaking or irreversible effects are described above with rollback notes (none; rollback is reverting this PR)

This change was produced by an AI agent per an authorized task specification; scope was fixed by the requester.

- set_dns.py: add argparse CLI with --dry-run and --config while preserving
  dispatcher positional arguments (interface/action). Dry run validates
  config selection/parsing, local IPv4, dispatcher arguments, and the
  derived FQDN, prints the intended reconciliation, and returns success
  without constructing a Cloudflare client or calling the API.
- install.py: make install() testable via optional source_dir,
  dispatcher_path, and config_files parameters; production constants,
  defaults, paths, root check, aliases, ownership, and modes unchanged.
- tests: cover dry-run client avoidance, intended-action reporting,
  --config selection, dispatcher argument handling, preferred-over-legacy
  config priority, installer targets/ownership/modes, and failure paths
  using tmp_path and mocks.
- README/CONTRIBUTING: document --dry-run as a non-mutating preflight that
  does not test Cloudflare/SOPS key availability or dispatcher execution.
@xnoto
xnoto requested a review from a team as a code owner September 2, 2026 00:24
Patching os.getuid in a fixture ran before tmp_path setup and broke
pytest's temporary-directory ownership check. Patch only around the
install() invocation via context managers.
@xnoto
xnoto merged commit b54caed into main Sep 2, 2026
6 checks passed
@xnoto
xnoto deleted the feature/dry-run-installer-tests branch September 2, 2026 00:35
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.

1 participant