From c742694ad8cbd90c4029b5284f37a8f68a920cab Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Sun, 6 Sep 2026 22:58:07 +0000 Subject: [PATCH 1/3] docs: generate a CLI reference from the cobra command tree talm's only documentation was the README, which never covered the command surface: five native commands plus everything wrapped from talosctl, each with its own flags. Writing that by hand would go stale on the next Talos bump, since the wrapper re-exports whatever upstream ships. Render it instead. TestReferenceDocs walks the live command tree and compares it against the committed pages, so `go test ./...` fails when the two drift; `make docs` rewrites them. This follows the golden-file convention already used for the chart render snapshots. The pages are rendered per command rather than through doc.GenMarkdownTree, which hardcodes file names carrying a redundant talm_ prefix and opens each page at H2, leaving no H1 for a docs site to title it from. Cobra's auto-generated date stamp is also suppressed on every command, not just those with a parent, so repeated runs agree. The test skips on Windows: flag defaults are built with filepath.Join, so the rendered pages carry backslashes there and a byte comparison fails for reasons unrelated to drift. Assisted-by: LLM Signed-off-by: Aleksei Sviridkin --- .gitattributes | 5 + Makefile | 8 + docs/reference/.nav.yml | 6 + docs/reference/apply.md | 77 +++++++ docs/reference/bootstrap.md | 46 ++++ docs/reference/cgroups.md | 54 +++++ docs/reference/completion.md | 38 ++++ docs/reference/completion_bash.md | 57 +++++ docs/reference/completion_fish.md | 48 ++++ docs/reference/completion_powershell.md | 45 ++++ docs/reference/completion_zsh.md | 59 +++++ docs/reference/conformance.md | 30 +++ docs/reference/conformance_kubernetes.md | 34 +++ docs/reference/containers.md | 34 +++ docs/reference/copy.md | 44 ++++ docs/reference/crashdump.md | 36 +++ docs/reference/dashboard.md | 50 +++++ docs/reference/debug.md | 45 ++++ docs/reference/disks.md | 33 +++ docs/reference/edit.md | 46 ++++ docs/reference/etcd.md | 38 ++++ docs/reference/etcd_alarm.md | 31 +++ docs/reference/etcd_alarm_disarm.md | 33 +++ docs/reference/etcd_alarm_list.md | 33 +++ docs/reference/etcd_defrag.md | 38 ++++ docs/reference/etcd_downgrade.md | 32 +++ docs/reference/etcd_downgrade_cancel.md | 33 +++ docs/reference/etcd_downgrade_enable.md | 33 +++ docs/reference/etcd_downgrade_validate.md | 33 +++ docs/reference/etcd_forfeit-leadership.md | 33 +++ docs/reference/etcd_leave.md | 33 +++ docs/reference/etcd_members.md | 33 +++ docs/reference/etcd_remove-member.md | 39 ++++ docs/reference/etcd_snapshot.md | 33 +++ docs/reference/etcd_status.md | 37 ++++ docs/reference/events.md | 37 ++++ docs/reference/get.md | 42 ++++ docs/reference/health.md | 40 ++++ docs/reference/image.md | 39 ++++ docs/reference/image_cache-cert-gen.md | 43 ++++ docs/reference/image_cache-create.md | 56 +++++ docs/reference/image_cache-serve.md | 43 ++++ docs/reference/image_integration.md | 37 ++++ docs/reference/image_k8s-bundle.md | 39 ++++ docs/reference/image_list.md | 34 +++ docs/reference/image_pull.md | 34 +++ docs/reference/image_remove.md | 34 +++ docs/reference/image_talos-bundle.md | 36 +++ docs/reference/index.md | 69 ++++++ docs/reference/init.md | 41 ++++ docs/reference/inspect.md | 30 +++ docs/reference/inspect_dependencies.md | 44 ++++ docs/reference/interfaces.md | 33 +++ docs/reference/kubeconfig.md | 43 ++++ docs/reference/list.md | 41 ++++ docs/reference/logs.md | 36 +++ docs/reference/memory.md | 34 +++ docs/reference/meta.md | 32 +++ docs/reference/meta_delete.md | 34 +++ docs/reference/meta_write.md | 34 +++ docs/reference/mounts.md | 33 +++ docs/reference/netstat.md | 55 +++++ docs/reference/pcap.md | 70 ++++++ docs/reference/processes.md | 34 +++ docs/reference/read.md | 33 +++ docs/reference/reboot.md | 40 ++++ docs/reference/reset.md | 42 ++++ docs/reference/restart.md | 34 +++ docs/reference/rollback.md | 33 +++ docs/reference/rotate-ca.md | 80 +++++++ docs/reference/routes.md | 33 +++ docs/reference/service.md | 39 ++++ docs/reference/shutdown.md | 37 ++++ docs/reference/stats.md | 34 +++ docs/reference/support.md | 58 +++++ docs/reference/talosconfig.md | 44 ++++ docs/reference/template.md | 61 ++++++ docs/reference/time.md | 34 +++ docs/reference/upgrade.md | 77 +++++++ docs/reference/usage.md | 37 ++++ docs/reference/version.md | 36 +++ docs/reference/wipe.md | 30 +++ docs/reference/wipe_disk.md | 42 ++++ docs_reference_test.go | 254 ++++++++++++++++++++++ go.mod | 1 + go.sum | 2 + main.go | 6 +- 87 files changed, 3569 insertions(+), 2 deletions(-) create mode 100644 docs/reference/.nav.yml create mode 100644 docs/reference/apply.md create mode 100644 docs/reference/bootstrap.md create mode 100644 docs/reference/cgroups.md create mode 100644 docs/reference/completion.md create mode 100644 docs/reference/completion_bash.md create mode 100644 docs/reference/completion_fish.md create mode 100644 docs/reference/completion_powershell.md create mode 100644 docs/reference/completion_zsh.md create mode 100644 docs/reference/conformance.md create mode 100644 docs/reference/conformance_kubernetes.md create mode 100644 docs/reference/containers.md create mode 100644 docs/reference/copy.md create mode 100644 docs/reference/crashdump.md create mode 100644 docs/reference/dashboard.md create mode 100644 docs/reference/debug.md create mode 100644 docs/reference/disks.md create mode 100644 docs/reference/edit.md create mode 100644 docs/reference/etcd.md create mode 100644 docs/reference/etcd_alarm.md create mode 100644 docs/reference/etcd_alarm_disarm.md create mode 100644 docs/reference/etcd_alarm_list.md create mode 100644 docs/reference/etcd_defrag.md create mode 100644 docs/reference/etcd_downgrade.md create mode 100644 docs/reference/etcd_downgrade_cancel.md create mode 100644 docs/reference/etcd_downgrade_enable.md create mode 100644 docs/reference/etcd_downgrade_validate.md create mode 100644 docs/reference/etcd_forfeit-leadership.md create mode 100644 docs/reference/etcd_leave.md create mode 100644 docs/reference/etcd_members.md create mode 100644 docs/reference/etcd_remove-member.md create mode 100644 docs/reference/etcd_snapshot.md create mode 100644 docs/reference/etcd_status.md create mode 100644 docs/reference/events.md create mode 100644 docs/reference/get.md create mode 100644 docs/reference/health.md create mode 100644 docs/reference/image.md create mode 100644 docs/reference/image_cache-cert-gen.md create mode 100644 docs/reference/image_cache-create.md create mode 100644 docs/reference/image_cache-serve.md create mode 100644 docs/reference/image_integration.md create mode 100644 docs/reference/image_k8s-bundle.md create mode 100644 docs/reference/image_list.md create mode 100644 docs/reference/image_pull.md create mode 100644 docs/reference/image_remove.md create mode 100644 docs/reference/image_talos-bundle.md create mode 100644 docs/reference/index.md create mode 100644 docs/reference/init.md create mode 100644 docs/reference/inspect.md create mode 100644 docs/reference/inspect_dependencies.md create mode 100644 docs/reference/interfaces.md create mode 100644 docs/reference/kubeconfig.md create mode 100644 docs/reference/list.md create mode 100644 docs/reference/logs.md create mode 100644 docs/reference/memory.md create mode 100644 docs/reference/meta.md create mode 100644 docs/reference/meta_delete.md create mode 100644 docs/reference/meta_write.md create mode 100644 docs/reference/mounts.md create mode 100644 docs/reference/netstat.md create mode 100644 docs/reference/pcap.md create mode 100644 docs/reference/processes.md create mode 100644 docs/reference/read.md create mode 100644 docs/reference/reboot.md create mode 100644 docs/reference/reset.md create mode 100644 docs/reference/restart.md create mode 100644 docs/reference/rollback.md create mode 100644 docs/reference/rotate-ca.md create mode 100644 docs/reference/routes.md create mode 100644 docs/reference/service.md create mode 100644 docs/reference/shutdown.md create mode 100644 docs/reference/stats.md create mode 100644 docs/reference/support.md create mode 100644 docs/reference/talosconfig.md create mode 100644 docs/reference/template.md create mode 100644 docs/reference/time.md create mode 100644 docs/reference/upgrade.md create mode 100644 docs/reference/usage.md create mode 100644 docs/reference/version.md create mode 100644 docs/reference/wipe.md create mode 100644 docs/reference/wipe_disk.md create mode 100644 docs_reference_test.go diff --git a/.gitattributes b/.gitattributes index d6894d5c..a2350b4f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -27,3 +27,8 @@ pkg/generated/** linguist-generated # not hand-edited. Marking them generated keeps the rendered YAML dumps # out of language stats and collapses them in PR diffs by default. pkg/engine/testdata/golden/** linguist-generated + +# docs/reference/ is rendered from the cobra command tree by +# `make docs`, not hand-edited. Marking it generated keeps it out of +# language stats and collapses it in PR diffs by default. +docs/reference/*.md linguist-generated diff --git a/Makefile b/Makefile index bfe3c7ba..8c077b67 100644 --- a/Makefile +++ b/Makefile @@ -9,3 +9,11 @@ TALOS_VERSION=$(shell go list -m github.com/siderolabs/talos | awk '{sub(/^v/, build: go build -ldflags="-X 'main.Version=$(VERSION)'" + +# Rewrite docs/reference/ from the cobra command tree. TestReferenceDocs +# compares the committed pages against that tree on every `go test ./...`, +# so run this after adding a command or bumping Talos. +docs: + TALM_UPDATE_DOCS=1 go test . -run TestReferenceDocs + +.PHONY: build docs diff --git a/docs/reference/.nav.yml b/docs/reference/.nav.yml new file mode 100644 index 00000000..a077a8ed --- /dev/null +++ b/docs/reference/.nav.yml @@ -0,0 +1,6 @@ +# Pages here are generated from the cobra command tree, so the list changes +# whenever a command is added — including on a Talos bump, since talm wraps +# talosctl's commands. Match them by glob instead of naming each one. +nav: + - index.md + - "*.md" diff --git a/docs/reference/apply.md b/docs/reference/apply.md new file mode 100644 index 00000000..3fd07980 --- /dev/null +++ b/docs/reference/apply.md @@ -0,0 +1,77 @@ +# talm apply + +Apply config to a Talos node + +## Synopsis + +Apply rendered configuration to a Talos node. + +Multi-file invocation (anchor + side-patches): the FIRST -f file is the +anchor — it must carry a "# talm: nodes=[…], templates=[…]" modeline and +live under a project root (Chart.yaml + secrets.yaml). Subsequent -f +files are side-patches stacked on top of the anchor's rendered config in +the order they appear; each is merged via the same overlay mechanism the +anchor's node body uses. A single ApplyConfiguration is issued per node +with the composed result. + +Examples: + + # Single node file (anchor only): + talm apply -f nodes/cp01.yaml + + # Stacked side-patches (e.g. one-shot debug overlay): + talm apply -f nodes/cp01.yaml -f /tmp/debug-kubelet.yaml + + # Side-patches do NOT need to live under the project root; the + # first file anchors detection. Reversing the order is an error + # (the orphan path has no project to anchor on). + +``` +talm apply [flags] +``` + +## Options + +``` + --cert-fingerprint strings list of server certificate fingeprints to accept (defaults to no check) + --debug show only rendered patches + --dry-run check how the config change will be applied in dry-run mode + -f, --file .yaml node config files / patches (.yaml / `.yml`; shell completion narrows to these extensions). First -f is the modelined anchor (must live under a `talm init`'d project root); subsequent -f files are side-patches stacked onto the anchor's rendered config and may live anywhere. + --force will overwrite existing files + -h, --help help for apply + -i, --insecure apply using the insecure (encrypted with no auth) maintenance service + --kubernetes-version string desired kubernetes version to run (default "1.36.2") + -m, --mode auto, no-reboot, reboot, staged, try apply config mode (default auto) + --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). For IP / CIDR / version literals use --set-string — dots in --set values are interpreted as YAML key nesting. + --set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2) + --set-json stringArray set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2) + --set-literal stringArray set a literal STRING value on the command line + --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Use for IP addresses, CIDR blocks, version strings, or any literal value where dots must NOT be interpreted as YAML key nesting. + --show-secrets-in-drift show secret-bearing field values verbatim in drift preview / post-apply verify output (default: redacted). Covers both the Talos bootstrap allowlist (cluster.token, cluster.ca.key, machine.token, Wireguard private keys, etc.) and values from encrypted value files (*.encrypted.yaml). Counterpart on template is --show-secrets, which governs the same values in template's stdout render. + --skip-drift-preview skip the pre-apply diff of on-node vs rendered MachineConfig + --skip-post-apply-verify skip the post-apply structural verification of on-node vs sent MachineConfig (default skip until the Talos-mutated field allowlist lands) (default true) + --skip-resource-validation skip the pre-apply check that declared host resources (links, disks) exist on the target node + --talos-version string the desired Talos version to generate config for (backwards compatibility, e.g. v0.8) + --timeout duration the config will be rolled back after specified timeout (if try mode is selected) (default 1m0s) + --values talm template specify values in a YAML file (can specify multiple). Must match talm template — apply re-renders from the modeline and would otherwise drop value files supplied at template time. + --with-secrets string use a secrets file generated using 'gen secrets' +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/bootstrap.md b/docs/reference/bootstrap.md new file mode 100644 index 00000000..ef3288b5 --- /dev/null +++ b/docs/reference/bootstrap.md @@ -0,0 +1,46 @@ +# talm bootstrap + +Bootstrap the etcd cluster on the specified node. + +## Synopsis + +When Talos cluster is created etcd service on control plane nodes enter the join loop waiting +to join etcd peers from other control plane nodes. One node should be picked as the bootstrap node. +When bootstrap command is issued, the node aborts join process and bootstraps etcd cluster as a single node cluster. +Other control plane nodes will join etcd cluster once Kubernetes is bootstrapped on the bootstrap node. + +This command should not be used when "init" type node are used. + +Talos etcd cluster can be recovered from a known snapshot with '--recover-from=' flag. + +``` +talm bootstrap [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for bootstrap + --recover-from string recover etcd cluster from the snapshot + --recover-skip-hash-check skip integrity check when recovering etcd (use when recovering from data directory copy) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/cgroups.md b/docs/reference/cgroups.md new file mode 100644 index 00000000..a4433876 --- /dev/null +++ b/docs/reference/cgroups.md @@ -0,0 +1,54 @@ +# talm cgroups + +Retrieve cgroups usage information + +## Synopsis + +The cgroups command fetches control group v2 (cgroupv2) usage details from the machine. +Several presets are available to focus on specific cgroup subsystems: + +* cpu +* cpuset +* io +* memory +* process +* swap + +You can specify the preset using the --preset flag. + +Alternatively, a custom schema can be provided using the --schema-file flag. +To see schema examples, refer to https://github.com/siderolabs/talos/tree/main/cmd/talosctl/cmd/talos/cgroupsprinter/schemas. + + +``` +talm cgroups [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for cgroups + --preset string preset name (one of: [cpu cpuset io memory process psi swap]) + --schema-file string path to the columns schema file + --skip-cri-resolve do not resolve cgroup names via a request to CRI +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/completion.md b/docs/reference/completion.md new file mode 100644 index 00000000..dac8e506 --- /dev/null +++ b/docs/reference/completion.md @@ -0,0 +1,38 @@ +# talm completion + +Generate the autocompletion script for the specified shell + +## Synopsis + +Generate the autocompletion script for talm for the specified shell. +See each sub-command's help for details on how to use the generated script. + + +## Options + +``` + -h, --help help for completion +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! +* [talm completion bash](completion_bash.md) - Generate the autocompletion script for bash +* [talm completion fish](completion_fish.md) - Generate the autocompletion script for fish +* [talm completion powershell](completion_powershell.md) - Generate the autocompletion script for powershell +* [talm completion zsh](completion_zsh.md) - Generate the autocompletion script for zsh + diff --git a/docs/reference/completion_bash.md b/docs/reference/completion_bash.md new file mode 100644 index 00000000..81f6a907 --- /dev/null +++ b/docs/reference/completion_bash.md @@ -0,0 +1,57 @@ +# talm completion bash + +Generate the autocompletion script for bash + +## Synopsis + +Generate the autocompletion script for the bash shell. + +This script depends on the 'bash-completion' package. +If it is not installed already, you can install it via your OS's package manager. + +To load completions in your current shell session: + + source <(talm completion bash) + +To load completions for every new session, execute once: + +#### Linux: + + talm completion bash > /etc/bash_completion.d/talm + +#### macOS: + + talm completion bash > $(brew --prefix)/etc/bash_completion.d/talm + +You will need to start a new shell for this setup to take effect. + + +``` +talm completion bash +``` + +## Options + +``` + -h, --help help for bash + --no-descriptions disable completion descriptions +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm completion](completion.md) - Generate the autocompletion script for the specified shell + diff --git a/docs/reference/completion_fish.md b/docs/reference/completion_fish.md new file mode 100644 index 00000000..7c69bd5a --- /dev/null +++ b/docs/reference/completion_fish.md @@ -0,0 +1,48 @@ +# talm completion fish + +Generate the autocompletion script for fish + +## Synopsis + +Generate the autocompletion script for the fish shell. + +To load completions in your current shell session: + + talm completion fish | source + +To load completions for every new session, execute once: + + talm completion fish > ~/.config/fish/completions/talm.fish + +You will need to start a new shell for this setup to take effect. + + +``` +talm completion fish [flags] +``` + +## Options + +``` + -h, --help help for fish + --no-descriptions disable completion descriptions +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm completion](completion.md) - Generate the autocompletion script for the specified shell + diff --git a/docs/reference/completion_powershell.md b/docs/reference/completion_powershell.md new file mode 100644 index 00000000..1ddfa8e9 --- /dev/null +++ b/docs/reference/completion_powershell.md @@ -0,0 +1,45 @@ +# talm completion powershell + +Generate the autocompletion script for powershell + +## Synopsis + +Generate the autocompletion script for powershell. + +To load completions in your current shell session: + + talm completion powershell | Out-String | Invoke-Expression + +To load completions for every new session, add the output of the above command +to your powershell profile. + + +``` +talm completion powershell [flags] +``` + +## Options + +``` + -h, --help help for powershell + --no-descriptions disable completion descriptions +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm completion](completion.md) - Generate the autocompletion script for the specified shell + diff --git a/docs/reference/completion_zsh.md b/docs/reference/completion_zsh.md new file mode 100644 index 00000000..5a024cc7 --- /dev/null +++ b/docs/reference/completion_zsh.md @@ -0,0 +1,59 @@ +# talm completion zsh + +Generate the autocompletion script for zsh + +## Synopsis + +Generate the autocompletion script for the zsh shell. + +If shell completion is not already enabled in your environment you will need +to enable it. You can execute the following once: + + echo "autoload -U compinit; compinit" >> ~/.zshrc + +To load completions in your current shell session: + + source <(talm completion zsh) + +To load completions for every new session, execute once: + +#### Linux: + + talm completion zsh > "${fpath[1]}/_talm" + +#### macOS: + + talm completion zsh > $(brew --prefix)/share/zsh/site-functions/_talm + +You will need to start a new shell for this setup to take effect. + + +``` +talm completion zsh [flags] +``` + +## Options + +``` + -h, --help help for zsh + --no-descriptions disable completion descriptions +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm completion](completion.md) - Generate the autocompletion script for the specified shell + diff --git a/docs/reference/conformance.md b/docs/reference/conformance.md new file mode 100644 index 00000000..b70a19b5 --- /dev/null +++ b/docs/reference/conformance.md @@ -0,0 +1,30 @@ +# talm conformance + +Run conformance tests + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for conformance +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! +* [talm conformance kubernetes](conformance_kubernetes.md) - Run Kubernetes conformance tests + diff --git a/docs/reference/conformance_kubernetes.md b/docs/reference/conformance_kubernetes.md new file mode 100644 index 00000000..c18b2957 --- /dev/null +++ b/docs/reference/conformance_kubernetes.md @@ -0,0 +1,34 @@ +# talm conformance kubernetes + +Run Kubernetes conformance tests + +``` +talm conformance kubernetes [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for kubernetes + --mode string conformance test mode: [fast, certified, network-policy] (default "fast") +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm conformance](conformance.md) - Run conformance tests + diff --git a/docs/reference/containers.md b/docs/reference/containers.md new file mode 100644 index 00000000..fead2d51 --- /dev/null +++ b/docs/reference/containers.md @@ -0,0 +1,34 @@ +# talm containers + +List containers + +``` +talm containers [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for containers + -k, --kubernetes use the k8s.io containerd namespace +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/copy.md b/docs/reference/copy.md new file mode 100644 index 00000000..50877a9b --- /dev/null +++ b/docs/reference/copy.md @@ -0,0 +1,44 @@ +# talm copy + +Copy data out from the node + +## Synopsis + +Creates an .tar.gz archive at the node starting at and +streams it back to the client. + +If '-' is given for , archive is written to stdout. +Otherwise archive is extracted to which should be an empty directory or +talosctl creates a directory if doesn't exist. Command doesn't preserve +ownership and access mode for the files in extract mode, while streamed .tar archive +captures ownership and permission bits. + +``` +talm copy -| [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for copy +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/crashdump.md b/docs/reference/crashdump.md new file mode 100644 index 00000000..35cb2efb --- /dev/null +++ b/docs/reference/crashdump.md @@ -0,0 +1,36 @@ +# talm crashdump + +Dump debug information about the cluster + +``` +talm crashdump [flags] +``` + +## Options + +``` + --control-plane-nodes strings specify IPs of control plane nodes + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for crashdump + --init-node string specify IPs of init node + --worker-nodes strings specify IPs of worker nodes +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/dashboard.md b/docs/reference/dashboard.md new file mode 100644 index 00000000..b763ed18 --- /dev/null +++ b/docs/reference/dashboard.md @@ -0,0 +1,50 @@ +# talm dashboard + +Cluster dashboard with node overview, logs and real-time metrics + +## Synopsis + +Provide a text-based UI to navigate node overview, logs and real-time metrics. + +Keyboard shortcuts: + + - h, - switch one node to the left + - l, - switch one node to the right + - j, - scroll logs/process list down + - k, - scroll logs/process list up + - - scroll logs/process list half page down + - - scroll logs/process list half page up + - - scroll logs/process list one page down + - - scroll logs/process list one page up + + +``` +talm dashboard [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for dashboard + -d, --update-interval duration interval between updates (default 3s) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/debug.md b/docs/reference/debug.md new file mode 100644 index 00000000..9cfd4720 --- /dev/null +++ b/docs/reference/debug.md @@ -0,0 +1,45 @@ +# talm debug + +Run a debug container from an image archive or reference + +``` +talm debug [args] [flags] +``` + +## Examples + +``` + # Run a debug container from a local tar archive (image will be loaded into Talos from the archive) + talosctl debug ./debug-tools.tar --args /bin/sh + + # Run a debug container from an image reference (Talos will pull the image if not present) + talosctl debug docker.io/library/alpine:latest --args /bin/sh +``` + +## Options + +``` + --args strings arguments to pass to the container + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for debug + --namespace system namespace to use: system (CRI containerd) or `inmem` for in-memory containerd instance (default "inmem") +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/disks.md b/docs/reference/disks.md new file mode 100644 index 00000000..98bd247a --- /dev/null +++ b/docs/reference/disks.md @@ -0,0 +1,33 @@ +# talm disks + +Get the list of disks from /sys/block on the machine + +``` +talm disks [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for disks +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/edit.md b/docs/reference/edit.md new file mode 100644 index 00000000..73a03ff7 --- /dev/null +++ b/docs/reference/edit.md @@ -0,0 +1,46 @@ +# talm edit + +Edit Talos node machine configuration with the default editor. + +## Synopsis + +The edit command allows you to directly edit the machine configuration +of a Talos node using your preferred text editor. + +It will open the editor defined by your TALOS_EDITOR, +or EDITOR environment variables, or fall back to 'vi' for Linux +or 'notepad' for Windows. + +``` +talm edit machineconfig [flags] +``` + +## Options + +``` + --dry-run do not apply the change after editing and print the change summary instead + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for edit + -m, --mode auto, no-reboot, reboot, staged, try apply config mode (default auto) + --namespace string resource namespace (default is to use default namespace per resource) + --timeout duration the config will be rolled back after specified timeout (if try mode is selected) (default 1m0s) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/etcd.md b/docs/reference/etcd.md new file mode 100644 index 00000000..57b8566e --- /dev/null +++ b/docs/reference/etcd.md @@ -0,0 +1,38 @@ +# talm etcd + +Manage etcd + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for etcd +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! +* [talm etcd alarm](etcd_alarm.md) - Manage etcd alarms +* [talm etcd defrag](etcd_defrag.md) - Defragment etcd database on the node +* [talm etcd downgrade](etcd_downgrade.md) - Manage etcd storage system downgrades +* [talm etcd forfeit-leadership](etcd_forfeit-leadership.md) - Tell node to forfeit etcd cluster leadership +* [talm etcd leave](etcd_leave.md) - Tell nodes to leave etcd cluster +* [talm etcd members](etcd_members.md) - Get the list of etcd cluster members +* [talm etcd remove-member](etcd_remove-member.md) - Remove the node from etcd cluster +* [talm etcd snapshot](etcd_snapshot.md) - Stream snapshot of the etcd node to the path. +* [talm etcd status](etcd_status.md) - Get the status of etcd cluster member + diff --git a/docs/reference/etcd_alarm.md b/docs/reference/etcd_alarm.md new file mode 100644 index 00000000..2e5ea097 --- /dev/null +++ b/docs/reference/etcd_alarm.md @@ -0,0 +1,31 @@ +# talm etcd alarm + +Manage etcd alarms + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for alarm +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd](etcd.md) - Manage etcd +* [talm etcd alarm disarm](etcd_alarm_disarm.md) - Disarm the etcd alarms for the node. +* [talm etcd alarm list](etcd_alarm_list.md) - List the etcd alarms for the node. + diff --git a/docs/reference/etcd_alarm_disarm.md b/docs/reference/etcd_alarm_disarm.md new file mode 100644 index 00000000..ed988774 --- /dev/null +++ b/docs/reference/etcd_alarm_disarm.md @@ -0,0 +1,33 @@ +# talm etcd alarm disarm + +Disarm the etcd alarms for the node. + +``` +talm etcd alarm disarm [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for disarm +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd alarm](etcd_alarm.md) - Manage etcd alarms + diff --git a/docs/reference/etcd_alarm_list.md b/docs/reference/etcd_alarm_list.md new file mode 100644 index 00000000..fdabe509 --- /dev/null +++ b/docs/reference/etcd_alarm_list.md @@ -0,0 +1,33 @@ +# talm etcd alarm list + +List the etcd alarms for the node. + +``` +talm etcd alarm list [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for list +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd alarm](etcd_alarm.md) - Manage etcd alarms + diff --git a/docs/reference/etcd_defrag.md b/docs/reference/etcd_defrag.md new file mode 100644 index 00000000..a529971d --- /dev/null +++ b/docs/reference/etcd_defrag.md @@ -0,0 +1,38 @@ +# talm etcd defrag + +Defragment etcd database on the node + +## Synopsis + +Defragmentation is a maintenance operation that releases unused space from the etcd database file. +Defragmentation is a resource heavy operation and should be performed only when necessary on a single node at a time. + +``` +talm etcd defrag [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for defrag +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd](etcd.md) - Manage etcd + diff --git a/docs/reference/etcd_downgrade.md b/docs/reference/etcd_downgrade.md new file mode 100644 index 00000000..5c0cb9d8 --- /dev/null +++ b/docs/reference/etcd_downgrade.md @@ -0,0 +1,32 @@ +# talm etcd downgrade + +Manage etcd storage system downgrades + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for downgrade +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd](etcd.md) - Manage etcd +* [talm etcd downgrade cancel](etcd_downgrade_cancel.md) - Cancel etcd storage system downgrade. +* [talm etcd downgrade enable](etcd_downgrade_enable.md) - Enable etcd storage system downgrade to the specified version. +* [talm etcd downgrade validate](etcd_downgrade_validate.md) - Validate if the etcd storage system can be downgraded to the specified version. + diff --git a/docs/reference/etcd_downgrade_cancel.md b/docs/reference/etcd_downgrade_cancel.md new file mode 100644 index 00000000..cc8b0edb --- /dev/null +++ b/docs/reference/etcd_downgrade_cancel.md @@ -0,0 +1,33 @@ +# talm etcd downgrade cancel + +Cancel etcd storage system downgrade. + +``` +talm etcd downgrade cancel [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for cancel +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd downgrade](etcd_downgrade.md) - Manage etcd storage system downgrades + diff --git a/docs/reference/etcd_downgrade_enable.md b/docs/reference/etcd_downgrade_enable.md new file mode 100644 index 00000000..16631a60 --- /dev/null +++ b/docs/reference/etcd_downgrade_enable.md @@ -0,0 +1,33 @@ +# talm etcd downgrade enable + +Enable etcd storage system downgrade to the specified version. + +``` +talm etcd downgrade enable [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for enable +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd downgrade](etcd_downgrade.md) - Manage etcd storage system downgrades + diff --git a/docs/reference/etcd_downgrade_validate.md b/docs/reference/etcd_downgrade_validate.md new file mode 100644 index 00000000..4c929638 --- /dev/null +++ b/docs/reference/etcd_downgrade_validate.md @@ -0,0 +1,33 @@ +# talm etcd downgrade validate + +Validate if the etcd storage system can be downgraded to the specified version. + +``` +talm etcd downgrade validate [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for validate +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd downgrade](etcd_downgrade.md) - Manage etcd storage system downgrades + diff --git a/docs/reference/etcd_forfeit-leadership.md b/docs/reference/etcd_forfeit-leadership.md new file mode 100644 index 00000000..b3db5a82 --- /dev/null +++ b/docs/reference/etcd_forfeit-leadership.md @@ -0,0 +1,33 @@ +# talm etcd forfeit-leadership + +Tell node to forfeit etcd cluster leadership + +``` +talm etcd forfeit-leadership [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for forfeit-leadership +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd](etcd.md) - Manage etcd + diff --git a/docs/reference/etcd_leave.md b/docs/reference/etcd_leave.md new file mode 100644 index 00000000..b575a6a8 --- /dev/null +++ b/docs/reference/etcd_leave.md @@ -0,0 +1,33 @@ +# talm etcd leave + +Tell nodes to leave etcd cluster + +``` +talm etcd leave [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for leave +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd](etcd.md) - Manage etcd + diff --git a/docs/reference/etcd_members.md b/docs/reference/etcd_members.md new file mode 100644 index 00000000..23e22bb8 --- /dev/null +++ b/docs/reference/etcd_members.md @@ -0,0 +1,33 @@ +# talm etcd members + +Get the list of etcd cluster members + +``` +talm etcd members [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for members +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd](etcd.md) - Manage etcd + diff --git a/docs/reference/etcd_remove-member.md b/docs/reference/etcd_remove-member.md new file mode 100644 index 00000000..d499f959 --- /dev/null +++ b/docs/reference/etcd_remove-member.md @@ -0,0 +1,39 @@ +# talm etcd remove-member + +Remove the node from etcd cluster + +## Synopsis + +Use this command only if you want to remove a member which is in broken state. +If there is no access to the node, or the node can't access etcd to call etcd leave. +Always prefer etcd leave over this command. + +``` +talm etcd remove-member [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for remove-member +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd](etcd.md) - Manage etcd + diff --git a/docs/reference/etcd_snapshot.md b/docs/reference/etcd_snapshot.md new file mode 100644 index 00000000..414dd6d2 --- /dev/null +++ b/docs/reference/etcd_snapshot.md @@ -0,0 +1,33 @@ +# talm etcd snapshot + +Stream snapshot of the etcd node to the path. + +``` +talm etcd snapshot [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for snapshot +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd](etcd.md) - Manage etcd + diff --git a/docs/reference/etcd_status.md b/docs/reference/etcd_status.md new file mode 100644 index 00000000..f540a143 --- /dev/null +++ b/docs/reference/etcd_status.md @@ -0,0 +1,37 @@ +# talm etcd status + +Get the status of etcd cluster member + +## Synopsis + +Returns the status of etcd member on the node, use multiple nodes to get status of all members. + +``` +talm etcd status [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for status +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm etcd](etcd.md) - Manage etcd + diff --git a/docs/reference/events.md b/docs/reference/events.md new file mode 100644 index 00000000..eae9a429 --- /dev/null +++ b/docs/reference/events.md @@ -0,0 +1,37 @@ +# talm events + +Stream runtime events + +``` +talm events [flags] +``` + +## Options + +``` + --actor-id string filter events by the specified actor ID (default is no filter) + --duration duration show events for the past duration interval (one second resolution, default is to show no history) + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for events + --since string show events after the specified event ID (default is to show no history) + --tail int32 show specified number of past events (use -1 to show full history, default is to show no history) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/get.md b/docs/reference/get.md new file mode 100644 index 00000000..9b4bda8f --- /dev/null +++ b/docs/reference/get.md @@ -0,0 +1,42 @@ +# talm get + +Get a specific resource or list of resources (use 'talosctl get rd' to see all available resource types). + +## Synopsis + +Similar to 'kubectl get', 'talosctl get' returns a set of resources from the OS. +To get a list of all available resource definitions, issue 'talosctl get rd' + +``` +talm get [] [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for get + -i, --insecure get resources using the insecure (encrypted with no auth) maintenance service + --namespace string resource namespace (default is to use default namespace per resource) + -o, --output string output mode (json, table, yaml, jsonpath) (default "table") + -w, --watch watch resource changes +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/health.md b/docs/reference/health.md new file mode 100644 index 00000000..fc24b888 --- /dev/null +++ b/docs/reference/health.md @@ -0,0 +1,40 @@ +# talm health + +Check cluster health + +``` +talm health [flags] +``` + +## Options + +``` + --control-plane-nodes strings specify IPs of control plane nodes + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for health + --init-node string specify IPs of init node + --k8s-endpoint string use endpoint instead of kubeconfig default + --run-e2e run Kubernetes e2e test + --server run server-side check (default true) + --wait-timeout duration timeout to wait for the cluster to be ready (default 20m0s) + --worker-nodes strings specify IPs of worker nodes +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/image.md b/docs/reference/image.md new file mode 100644 index 00000000..139eff63 --- /dev/null +++ b/docs/reference/image.md @@ -0,0 +1,39 @@ +# talm image + +Manage container images + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for image + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! +* [talm image cache-cert-gen](image_cache-cert-gen.md) - Generate TLS certificates and CA patch required for securing image cache to Talos communication +* [talm image cache-create](image_cache-create.md) - Create a cache of images in OCI format into a directory +* [talm image cache-serve](image_cache-serve.md) - Serve an OCI image cache directory over HTTP(S) as a container registry +* [talm image integration](image_integration.md) - List the integration images used by k8s in Talos +* [talm image k8s-bundle](image_k8s-bundle.md) - List the default Kubernetes images used by Talos +* [talm image list](image_list.md) - List images in the machine's container runtime +* [talm image pull](image_pull.md) - Pull an image into the machine's container runtime +* [talm image remove](image_remove.md) - Remove an image from the machine's container runtime +* [talm image talos-bundle](image_talos-bundle.md) - List the default system images and extensions used for Talos + diff --git a/docs/reference/image_cache-cert-gen.md b/docs/reference/image_cache-cert-gen.md new file mode 100644 index 00000000..d3529ef8 --- /dev/null +++ b/docs/reference/image_cache-cert-gen.md @@ -0,0 +1,43 @@ +# talm image cache-cert-gen + +Generate TLS certificates and CA patch required for securing image cache to Talos communication + +## Synopsis + +Generate TLS certificates and CA patch required for securing image cache to Talos communication + +``` +talm image cache-cert-gen [flags] +``` + +## Options + +``` + --advertised-address ipSlice The addresses to advertise. (default []) + --advertised-name strings The DNS names to advertise. + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for cache-cert-gen + --tls-ca-file string TLS certificate authority file (default "ca.crt") + --tls-cert-file string TLS certificate file to use for serving (default "tls.crt") + --tls-key-file string TLS key file to use for serving (default "tls.key") +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm image](image.md) - Manage container images + diff --git a/docs/reference/image_cache-create.md b/docs/reference/image_cache-create.md new file mode 100644 index 00000000..cf2925b2 --- /dev/null +++ b/docs/reference/image_cache-create.md @@ -0,0 +1,56 @@ +# talm image cache-create + +Create a cache of images in OCI format into a directory + +## Synopsis + +Create a cache of images in OCI format into a directory + +``` +talm image cache-create [flags] +``` + +## Examples + +``` +talosctl images cache-create --images=ghcr.io/siderolabs/kubelet:v1.36.2 --image-cache-path=/tmp/talos-image-cache + +Alternatively, stdin can be piped to the command: +talosctl images default | talosctl images cache-create --image-cache-path=/tmp/talos-image-cache --images=- + +``` + +## Options + +``` + --cosign-signatures pull and cache cosign signatures for images (default true) + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + --force force overwrite of existing image cache + -h, --help help for cache-create + --image-cache-path string directory to save the image cache in OCI format + --image-layer-cache-path string directory to save the image layer cache + --images strings images to cache + --insecure allow insecure registries + --layout string Specifies the cache layout format: "oci" for an OCI image layout directory, or "flat" for a registry-like flat file structure (default "oci") + --platform strings platform(s) to cache (e.g. linux/amd64,linux/arm64), or "all" to cache every platform in the image index (default [linux/amd64]) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm image](image.md) - Manage container images + diff --git a/docs/reference/image_cache-serve.md b/docs/reference/image_cache-serve.md new file mode 100644 index 00000000..3f1a562e --- /dev/null +++ b/docs/reference/image_cache-serve.md @@ -0,0 +1,43 @@ +# talm image cache-serve + +Serve an OCI image cache directory over HTTP(S) as a container registry + +## Synopsis + +Serve an OCI image cache directory over HTTP(S) as a container registry + +``` +talm image cache-serve [flags] +``` + +## Options + +``` + --address string address to serve the registry on (default "127.0.0.1:3172") + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for cache-serve + --image-cache-path string directory to save the image cache in flat format + --mirror strings list of registry mirrors to add to the Talos config patch (default [docker.io,ghcr.io,registry.k8s.io]) + --tls-cert-file string TLS certificate file to use for serving + --tls-key-file string TLS key file to use for serving +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm image](image.md) - Manage container images + diff --git a/docs/reference/image_integration.md b/docs/reference/image_integration.md new file mode 100644 index 00000000..1c729e34 --- /dev/null +++ b/docs/reference/image_integration.md @@ -0,0 +1,37 @@ +# talm image integration + +List the integration images used by k8s in Talos + +``` +talm image integration [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for integration + --installer-tag string tag of the installer image to use + --registry-and-user string registry and user to use for the images + --talos-tag string tag of the installer image to use (default "v1.13.7") +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm image](image.md) - Manage container images + diff --git a/docs/reference/image_k8s-bundle.md b/docs/reference/image_k8s-bundle.md new file mode 100644 index 00000000..e6fd2ee9 --- /dev/null +++ b/docs/reference/image_k8s-bundle.md @@ -0,0 +1,39 @@ +# talm image k8s-bundle + +List the default Kubernetes images used by Talos + +``` +talm image k8s-bundle [flags] +``` + +## Options + +``` + --coredns-version semver CoreDNS semantic version (default v1.14.4) + --etcd-version semver ETCD semantic version (default v3.6.12) + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + --flannel-version semver Flannel CNI semantic version (default 0.28.7) + -h, --help help for k8s-bundle + --k8s-version semver Kubernetes semantic version (default v1.36.2) + --kube-network-policies-version semver kube-network-policies semantic version (default v1.1.0) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm image](image.md) - Manage container images + diff --git a/docs/reference/image_list.md b/docs/reference/image_list.md new file mode 100644 index 00000000..f1a9f7ae --- /dev/null +++ b/docs/reference/image_list.md @@ -0,0 +1,34 @@ +# talm image list + +List images in the machine's container runtime + +``` +talm image list [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for list +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm image](image.md) - Manage container images + diff --git a/docs/reference/image_pull.md b/docs/reference/image_pull.md new file mode 100644 index 00000000..0b2b323a --- /dev/null +++ b/docs/reference/image_pull.md @@ -0,0 +1,34 @@ +# talm image pull + +Pull an image into the machine's container runtime + +``` +talm image pull [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for pull +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm image](image.md) - Manage container images + diff --git a/docs/reference/image_remove.md b/docs/reference/image_remove.md new file mode 100644 index 00000000..28503e8c --- /dev/null +++ b/docs/reference/image_remove.md @@ -0,0 +1,34 @@ +# talm image remove + +Remove an image from the machine's container runtime + +``` +talm image remove [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for remove +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm image](image.md) - Manage container images + diff --git a/docs/reference/image_talos-bundle.md b/docs/reference/image_talos-bundle.md new file mode 100644 index 00000000..12046ef7 --- /dev/null +++ b/docs/reference/image_talos-bundle.md @@ -0,0 +1,36 @@ +# talm image talos-bundle + +List the default system images and extensions used for Talos + +``` +talm image talos-bundle [talos-version] [flags] +``` + +## Options + +``` + --extensions Include images that belong to Talos extensions (default true) + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for talos-bundle + --overlays Include images that belong to Talos overlays (default true) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "cri") + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm image](image.md) - Manage container images + diff --git a/docs/reference/index.md b/docs/reference/index.md new file mode 100644 index 00000000..8805de98 --- /dev/null +++ b/docs/reference/index.md @@ -0,0 +1,69 @@ +# talm + +Manage Talos the GitOps Way! + +## Options + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + -h, --help help for talm + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm apply](apply.md) - Apply config to a Talos node +* [talm bootstrap](bootstrap.md) - Bootstrap the etcd cluster on the specified node. +* [talm cgroups](cgroups.md) - Retrieve cgroups usage information +* [talm completion](completion.md) - Generate the autocompletion script for the specified shell +* [talm conformance](conformance.md) - Run conformance tests +* [talm containers](containers.md) - List containers +* [talm copy](copy.md) - Copy data out from the node +* [talm crashdump](crashdump.md) - Dump debug information about the cluster +* [talm dashboard](dashboard.md) - Cluster dashboard with node overview, logs and real-time metrics +* [talm debug](debug.md) - Run a debug container from an image archive or reference +* [talm disks](disks.md) - Get the list of disks from /sys/block on the machine +* [talm edit](edit.md) - Edit Talos node machine configuration with the default editor. +* [talm etcd](etcd.md) - Manage etcd +* [talm events](events.md) - Stream runtime events +* [talm get](get.md) - Get a specific resource or list of resources (use 'talosctl get rd' to see all available resource types). +* [talm health](health.md) - Check cluster health +* [talm image](image.md) - Manage container images +* [talm init](init.md) - Initialize a new project and generate default values +* [talm inspect](inspect.md) - Inspect internals of Talos +* [talm interfaces](interfaces.md) - List network interfaces +* [talm kubeconfig](kubeconfig.md) - Download the admin kubeconfig from the node +* [talm list](list.md) - Retrieve a directory listing +* [talm logs](logs.md) - Retrieve logs for a service +* [talm memory](memory.md) - Show memory usage +* [talm meta](meta.md) - Write and delete keys in the META partition +* [talm mounts](mounts.md) - List mounts +* [talm netstat](netstat.md) - Show network connections and sockets +* [talm pcap](pcap.md) - Capture the network packets from the node. +* [talm processes](processes.md) - List running processes +* [talm read](read.md) - Read a file on the machine +* [talm reboot](reboot.md) - Reboot a node +* [talm reset](reset.md) - Reset a node +* [talm restart](restart.md) - Restart a process +* [talm rollback](rollback.md) - Rollback a node to the previous installation +* [talm rotate-ca](rotate-ca.md) - Rotate cluster CAs (Talos and Kubernetes APIs). +* [talm routes](routes.md) - List network routes +* [talm service](service.md) - Retrieve the state of a service (or all services), control service state +* [talm shutdown](shutdown.md) - Shutdown a node +* [talm stats](stats.md) - Get container stats +* [talm support](support.md) - Dump debug information about the cluster +* [talm talosconfig](talosconfig.md) - Regenerate talosconfig with new client certificates +* [talm template](template.md) - Render templates locally and display the output +* [talm time](time.md) - Gets current server time +* [talm upgrade](upgrade.md) - Upgrade Talos on the target node +* [talm usage](usage.md) - Retrieve a disk usage +* [talm version](version.md) - Prints the version +* [talm wipe](wipe.md) - Wipe block device or volumes + diff --git a/docs/reference/init.md b/docs/reference/init.md new file mode 100644 index 00000000..438c6dfc --- /dev/null +++ b/docs/reference/init.md @@ -0,0 +1,41 @@ +# talm init + +Initialize a new project and generate default values + +``` +talm init [flags] +``` + +## Options + +``` + --cluster-endpoint string Kubernetes control-plane URL written to values.yaml::endpoint (e.g. https://10.0.0.1:6443 or https://vip.example.test:6443). Takes precedence over the single-endpoint auto-derive heuristic; required for multi-control-plane setups where the operator picks a VIP or load balancer. + -d, --decrypt decrypt all encrypted files (does not require preset) + -e, --encrypt encrypt all sensitive files (secrets.yaml, talosconfig, kubeconfig, values-secret.yaml) + --endpoints strings override default endpoints in Talos configuration + --force overwrite existing files; on --update also auto-accepts every preset-template diff without the interactive prompt + -h, --help help for init + --image string override the Talos installer image written to the preset's values.yaml (e.g. factory.talos.dev/installer/:) + -N, --name string cluster name (not required with --encrypt, --decrypt, or --update) + -p, --preset string preset for file generation (not required with --encrypt, --decrypt, or --update) + --talos-version string the desired Talos version to generate config for (backwards compatibility, e.g. v0.8) + -u, --update update Talm library chart +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/inspect.md b/docs/reference/inspect.md new file mode 100644 index 00000000..d6804426 --- /dev/null +++ b/docs/reference/inspect.md @@ -0,0 +1,30 @@ +# talm inspect + +Inspect internals of Talos + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for inspect +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! +* [talm inspect dependencies](inspect_dependencies.md) - Inspect controller-resource dependencies as graphviz graph. + diff --git a/docs/reference/inspect_dependencies.md b/docs/reference/inspect_dependencies.md new file mode 100644 index 00000000..f1062504 --- /dev/null +++ b/docs/reference/inspect_dependencies.md @@ -0,0 +1,44 @@ +# talm inspect dependencies + +Inspect controller-resource dependencies as graphviz graph. + +## Synopsis + +Inspect controller-resource dependencies as graphviz graph. + +Pipe the output of the command through the "dot" program (part of graphviz package) +to render the graph: + + talosctl inspect dependencies | dot -Tpng > graph.png + + +``` +talm inspect dependencies [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for dependencies + --with-resources display live resource information with dependencies +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm inspect](inspect.md) - Inspect internals of Talos + diff --git a/docs/reference/interfaces.md b/docs/reference/interfaces.md new file mode 100644 index 00000000..a79ac329 --- /dev/null +++ b/docs/reference/interfaces.md @@ -0,0 +1,33 @@ +# talm interfaces + +List network interfaces + +``` +talm interfaces [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for interfaces +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/kubeconfig.md b/docs/reference/kubeconfig.md new file mode 100644 index 00000000..becd38d3 --- /dev/null +++ b/docs/reference/kubeconfig.md @@ -0,0 +1,43 @@ +# talm kubeconfig + +Download the admin kubeconfig from the node + +## Synopsis + +Download the admin kubeconfig from the node. +If merge flag is true, config will be merged with ~/.kube/config. +Otherwise, kubeconfig will be written to PWD. + +``` +talm kubeconfig [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -F, --force Force overwrite of kubeconfig if already present, force overwrite on kubeconfig merge + --force-context-name string Force context name for kubeconfig merge + -h, --help help for kubeconfig + -l, --login update system kubeconfig file, not local one + -m, --merge Merge with existing kubeconfig (default true) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/list.md b/docs/reference/list.md new file mode 100644 index 00000000..41dee602 --- /dev/null +++ b/docs/reference/list.md @@ -0,0 +1,41 @@ +# talm list + +Retrieve a directory listing + +``` +talm list [path] [flags] +``` + +## Options + +``` + -d, --depth int32 maximum recursion depth (default 1) + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for list + -H, --humanize humanize size and time in the output + -l, --long display additional file details + -r, --recurse recurse into subdirectories + -t, --type strings filter by specified types: + f regular file + d directory + l, L symbolic link +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/logs.md b/docs/reference/logs.md new file mode 100644 index 00000000..4ad82c13 --- /dev/null +++ b/docs/reference/logs.md @@ -0,0 +1,36 @@ +# talm logs + +Retrieve logs for a service + +``` +talm logs [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -F, --follow specify if the logs should be streamed + -h, --help help for logs + -k, --kubernetes use the k8s.io containerd namespace + --tail int32 lines of log file to display (default is to show from the beginning) (default -1) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/memory.md b/docs/reference/memory.md new file mode 100644 index 00000000..5fae1bbe --- /dev/null +++ b/docs/reference/memory.md @@ -0,0 +1,34 @@ +# talm memory + +Show memory usage + +``` +talm memory [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for memory + -v, --verbose display extended memory statistics +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/meta.md b/docs/reference/meta.md new file mode 100644 index 00000000..35858a15 --- /dev/null +++ b/docs/reference/meta.md @@ -0,0 +1,32 @@ +# talm meta + +Write and delete keys in the META partition + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for meta + -i, --insecure write|delete meta using the insecure (encrypted with no auth) maintenance service +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! +* [talm meta delete](meta_delete.md) - Delete a key from the META partition. +* [talm meta write](meta_write.md) - Write a key-value pair to the META partition. + diff --git a/docs/reference/meta_delete.md b/docs/reference/meta_delete.md new file mode 100644 index 00000000..bf097215 --- /dev/null +++ b/docs/reference/meta_delete.md @@ -0,0 +1,34 @@ +# talm meta delete + +Delete a key from the META partition. + +``` +talm meta delete key [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for delete +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + -i, --insecure write|delete meta using the insecure (encrypted with no auth) maintenance service + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm meta](meta.md) - Write and delete keys in the META partition + diff --git a/docs/reference/meta_write.md b/docs/reference/meta_write.md new file mode 100644 index 00000000..ff5504b3 --- /dev/null +++ b/docs/reference/meta_write.md @@ -0,0 +1,34 @@ +# talm meta write + +Write a key-value pair to the META partition. + +``` +talm meta write key value [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for write +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + -i, --insecure write|delete meta using the insecure (encrypted with no auth) maintenance service + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm meta](meta.md) - Write and delete keys in the META partition + diff --git a/docs/reference/mounts.md b/docs/reference/mounts.md new file mode 100644 index 00000000..e5e3f7cc --- /dev/null +++ b/docs/reference/mounts.md @@ -0,0 +1,33 @@ +# talm mounts + +List mounts + +``` +talm mounts [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for mounts +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/netstat.md b/docs/reference/netstat.md new file mode 100644 index 00000000..49ec5bea --- /dev/null +++ b/docs/reference/netstat.md @@ -0,0 +1,55 @@ +# talm netstat + +Show network connections and sockets + +## Synopsis + +Show network connections and sockets. + +You can pass an optional argument to view a specific pod's connections. +To do this, format the argument as "namespace/pod". +Note that only pods with a pod network namespace are allowed. +If you don't pass an argument, the command will show host connections. + +``` +talm netstat [flags] +``` + +## Options + +``` + -a, --all display all sockets states (default: connected) + -x, --extend show detailed socket information + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for netstat + -4, --ipv4 display only ipv4 sockets + -6, --ipv6 display only ipv6 sockets + -l, --listening display listening server sockets + -k, --pods show sockets used by Kubernetes pods + -p, --programs show process using socket + -w, --raw display only RAW sockets + -t, --tcp display only TCP sockets + -o, --timers display timers + -u, --udp display only UDP sockets + -U, --udplite display only UDPLite sockets + -v, --verbose display sockets of all supported transport protocols +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/pcap.md b/docs/reference/pcap.md new file mode 100644 index 00000000..cc6f0cb8 --- /dev/null +++ b/docs/reference/pcap.md @@ -0,0 +1,70 @@ +# talm pcap + +Capture the network packets from the node. + +## Synopsis + +The command launches packet capture on the node and streams back the packets as raw pcap file. + +``` +talm pcap [flags] +``` + +## Examples + +``` +Default behavior is to decode the packets with internal decoder to stdout: + + talosctl pcap -i eth0 + +Raw pcap file can be saved with `--output` flag: + + talosctl pcap -i eth0 --output eth0.pcap + +Output can be piped to tcpdump: + + talosctl pcap -i eth0 -o - | tcpdump -vvv -r - + +BPF filter can be applied, but it has to compiled to BPF instructions first using tcpdump. +Correct link type should be specified for the tcpdump: EN10MB for Ethernet links and RAW +for e.g. Wireguard tunnels: + + talosctl pcap -i eth0 --bpf-filter "$(tcpdump -dd -y EN10MB 'tcp and dst port 80')" + + talosctl pcap -i kubespan --bpf-filter "$(tcpdump -dd -y RAW 'port 50000')" + +As packet capture is transmitted over the network, it is recommended to filter out the Talos API traffic, +e.g. by excluding packets with the port 50000. + +``` + +## Options + +``` + --bpf-filter string bpf filter to apply, tcpdump -dd format + --duration duration duration of the capture + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for pcap + -i, --interface string interface name to capture packets on (default "eth0") + -o, --output string if not set, decode packets to stdout; if set write raw pcap data to a file, use '-' for stdout + --promiscuous put interface into promiscuous mode +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/processes.md b/docs/reference/processes.md new file mode 100644 index 00000000..4f523922 --- /dev/null +++ b/docs/reference/processes.md @@ -0,0 +1,34 @@ +# talm processes + +List running processes + +``` +talm processes [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for processes + -s, --sort string Column to sort output by. [rss|cpu] (default "rss") +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/read.md b/docs/reference/read.md new file mode 100644 index 00000000..08767e62 --- /dev/null +++ b/docs/reference/read.md @@ -0,0 +1,33 @@ +# talm read + +Read a file on the machine + +``` +talm read [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for read +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/reboot.md b/docs/reference/reboot.md new file mode 100644 index 00000000..5db98428 --- /dev/null +++ b/docs/reference/reboot.md @@ -0,0 +1,40 @@ +# talm reboot + +Reboot a node + +``` +talm reboot [flags] +``` + +## Options + +``` + --debug debug operation from kernel logs. --wait is set to true when this flag is set + --drain drain the Kubernetes node before rebooting (cordon + evict pods) + --drain-timeout duration timeout for draining the Kubernetes node (default 5m0s) + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for reboot + -m, --mode string select the reboot mode during upgrade. Mode "powercycle" bypasses kexec. Values: [default force powercycle] (default "default") + --progress string output mode for upgrade progress. Values: [auto plain] (default "auto") + --timeout duration time to wait for the operation is complete if --debug or --wait is set (default 30m0s) + --wait wait for the operation to complete, tracking its progress. always set to true when --debug is set (default true) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/reset.md b/docs/reference/reset.md new file mode 100644 index 00000000..51c64b47 --- /dev/null +++ b/docs/reference/reset.md @@ -0,0 +1,42 @@ +# talm reset + +Reset a node + +``` +talm reset [flags] +``` + +## Options + +``` + --debug debug operation from kernel logs. --wait is set to true when this flag is set + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + --graceful if true, attempt to cordon/drain node and leave etcd (if applicable) (default true) + -h, --help help for reset + --insecure reset using the insecure (encrypted with no auth) maintenance service + --reboot if true, reboot the node after resetting instead of shutting down + --system-labels-to-wipe strings wipe selected system disk partitions by label, keeping others intact (talm default when no wipe flag is set: STATE,EPHEMERAL) + --timeout duration time to wait for the operation is complete if --debug or --wait is set (default 30m0s) + --user-disks-to-wipe strings if set, wipes defined devices in the list + --wait wait for the operation to complete, tracking its progress. always set to true when --debug is set (default true) + --wipe-mode all, system-disk, user-disks disk reset mode (talm default: --system-labels-to-wipe=STATE,EPHEMERAL preserves META so the node self-recovers; pass --wipe-mode=all or --wipe-mode=system-disk explicitly for upstream's destructive behaviour — both destroy META) (default all) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/restart.md b/docs/reference/restart.md new file mode 100644 index 00000000..01dbb3c6 --- /dev/null +++ b/docs/reference/restart.md @@ -0,0 +1,34 @@ +# talm restart + +Restart a process + +``` +talm restart [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for restart + -k, --kubernetes use the k8s.io containerd namespace +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/rollback.md b/docs/reference/rollback.md new file mode 100644 index 00000000..d6865565 --- /dev/null +++ b/docs/reference/rollback.md @@ -0,0 +1,33 @@ +# talm rollback + +Rollback a node to the previous installation + +``` +talm rollback [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for rollback +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/rotate-ca.md b/docs/reference/rotate-ca.md new file mode 100644 index 00000000..85b21f2e --- /dev/null +++ b/docs/reference/rotate-ca.md @@ -0,0 +1,80 @@ +# talm rotate-ca + +Rotate cluster CAs (Talos and Kubernetes APIs). + +## Synopsis + +Rotates Talos and/or Kubernetes root Certificate Authorities. + +This command must be run against a SINGLE control-plane node. The specified node +will be used to coordinate the CA rotation across the entire cluster. + +The command works by: +1. Auto-discovering all cluster nodes (control-plane and workers) from Kubernetes API +2. Generating new CA certificates +3. Gracefully rolling out the new CAs to all nodes +4. Updating local configs (talosconfig, secrets.yaml, kubeconfig) + +IMPORTANT: You must specify exactly ONE control-plane node via --endpoints/-e or --nodes +flags, or through a single config file (-f). The node must be a control-plane node. + +By default, both Talos API CA and Kubernetes API CA are rotated. Use --talos=false +or --kubernetes=false to rotate only one of them. + +The command runs in dry-run mode by default. Use --dry-run=false to perform actual rotation. + +``` +talm rotate-ca [flags] +``` + +## Examples + +``` + # Dry-run CA rotation (recommended first step) + talm rotate-ca -f nodes/controlplane-1.yaml + + # Actually perform the rotation + talm rotate-ca -f nodes/controlplane-1.yaml --dry-run=false + + # Rotate only Talos API CA + talm rotate-ca -f nodes/controlplane-1.yaml --kubernetes=false --dry-run=false + + # Rotate only Kubernetes API CA + talm rotate-ca -f nodes/controlplane-1.yaml --talos=false --dry-run=false +``` + +## Options + +``` + --control-plane-nodes strings specify IPs of control plane nodes + --dry-run dry-run mode (no changes to the cluster) (default true) + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for rotate-ca + --init-node string specify IPs of init node + --k8s-endpoint string use endpoint instead of kubeconfig default + --kubernetes rotate Kubernetes API CA (default true) + -o, --output talosconfig path to the output new talosconfig (default "talosconfig") + --talos rotate Talos API CA (default true) + --with-docs patch all machine configs adding the documentation for each field + --with-examples patch all machine configs with the commented examples + --worker-nodes strings specify IPs of worker nodes +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/routes.md b/docs/reference/routes.md new file mode 100644 index 00000000..35bdf2b8 --- /dev/null +++ b/docs/reference/routes.md @@ -0,0 +1,33 @@ +# talm routes + +List network routes + +``` +talm routes [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for routes +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/service.md b/docs/reference/service.md new file mode 100644 index 00000000..00f6a8ba --- /dev/null +++ b/docs/reference/service.md @@ -0,0 +1,39 @@ +# talm service + +Retrieve the state of a service (or all services), control service state + +## Synopsis + +Service control command. If run without arguments, lists all the services and their state. +If service ID is specified, default action 'status' is executed which shows status of a single list service. +With actions 'start', 'stop', 'restart', service state is updated respectively. + +``` +talm service [ [start|stop|restart|status]] [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for service +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/shutdown.md b/docs/reference/shutdown.md new file mode 100644 index 00000000..c2fa25d4 --- /dev/null +++ b/docs/reference/shutdown.md @@ -0,0 +1,37 @@ +# talm shutdown + +Shutdown a node + +``` +talm shutdown [flags] +``` + +## Options + +``` + --debug debug operation from kernel logs. --wait is set to true when this flag is set + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + --force if true, force a node to shutdown without a cordon/drain + -h, --help help for shutdown + --timeout duration time to wait for the operation is complete if --debug or --wait is set (default 30m0s) + --wait wait for the operation to complete, tracking its progress. always set to true when --debug is set (default true) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/stats.md b/docs/reference/stats.md new file mode 100644 index 00000000..ca7f8afd --- /dev/null +++ b/docs/reference/stats.md @@ -0,0 +1,34 @@ +# talm stats + +Get container stats + +``` +talm stats [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for stats + -k, --kubernetes use the k8s.io containerd namespace +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/support.md b/docs/reference/support.md new file mode 100644 index 00000000..4886f669 --- /dev/null +++ b/docs/reference/support.md @@ -0,0 +1,58 @@ +# talm support + +Dump debug information about the cluster + +## Synopsis + +Generated bundle contains the following debug information: + +- For each node: + + - Kernel logs. + - All Talos internal services logs. + - All kube-system pods logs. + - Talos COSI resources without secrets. + - COSI runtime state graph. + - Processes snapshot. + - IO pressure snapshot. + - Mounts list. + - PCI devices info. + - Talos version. + +- For the cluster: + + - Kubernetes nodes and kube-system pods manifests. + + +``` +talm support [flags] +``` + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for support + -w, --num-workers int number of workers per node (default 1) + -O, --output string output file to write support archive to + -v, --verbose verbose output +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/talosconfig.md b/docs/reference/talosconfig.md new file mode 100644 index 00000000..a3c7a270 --- /dev/null +++ b/docs/reference/talosconfig.md @@ -0,0 +1,44 @@ +# talm talosconfig + +Regenerate talosconfig with new client certificates + +## Synopsis + +Regenerate talosconfig from secrets.yaml with fresh client certificates. + +This command: +1. Decrypts talosconfig if encrypted version exists +2. Regenerates client certificates from secrets.yaml +3. Preserves endpoints and nodes from existing config +4. Re-encrypts if encryption is used + +Use this command when your client certificate has expired. + +``` +talm talosconfig [flags] +``` + +## Options + +``` + -h, --help help for talosconfig +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/template.md b/docs/reference/template.md new file mode 100644 index 00000000..8c466164 --- /dev/null +++ b/docs/reference/template.md @@ -0,0 +1,61 @@ +# talm template + +Render templates locally and display the output + +## Synopsis + +Render Talos configuration templates locally. + +Multi-file invocation note: unlike `talm apply` (where the first -f +anchors and later -f files are stacked side-patches), +`talm template -f a.yaml -f b.yaml -f c.yaml` renders each file +independently driven by its own modeline. This is intentional — +template's per-file render mirrors the "regenerate the artifact +beside the source" workflow, while apply's chain models "compose a +single MachineConfig and apply it once". + +``` +talm template [flags] +``` + +## Options + +``` + --debug show only rendered patches + -f, --file .yaml node config files for in-place update (.yaml / `.yml`; shell completion narrows to these extensions). Each file's modeline drives the per-file render. + --full show full resulting config, not only patch + -h, --help help for template + -I, --in-place re-template and update generated files in place (overwrite them) + -i, --insecure template using the insecure (encrypted with no auth) maintenance service + --kubernetes-version string desired kubernetes version to run (default "1.36.2") + --offline disable gathering information and lookup functions + --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). For IP / CIDR / version literals use --set-string — dots in --set values are interpreted as YAML key nesting. + --set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2) + --set-json stringArray set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2) + --set-literal stringArray set a literal STRING value on the command line + --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Use for IP addresses, CIDR blocks, version strings, or any literal value where dots must NOT be interpreted as YAML key nesting. + --show-secrets print values from encrypted value files (*.encrypted.yaml) verbatim in stdout output (default: redacted to ***; never affects -I, which always omits them). Counterpart on apply is --show-secrets-in-drift, which governs the same values in apply's drift preview. + --talos-version string the desired Talos version to generate config for (backwards compatibility, e.g. v0.8) + -t, --template strings specify templates to render manifest from (can specify multiple) + --values strings specify values in a YAML file (can specify multiple) + --with-secrets string use a secrets file generated using 'gen secrets' +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/time.md b/docs/reference/time.md new file mode 100644 index 00000000..40ac86ba --- /dev/null +++ b/docs/reference/time.md @@ -0,0 +1,34 @@ +# talm time + +Gets current server time + +``` +talm time [--check server] [flags] +``` + +## Options + +``` + --check string checks server time against specified ntp server + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for time +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/upgrade.md b/docs/reference/upgrade.md new file mode 100644 index 00000000..97beb6d4 --- /dev/null +++ b/docs/reference/upgrade.md @@ -0,0 +1,77 @@ +# talm upgrade + +Upgrade Talos on the target node + +## Synopsis + +Upgrade Talos on the target node(s). + +Image resolution (when -f is provided): + - --image takes precedence and is used as-is. + - otherwise, talm reads `image:` from values.yaml at the + project root and passes it as the upgrade target. Bumping + values.yaml::image is the canonical "raise the cluster's + Talos version" workflow — re-running `talm template` to + refresh node files first is NOT required. + +The first -f file anchors the project root (Chart.yaml + +secrets.yaml); its modeline supplies the nodes / endpoints. The +node body's machine.install.image is no longer consulted by the +upgrade flow. + +Post-upgrade sync (when the upgrade succeeds): + - talm point-patches machine.install.image in every -f node body + to the image that was applied. Keeps the body consistent with + the running node — without this a follow-up `talm apply` would + merge the stale install.image over the chart-rendered new value + and silently pin the cluster back to the pre-upgrade image on + the next A/B boot. Comments, modeline, and unrelated keys are + preserved (yaml.v3 node round-trip); files without an + install.image key (orphans / side-patches) are silently skipped. + - The patch fires after post-upgrade verify confirms the running + version matches the target. A failed verify (auto-rollback) + intentionally leaves the body untouched, so it still reflects + what the node actually runs. + +``` +talm upgrade [flags] +``` + +## Options + +``` + --debug debug operation from kernel logs. --wait is set to true when this flag is set + --drain drain the Kubernetes node before rebooting (cordon + evict pods) (default true) + --drain-timeout duration timeout for draining the Kubernetes node (default 5m0s) + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for upgrade + -i, --image string the container image to use for performing the install (default "ghcr.io/siderolabs/installer:v1.13.7") + --legacy force use of legacy upgrade method + --namespace string namespace to use: "system" (etcd and kubelet images), "cri" for all Kubernetes workloads, "inmem" for in-memory containerd instance (default "system") + --no-reboot do not reboot the node after upgrade (skip reboot and drain) + --post-upgrade-reconcile-window duration how long to wait after upgrade returns before re-reading the running version; widen for slow hardware / large image pulls (default 1m30s) + --progress string output mode for upgrade progress. Values: [auto plain] (default "auto") + -m, --reboot-mode string select the reboot mode during upgrade. Mode "powercycle" bypasses kexec. Values: [default force powercycle] (default "default") + --skip-post-upgrade-verify skip the post-upgrade check that compares running Talos version against the target image's tag (detects silent A/B rollback after the RPC acks success) + --timeout duration time to wait for the operation is complete if --debug or --wait is set (default 30m0s) + --wait wait for the operation to complete, tracking its progress. always set to true when --debug is set (default true) +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/usage.md b/docs/reference/usage.md new file mode 100644 index 00000000..658c0da7 --- /dev/null +++ b/docs/reference/usage.md @@ -0,0 +1,37 @@ +# talm usage + +Retrieve a disk usage + +``` +talm usage [path1] [path2] ... [pathN] [flags] +``` + +## Options + +``` + -a, --all write counts for all files, not just directories + -d, --depth int32 maximum recursion depth + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for usage + -H, --humanize humanize size and time in the output + -t, --threshold int threshold exclude entries smaller than SIZE if positive, or entries greater than SIZE if negative +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/version.md b/docs/reference/version.md new file mode 100644 index 00000000..5c10dfd2 --- /dev/null +++ b/docs/reference/version.md @@ -0,0 +1,36 @@ +# talm version + +Prints the version + +``` +talm version [flags] +``` + +## Options + +``` + --client Print client version only + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for version + -i, --insecure use Talos maintenance mode API + --short Print the short version +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! + diff --git a/docs/reference/wipe.md b/docs/reference/wipe.md new file mode 100644 index 00000000..59098f9e --- /dev/null +++ b/docs/reference/wipe.md @@ -0,0 +1,30 @@ +# talm wipe + +Wipe block device or volumes + +## Options + +``` + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for wipe +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm](index.md) - Manage Talos the GitOps Way! +* [talm wipe disk](wipe_disk.md) - Wipe a block device (disk or partition) which is not used as a volume + diff --git a/docs/reference/wipe_disk.md b/docs/reference/wipe_disk.md new file mode 100644 index 00000000..814e8bf4 --- /dev/null +++ b/docs/reference/wipe_disk.md @@ -0,0 +1,42 @@ +# talm wipe disk + +Wipe a block device (disk or partition) which is not used as a volume + +## Synopsis + +Wipe a block device (disk or partition) which is not used as a volume. + +Use device names as arguments, for example: vda or sda5. + +``` +talm wipe disk ... [flags] +``` + +## Options + +``` + --drop-partition drop partition after wipe (if applicable) + -f, --file strings specify config files or patches in a YAML file (can specify multiple) + -h, --help help for disk + -i, --insecure use Talos maintenance mode API + --method string wipe method to use [FAST ZEROES] (default "FAST") +``` + +## Options inherited from parent commands + +``` + --cluster string Cluster to connect to if a proxy endpoint is used. + --context string Context to be used in command + -e, --endpoints strings override default endpoints in Talos configuration + --nodes strings target the specified nodes + --root string root directory of the project (default ".") + --skip-verify skip TLS certificate verification (keeps client authentication) + --strict-charts fail if the project's vendored charts/talm/ or pinned preset baseline differs from the talm binary (run talm init --update --preset to re-sync) + --talosconfig string The path to the Talos configuration file. Defaults to 'TALOSCONFIG' env variable if set, otherwise '$HOME/.talos/config' and '/var/run/secrets/talos.dev/config' in order. + --version Print the version number of the application +``` + +## SEE ALSO + +* [talm wipe](wipe.md) - Wipe block device or volumes + diff --git a/docs_reference_test.go b/docs_reference_test.go new file mode 100644 index 00000000..0872e1f3 --- /dev/null +++ b/docs_reference_test.go @@ -0,0 +1,254 @@ +// Copyright Cozystack Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "runtime" + "sort" + "strings" + "testing" + + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" +) + +// referenceDir is the published CLI reference, rendered from the cobra +// command tree and committed so the docs site can build without a Go +// toolchain. +const referenceDir = "docs/reference" + +// updateReference reports whether to rewrite the committed reference +// instead of comparing against it. Mirrors TALM_UPDATE_GOLDEN in +// pkg/engine: +// +// TALM_UPDATE_DOCS=1 go test . -run TestReferenceDocs +func updateReference() bool { + return os.Getenv("TALM_UPDATE_DOCS") != "" +} + +// referencePage maps a cobra command path to the page that documents it. +// "talm" is the site's reference index; everything below it drops the +// binary name, so `talm etcd status` lands at etcd_status.md and is +// served from /reference/etcd_status/. +func referencePage(commandPath string) string { + trimmed := strings.TrimPrefix(commandPath, "talm") + trimmed = strings.TrimSpace(trimmed) + if trimmed == "" { + return "index.md" + } + + return strings.ReplaceAll(trimmed, " ", "_") + ".md" +} + +// referenceLink rewrites the cross-references cobra emits under SEE ALSO +// (talm_etcd_status.md) into the page names used here. +func referenceLink(name string) string { + return referencePage(strings.ReplaceAll(strings.TrimSuffix(name, ".md"), "_", " ")) +} + +// renderReference walks the command tree and returns page name -> content. +// +// It renders each command with doc.GenMarkdownCustom rather than calling +// doc.GenMarkdownTree, which hardcodes both the file names and an opening +// H2. MkDocs takes a page's title from its first H1 and falls back to the +// file name, so the heading is promoted here. +func renderReference(root *cobra.Command) (map[string]string, error) { + pages := map[string]string{} + + var walk func(*cobra.Command) error + walk = func(cmd *cobra.Command) error { + // Cobra only propagates this from a parent inside its SEE ALSO + // branch. Without it every command stamps the current date into + // its page and no two runs ever agree. + cmd.DisableAutoGenTag = true + + buf := &bytes.Buffer{} + if err := doc.GenMarkdownCustom(cmd, buf, referenceLink); err != nil { + return fmt.Errorf("render %s: %w", cmd.CommandPath(), err) + } + + pages[referencePage(cmd.CommandPath())] = promoteHeadings(buf.String()) + + for _, child := range cmd.Commands() { + if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() { + continue + } + if err := walk(child); err != nil { + return err + } + } + + return nil + } + + if err := walk(root); err != nil { + return nil, err + } + + return pages, nil +} + +// cobraHeadings are the section headings doc.GenMarkdownCustom emits. It +// opens a page at H2 and puts every section under it at H3, which leaves +// MkDocs with no H1 to title the page from and a table of contents that +// starts one level too deep. Promote the whole document by one level. +// +//nolint:gochecknoglobals // immutable lookup table read by promoteHeadings. +var cobraHeadings = []string{ + "### Synopsis", + "### Examples", + "### Options", + "### Options inherited from parent commands", + "### SEE ALSO", +} + +func promoteHeadings(body string) string { + body = strings.Replace(body, "## ", "# ", 1) + + for _, heading := range cobraHeadings { + body = strings.ReplaceAll(body, "\n"+heading+"\n", "\n"+heading[1:]+"\n") + } + + return body +} + +// referenceRoot returns the command tree as an operator sees it. +func referenceRoot(t *testing.T) *cobra.Command { + t.Helper() + + // Persistent flags supply the "Options inherited from parent commands" + // section of every page. registerRootFlags is single-call by contract + // (pflag panics on a redefined flag), and rootCmd is a package global + // that survives between tests, so guard on a flag it registers rather + // than calling it blind — otherwise `go test -count=2` panics. + if rootCmd.PersistentFlags().Lookup("talosconfig") == nil { + registerRootFlags(rootCmd) + } + + // Cobra builds `completion` lazily inside Execute(), so it is absent + // from the tree a test walks. Operators have it, so document it. The + // call is idempotent: it returns early once the command exists. + rootCmd.InitDefaultCompletionCmd() + + return rootCmd +} + +// TestReferenceDocs pins docs/reference/ to the cobra command tree, so +// adding a command — including one inherited from a Talos bump, since talm +// wraps talosctl's commands — fails here until the reference is +// regenerated. Cobra's own `help` command is not documented: +// IsAvailableCommand reports false for it, so both the walk here and +// cobra's SEE ALSO loop skip it. +func TestReferenceDocs(t *testing.T) { + // Flag defaults are built with filepath.Join (the --talosconfig + // default among them), so the rendered pages carry backslashes on + // Windows and a byte comparison fails for reasons unrelated to + // drift. Linux CI is what enforces freshness. + if runtime.GOOS == "windows" { + t.Skip("reference pages embed OS-specific path separators; generated and verified on Linux") + } + + pages, err := renderReference(referenceRoot(t)) + if err != nil { + t.Fatalf("render reference: %v", err) + } + + if updateReference() { + writeReference(t, pages) + + return + } + + compareReference(t, pages) +} + +func writeReference(t *testing.T, pages map[string]string) { + t.Helper() + + existing, err := filepath.Glob(filepath.Join(referenceDir, "*.md")) + if err != nil { + t.Fatalf("list reference dir: %v", err) + } + + for _, path := range existing { + if _, kept := pages[filepath.Base(path)]; !kept { + if err := os.Remove(path); err != nil { + t.Fatalf("remove stale page %s: %v", path, err) + } + } + } + + if err := os.MkdirAll(referenceDir, 0o755); err != nil { + t.Fatalf("create reference dir: %v", err) + } + + for name, body := range pages { + if err := os.WriteFile(filepath.Join(referenceDir, name), []byte(body), 0o644); err != nil { + t.Fatalf("write %s: %v", name, err) + } + } +} + +func compareReference(t *testing.T, pages map[string]string) { + t.Helper() + + const regenerate = "regenerate with: TALM_UPDATE_DOCS=1 go test . -run TestReferenceDocs" + + onDisk, err := filepath.Glob(filepath.Join(referenceDir, "*.md")) + if err != nil { + t.Fatalf("list reference dir: %v", err) + } + + seen := map[string]bool{} + + for _, path := range onDisk { + name := filepath.Base(path) + seen[name] = true + + want, documented := pages[name] + if !documented { + t.Errorf("%s documents a command that no longer exists — %s", path, regenerate) + + continue + } + + got, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read %s: %v", path, err) + } + + if string(got) != want { + t.Errorf("%s differs from the command tree — %s", path, regenerate) + } + } + + missing := []string{} + + for name := range pages { + if !seen[name] { + missing = append(missing, name) + } + } + + sort.Strings(missing) + + if len(missing) > 0 { + t.Errorf("%d command(s) have no page: %s — %s", len(missing), strings.Join(missing, ", "), regenerate) + } +} diff --git a/go.mod b/go.mod index 20853e02..eb320261 100644 --- a/go.mod +++ b/go.mod @@ -141,6 +141,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.7.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/creack/pty v1.1.24 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dlclark/regexp2 v1.11.5 // indirect diff --git a/go.sum b/go.sum index e79cb7ba..f9f14b76 100644 --- a/go.sum +++ b/go.sum @@ -129,6 +129,8 @@ github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7 github.com/cosi-project/runtime v1.16.2 h1:sgjOMrnaElrja93kkJJJIQYwd45PhpGl9cBci9yqn5c= github.com/cosi-project/runtime v1.16.2/go.mod h1:+GrSnmJjMfWMe6NubevwwXQf/v7afddDLeCbLonvvps= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= diff --git a/main.go b/main.go index bca54afb..27bee52e 100644 --- a/main.go +++ b/main.go @@ -101,8 +101,10 @@ func main() { // Extracted from Execute so tests can exercise the registration // without running cobra's executor. Single-call contract: cobra // panics on duplicate flag registration, so production calls this -// exactly once from Execute; tests must build a fresh -// *cobra.Command for each invocation. +// exactly once from Execute. A test must either pass a fresh +// *cobra.Command or, when it needs rootCmd itself, check first +// whether the flags are already on it — rootCmd is a package global +// and survives across tests and across `go test -count=N`. func registerRootFlags(cmd *cobra.Command) { cmd.PersistentFlags().StringVar( &commands.GlobalArgs.Talosconfig, From 1223e102de5dcf6c7433a824fb838275ba9c1e89 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Sun, 6 Sep 2026 22:58:24 +0000 Subject: [PATCH 2/3] docs: publish the manual as a documentation site MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The README carried the entire manual: 459 lines covering everything from installing the binary to age-encrypted user values, in one flat page with no navigation, no search and no way to link a reader to a single topic. Sections had grown into each other — the getting-started walk had 46 lines of format reference and a 1000-word block on apply-time gates wedged between "gather node information" and "apply config". Split it across pages at those seams and build the result with MkDocs Material, deployed to talm.cozystack.io by GitHub Pages. The prose is moved, not rewritten; the parts that change are heading levels, the one cross-reference that pointed at a section now on another page, and blockquotes that carried warnings, which become admonitions. The README keeps the pitch, the features and the install instructions, and links out for the rest. mkdocs.yml raises MkDocs' anchor, link and nav validation to warnings so that `--strict` fails on a cross-reference lost in a future split rather than shipping it. Both the deploy and the pull-request check build with that flag; the pull-request check carries no paths filter, since a workflow skipped by one stays Pending forever and could never be a required check. The test pinning the post-upgrade reconcile window against a hardcoded 90s followed its subject out of the README and now reads the page that documents it. Assisted-by: LLM Signed-off-by: Aleksei Sviridkin --- .github/workflows/docs-validate.yaml | 49 ++ .github/workflows/docs.yaml | 78 +++ .gitignore | 3 + README.md | 429 +------------- docs/.nav.yml | 22 + docs/assets/favicon.svg | 1 + docs/assets/logo.svg | 1 + docs/configuration/encryption.md | 86 +++ docs/configuration/endpoints-and-vips.md | 28 + docs/configuration/node-files.md | 80 +++ docs/configuration/talos-versions.md | 44 ++ docs/configuration/templates.md | 43 ++ docs/getting-started/init.md | 45 ++ docs/getting-started/installation.md | 21 + docs/getting-started/quickstart.md | 80 +++ docs/index.md | 87 +++ docs/operations/safety-gates.md | 52 ++ docs/operations/side-patches.md | 24 + docs/operations/talosctl-commands.md | 43 ++ docs/operations/upgrading.md | 54 ++ docs/stylesheets/extra.css | 31 + mkdocs.yml | 156 +++++ pkg/commands/upgrade_handler_test.go | 23 +- requirements-docs.in | 20 + requirements-docs.txt | 688 +++++++++++++++++++++++ 25 files changed, 1763 insertions(+), 425 deletions(-) create mode 100644 .github/workflows/docs-validate.yaml create mode 100644 .github/workflows/docs.yaml create mode 100644 docs/.nav.yml create mode 100644 docs/assets/favicon.svg create mode 100644 docs/assets/logo.svg create mode 100644 docs/configuration/encryption.md create mode 100644 docs/configuration/endpoints-and-vips.md create mode 100644 docs/configuration/node-files.md create mode 100644 docs/configuration/talos-versions.md create mode 100644 docs/configuration/templates.md create mode 100644 docs/getting-started/init.md create mode 100644 docs/getting-started/installation.md create mode 100644 docs/getting-started/quickstart.md create mode 100644 docs/index.md create mode 100644 docs/operations/safety-gates.md create mode 100644 docs/operations/side-patches.md create mode 100644 docs/operations/talosctl-commands.md create mode 100644 docs/operations/upgrading.md create mode 100644 docs/stylesheets/extra.css create mode 100644 mkdocs.yml create mode 100644 requirements-docs.in create mode 100644 requirements-docs.txt diff --git a/.github/workflows/docs-validate.yaml b/.github/workflows/docs-validate.yaml new file mode 100644 index 00000000..0a4a5307 --- /dev/null +++ b/.github/workflows/docs-validate.yaml @@ -0,0 +1,49 @@ +name: Documentation Validation + +# No paths filter, deliberately. A workflow skipped by a paths filter stays in +# a Pending check, and a merge blocked on a required check that never reports +# is blocked forever — so a filtered workflow can never be a required check at +# all. This build is the only thing that sees a relative link or an anchor +# inside docs/, so it has to be able to block. The cost is well under a minute +# on a Go-only change. +on: + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + validate: + name: Validate documentation + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # git-revision-date-localized runs in the build below and reads each + # page's last commit; a shallow clone has none. + fetch-depth: 0 + + - name: Setup Python + uses: actions/setup-python@v7 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-docs.txt + + - name: Install dependencies + run: pip install --requirement requirements-docs.txt + + # The site only builds for real on a push to main, where a failure lands + # on the published documentation. Build it here too: relative links and + # anchors inside docs/ are checked by this and nothing else. + # + # --quiet must never be added: --strict fails on the warning COUNT and + # --quiet suppresses the warnings before anything counts them, so the two + # together report success while checking nothing. + - name: Build documentation + run: mkdocs build --strict diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 00000000..50bd05dd --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,78 @@ +name: Documentation + +on: + push: + branches: + - main + paths: + - "docs/**" + - "mkdocs.yml" + - "requirements-docs.in" + - "requirements-docs.txt" + - ".github/workflows/docs.yaml" + workflow_dispatch: + +permissions: + contents: read + +# Never cancel a deploy mid-flight: the site is replaced wholesale, so a +# cancelled run can leave the artifact half-uploaded. Queue instead. +concurrency: + group: pages + cancel-in-progress: false + +jobs: + deploy: + name: Deploy documentation + runs-on: ubuntu-latest + permissions: + contents: read + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + # git-revision-date-localized reads each page's last commit for the + # footer date; a shallow clone has no history to read it from. + fetch-depth: 0 + + - name: Setup Python + uses: actions/setup-python@v7 + with: + python-version: "3.14" + cache: pip + cache-dependency-path: requirements-docs.txt + + # Provisions the Pages site when the repository has none yet, so the + # deploy below does not fail on a repository where Pages was never + # switched on. Idempotent once it exists. The custom domain is not + # expressible here and has to be set in the repository settings. + - name: Configure Pages + uses: actions/configure-pages@v6 + with: + enablement: true + + - name: Install dependencies + run: pip install --requirement requirements-docs.txt + + # --strict fails the build on warnings; the validation block in + # mkdocs.yml is what makes a dead anchor, an unrecognized link and a page + # missing from the nav warnings at all. Both halves are needed. + - name: Build documentation + run: mkdocs build --strict + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v5 + with: + path: site + + # Unlike a gh-pages branch push, this waits on the Pages deployment + # itself and fails if it does not converge, so a stalled deploy turns + # this job red instead of leaving a stale site behind a green run. + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 diff --git a/.gitignore b/.gitignore index d3d615ee..6775c908 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ talm dist/ .claude/ + +# MkDocs build output +/site/ diff --git a/README.md b/README.md index aa923c0e..21445cf6 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ While developing Talm, we aimed to achieve the following goals: - **GitOps Friendly**: The patches generated do not contain sensitive data, allowing them to be stored in Git in an unencrypted, open format. For scenarios requiring complete configurations, the `--full` option allows the obtain a complete config that can be used for matchbox and other solutions. -- **Simplicity of Use**: You no longer need to pass connection options for each specific server; they are saved along with the templating results into a separate file. Per-node configuration sits in a single modeline-annotated `nodes/.yaml`; the first `-f` file is the anchor and any subsequent `-f` files stack onto its rendered config as side-patches (see "Apply with side-patches" below). +- **Simplicity of Use**: You no longer need to pass connection options for each specific server; they are saved along with the templating results into a separate file. Per-node configuration sits in a single modeline-annotated `nodes/.yaml`; the first `-f` file is the anchor and any subsequent `-f` files stack onto its rendered config as side-patches (see [Applying with side-patches](https://talm.cozystack.io/operations/side-patches/)). - **Compatibility with talosctl**: We strive to maintain compatibility with the upstream project in patches and configurations. The configurations you obtain can be used with the official tools like talosctl and Omni. @@ -42,418 +42,21 @@ curl -sSL https://github.com/cozystack/talm/raw/refs/heads/main/hack/install.sh Windows is supported. Download the `talm-windows-*.zip` archive from the [releases page](https://github.com/cozystack/talm/releases/latest) and extract `talm.exe`. On Windows, template paths passed to the `-t` / `--template` flag accept either `\` or `/` separators, so `-t templates\controlplane.yaml` and `-t templates/controlplane.yaml` are equivalent. Other path flags (`--talosconfig`, `-f` / `--file`) are delegated to the underlying OS file loader and follow standard Windows path rules. -## Getting Started +## Documentation -Create new project -```bash -mkdir newcluster -cd newcluster -talm init -p cozystack -N myawesomecluster -``` - -`talm init` refuses to run when the current directory is inside an existing talm project (it would otherwise walk up and partially overwrite the parent). To create a project under the current directory anyway — e.g. a sub-project nested inside another talm project — pass `--root .` explicitly. To re-initialise the parent itself, run `talm init` from the parent directory. - -To pin a specific Talos installer image at init time (e.g. a [Talos Factory](https://factory.talos.dev/) image with extensions), pass `--image`: - -```bash -talm init -p cozystack -N myawesomecluster --image factory.talos.dev/installer/: -``` - -`--image` rewrites the top-level `image:` field in the preset's `values.yaml` before write. The flag is honored on initial `init` only — for an existing project, edit `values.yaml` directly. The `cozystack` preset declares `image:`; the `generic` preset does not, so `--image --preset generic` is rejected up front. - -To set the Kubernetes control-plane URL at init time, pass `--cluster-endpoint`: - -```bash -talm init -p cozystack -N myawesomecluster --cluster-endpoint https://vip.example.test:6443 -``` - -`--cluster-endpoint` writes the URL into `values.yaml::endpoint`, which the chart renders into `cluster.controlPlane.endpoint` of every node's MachineConfig (the URL kubelet and kube-proxy dial). The flag is honored on initial `init` only — for an existing project, edit `values.yaml` directly. - -`--endpoints` and `--cluster-endpoint` address different concepts: `--endpoints` (plural, list) populates the `talosconfig` context for the talosctl client; `--cluster-endpoint` (singular, full URL) populates the Kubernetes control-plane address inside the chart. When `--endpoints` is given a single value, init auto-derives `values.yaml::endpoint` as `https://:6443` — the single-target case is unambiguous. Multi-endpoint inputs never auto-derive (picking one node would silently couple cluster availability to it); the operator must pass `--cluster-endpoint` explicitly or fill `values.yaml::endpoint` later. The init flow prints a hint at the end when the field is left empty. - -Edit `values.yaml` to set your cluster's control-plane endpoint if neither flag set it. This is the URL every node's kubelet and kube-proxy will dial. The chart leaves it empty by default so a missed override fails loudly instead of silently embedding a placeholder. - -Endpoint / floatingIP combinations: - -- **cozystack VIP setup**: set `endpoint` and `floatingIP` together to the same IP — single shared VIP. -- **single-node cluster**: set `endpoint` to the node's routable IP and leave `floatingIP` blank. -- **multi-node with external load balancer**: set `endpoint` to the LB URL and leave `floatingIP` blank. - -When `vipLink` is left empty the chart picks the link automatically using a two-step rule: - -1. **Longest-prefix match across configurable links.** If `floatingIP` falls inside the CIDR of any address on a configurable link (physical NIC, bond, VLAN, bridge), the most specific subnet wins. This handles the Hetzner-style topology where a public NIC carries the default route and a VLAN child carries the private cluster subnet — the VIP lands on the VLAN child. -2. **Fallback to the IPv4-default-gateway-bearing link.** Used when no configurable link's CIDR contains the `floatingIP` — typical for upstream-routable VIPs that arrive via the default route. - -Addresses on links the chart does not emit a per-link document for (Wireguard, kernel-managed loopback, slave NICs of a bond, anything outside the configurable set) are skipped — a VIP pinned there would have no surrounding network document. - -Set `vipLink` explicitly when the target link does not yet exist on the live system at first apply (typically a VLAN sub-interface). The chart pins `Layer2VIPConfig.link` to it directly and emits the document even on a fresh node where discovery has not yet populated the addresses table. The chart does not auto-emit a `LinkConfig` or `VLANConfig` for the override link; the operator is responsible for ensuring the link comes up, typically by adding a `LinkConfig` or `VLANConfig` for that link to the per-node body overlay alongside `vipLink`. - -Subnet-selector fields (`kubelet.validSubnets`, `etcd.advertisedSubnets`) are derived automatically from the node's default-gateway-bearing link, so no override is needed unless you have a multi-homed node that requires a specific subnet pinned. - -Boot Talos Linux node, let's say it has address `192.0.2.4`. Then: - -```yaml -# values.yaml (single-node example matching the 192.0.2.4 node below) -endpoint: "https://192.0.2.4:6443" -floatingIP: "" -``` - -Gather node information: -```bash -talm --nodes 192.0.2.4 -e 192.0.2.4 template -t templates/controlplane.yaml -i > nodes/node1.yaml -``` - -Edit `nodes/node1.yaml` file: -```yaml -# talm: nodes=["192.0.2.4"], endpoints=["192.0.2.4"], templates=["templates/controlplane.yaml"] -machine: - network: - # -- Discovered interfaces: - # enx9c6b0047066c: - # name: enp193s0f0 - # mac:9c:6b:00:47:06:6c - # bus:0000:c1:00.0 - # driver:bnxt_en - # vendor: Broadcom Inc. and subsidiaries - # product: BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller) - # enx9c6b0047066d: - # name: enp193s0f1 - # mac:9c:6b:00:47:06:6d - # bus:0000:c1:00.1 - # driver:bnxt_en - # vendor: Broadcom Inc. and subsidiaries - # product: BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller) - interfaces: - - interface: enx9c6b0047066c - addresses: - - 192.0.2.4/26 - routes: - - network: 0.0.0.0/0 - gateway: 192.0.2.1 - nameservers: - - 8.8.8.8 - - 8.8.4.4 - install: - # -- Discovered disks: - # /dev/nvme0n1: - # model: SAMSUNG MZQL21T9HCJR-00A07 - # serial: S64GNE0RB00153 - # wwid: eui.3634473052b001530025384500000001 - # size: 1.75 TB - # /dev/nvme1n1: - # model: SAMSUNG MZQL21T9HCJR-00A07 - # serial: S64GNE0R811820 - # wwid: eui.36344730528118200025384500000001 - # size: 1.75 TB - disk: /dev/nvme0n1 - type: controlplane -cluster: - clusterName: talm - controlPlane: - endpoint: https://192.0.2.4:6443 -``` - -> **Note: output format depends on Talos version.** -> -> Selected via `Chart.yaml` (`templateOptions.talosVersion`) or `--talos-version`: -> -> - **Talos < v1.12** — single YAML document with `machine.network` and `machine.registries` sections (as shown above). -> - **Talos >= v1.12** — multi-document format with separate typed documents instead of the deprecated monolithic fields. -> -> For v1.12+ multi-doc output, one document is emitted per configurable link on the node, plus any link declared through `network.extraLinks` and a fixed pair on every render: -> -> - `HostnameConfig` and `ResolverConfig` — always emitted. -> - `LinkConfig` — physical NICs. -> - `BondConfig` — bond masters. Bond slaves are filtered out so they do not collide with the master's document. -> - `VLANConfig` — VLAN sub-interfaces. -> - `BridgeConfig` — bridges, symmetric to `BondConfig` for bonds. Ports discovered via `spec.slaveKind == "bridge"` + `spec.masterIndex`; STP / VLAN-filtering settings reach the output when the bridge controller reports them on `spec.bridgeMaster`. -> - `Layer2VIPConfig` — one per VIP. The `floatingIP` shorthand emits it on controlplane nodes; each `vips` entry emits one on any node, so a storage VIP works on a worker. -> - `RegistryMirrorConfig` and `RegistryTLSConfig` — from the `registryMirrors` and `registryTLS` values, available on both charts. -> -> Per-link emission rules: -> -> - The link carrying the IPv4 default route gets the `routes.gateway` entry on its document; every other link is emitted gateway-less. Applies uniformly to `LinkConfig`, `BondConfig`, `VLANConfig`, `BridgeConfig`. -> - Both IPv4 and IPv6 global-scope addresses on a link are surfaced. -> - Every declared VIP ip (`floatingIP` plus each `vips[].ip`) is stripped from the addresses discovery reports, so a VIP currently held by a leader does not leak into the static document. Addresses are compared canonically, so a VIP spelled differently from what the node reports (`2001:0DB8::5` against `2001:db8::5/64`) is still recognised. An address the operator writes by hand under `network.extraLinks` is refused rather than stripped — the render does not silently drop what it was told to emit. -> -> Multi-NIC nodes therefore produce one document per NIC, not one document total. -> -> Two values change this shape. `network.extraLinks` declares links that discovery cannot see — a bond, VLAN or address the node does not carry yet — so documents are emitted for links that are not (or not yet) on the node. A link named in `bond.interfaces` becomes a slave and stops getting a document of its own, the same filter discovery applies once the bond exists. Moving an already-addressed NIC into a bond works, provided the entry restates everything the slave was carrying — its `addresses`, a destination-less `routes` entry when it held the default route, and a matching `routes` entry per static route. Anything left behind fails the render rather than silently costing the node its connectivity or a reachable subnet. `network.preserveExisting` goes the other way: the running `machine.network.interfaces` block is carried over verbatim and the typed per-link rebuild is skipped entirely, so no per-link document is emitted at all. VIP and registry documents are unaffected by either. - -> **Version compatibility (`templateOptions.talosVersion` / `--talos-version`).** This setting must match the **Talos version actually running on the target node** — i.e. the maintenance ISO/PXE the node booted from for `apply -i`, or the installed Talos for an authenticated apply. It is **not** the same as `install.image`, which only controls what gets written to disk after a successful apply. When the configured contract is newer than the running binary, machinery injects fields (e.g. `machine.install.grubUseUKICmdline` from v1.12) that the running parser does not know, and the apply fails on the node side with `failed to parse config: unknown keys found during decoding: ...`. `talm apply` runs a best-effort pre-flight check against the running version and prints a `warning: pre-flight: ...` line with a hint when it detects this mismatch; if the warning is missed, the same hint is appended to the apply error. Either reboot the node into a maintenance image that matches the configured contract, or lower `templateOptions.talosVersion` / `--talos-version` to match what is running. - -> **Apply-time safety gates.** `talm apply` and `talm upgrade` run additional gates around each operation: -> -> 1. **Declared-resource existence** (`--skip-resource-validation` opt-out, default on). Before sending the config to the node, the gate walks the rendered MachineConfig, extracts every reference to a host-side resource (network links from v1.12 multi-doc — `LinkConfig.name`, `BondConfig.links[]`, `VLANConfig.parent`, `BridgeConfig.links[]`, `Layer2VIPConfig.link`, `HCloudVIPConfig.link`, `DHCPv4Config.name` / `DHCPv6Config.name` / `EthernetConfig.name`; v1.11 legacy `machine.network.interfaces[].interface`; install disk via `machine.install.disk` literal or `machine.install.diskSelector`; `UserVolumeConfig.provisioning.diskSelector`), and verifies each against the node's COSI `LinkStatus`/`Disk` snapshots. A reference that doesn't resolve fails the apply with a `[blocker]` line listing the available names so the typo or migration miss is fixable from the values without re-running discovery. Disk selectors must match at least one (non-readonly, non-CDROM, non-virtual) disk — zero matches block, multiple matches warn (install picks the first). Virtual-link-creator documents (`BondConfig.name`, `VLANConfig.name`, `BridgeConfig.name`, `WireguardConfig.name`, `DummyLinkConfig.name`, `LinkAliasConfig.name`) are intentionally NOT validated against existing links — those `.name` fields describe new virtual links the apply is creating, not references to pre-existing host resources. Five of them (`BondConfig`, `VLANConfig`, `BridgeConfig`, `DummyLinkConfig`, `LinkAliasConfig`) additionally register their `.name` as a link this apply brings into existence, so a `VLANConfig.parent`, `BondConfig.links[]` or `Layer2VIPConfig.link` pointing at one of them resolves rather than blocking. That is what makes a `network.extraLinks` bond usable on first apply, before the node carries it. A `LinkAliasConfig` name ending in `%d` is registered as a pattern rather than a literal, because Talos expands it into one sequential alias per matched link (`net0`, `net1`, …) — so a reference to `net0` resolves while the literal `net%d`, which never exists on the node, is not treated as a link. `WireguardConfig` is the exception: it is handled by the net-addr walker (for its `peers[].endpoint`), which stays disjoint from the link walker, so it does not register its name — a VLAN or VIP layered on a wireguard link still blocks on first apply and needs `--skip-resource-validation` until the link exists. The gate also runs a syntactic net-addr walker against `StaticHostConfig.name` (must parse as an IP literal — the `name` field on this kind doubles as the IP the hostnames map to), `NetworkRuleConfig.ingress[].subnet` and `.except` (per-entry CIDR), and `WireguardConfig.peers[].endpoint` (host:port; empty / absent endpoint is a listener-only peer, NOT a finding). Out of scope today: `machine.disks[].device` (extra-disk partitioning); track in a follow-up if you need it. With `network.preserveExisting` the rendered config carries the running `machine.network.interfaces` block instead of typed per-link documents, so the gate validates the legacy `interface` fields from that block. Pass `--skip-resource-validation` for recovery into a maintenance image with mismatched hardware or pre-staging values for hardware that isn't installed yet. -> -> 2. **Pre-apply drift preview** (`--skip-drift-preview` opt-out, default on). Reads the node's current MachineConfig via COSI and prints a `+`/`-`/`~`/`=` diff of what's about to change, keyed by `(kind, name)`. Informational only — never blocks. The `-` lines are the most useful: they surface stale documents from a previous apply that the new render no longer emits (e.g. an `eth1` LinkConfig lingering after a migration to `eth0`). Reading the current config requires the auth path — `MachineConfig` is a Sensitive COSI resource and is unreachable on the `--insecure` maintenance connection; the gate prints `drift verification unavailable on maintenance connection` (per-node-prefixed on multi-node insecure apply) and proceeds in that case. Secret-bearing field values (`cluster.token`, `cluster.{ca,aggregatorCA,serviceAccount,etcd.ca}.key`, `machine.token` / `machine.ca.key`, the `cluster.acceptedCAs` / `machine.acceptedCAs` slices, `WireguardConfig.privateKey`, the `peers` slice carrying `presharedKey`s) are redacted by default — both sides render as `***redacted (len=N)***` so a rotation surfaces as different-length sentinels without leaking the value. In addition to that static path allowlist, any value originating from an encrypted user value file (`*.encrypted.yaml` referenced via `templateOptions.valueFiles`) is redacted **by value** wherever it surfaces in the diff (at any path, including nested in a slice) — symmetric with how `talm template` redacts the same values. Pass `--show-secrets-in-drift` to see the raw values verbatim (debugging only — disables both the path-based and value-based redaction for the run). **`--dry-run` runs this gate** — the diff is read-only and "show me what would change" is exactly the dry-run contract. -> -> 3. **Post-apply state verification** (`--skip-post-apply-verify` opt-out, **default off** pending a Talos-mutated-field allowlist). After `ApplyConfiguration` returns success, re-reads the on-node MachineConfig and structurally compares it against the bytes that were sent. Divergence blocks the apply chain with a per-document diff, primarily catching silent doc drops (Talos parser ignored an unknown field) and controller reverts. Disabled by default because Talos mutates a handful of leaf fields post-apply (cert hashes, timestamps) that would surface as false-positive divergence without an allowlist. The verify runs only on `--mode=no-reboot`. `--mode=staged`, `--mode=try`, `--mode=reboot`, and `--mode=auto` all skip the gate — each for a documented reason: staged stores rather than activates; try auto-rolls back; reboot kills the COSI connection mid-verify; auto is promoted by Talos to REBOOT internally when the change requires it, so the verify would race the reboot. `--dry-run` skips it too. -> -> 4. **Post-upgrade version verify** (`--skip-post-upgrade-verify` opt-out, default on — the gate runs). After `talm upgrade` reports success, waits the configured reconcile window (default 90s; tune via `--post-upgrade-reconcile-window` for slow hardware / large image pulls) for the node to finish booting, then reads `runtime.Version` COSI and compares the running version's `(Major, Minor)` contract against the contract parsed from the target image tag. Point releases share a minor contract; cross-minor mismatch surfaces as a hint-bearing blocker. Catches the silent A/B rollback case where the upgrade RPC acks success but Talos rolled back to the previous partition (cross-vendor image, missing extensions, failed boot readiness check, slow boot exceeding the configured window). Best-effort surrender on digest-pinned images and unparseable tags. -> -> The skip flags don't suppress each other — pass them independently. On the `--insecure` (maintenance) path the gates are functionally unreachable for charts that drive discovery via `lookup` — those COSI lookups require an authenticated connection and the render itself errors before any gate runs. Charts that render fully offline (no `lookup` calls) reach the gates on `--insecure` as well, with the Phase 2 hooks degrading gracefully because the `MachineConfig` resource is Sensitive. - -Apply config: -```bash -talm apply -f nodes/node1.yaml -i -``` - -Upgrade node: -```bash -talm upgrade -f nodes/node1.yaml -``` - -`talm upgrade` resolves the target installer image from `values.yaml::image` (the cluster-wide knob). To pick the new version, bump `values.yaml::image` and re-run `talm upgrade -f nodes/.yaml`; there is no need to re-template the node files first. Pass `--image ` to override per-invocation (e.g. for an experimental installer build); the flag wins over the `values.yaml` lookup. - -Show diff: -```bash -talm apply -f nodes/node1.yaml --dry-run -``` - -Re-template and update generated file in place (this will overwrite it): -``` -talm template -f nodes/node1.yaml -I -``` - -> **Per-node patches inside node files.** A node file can carry Talos config below its modeline (for example, a custom `hostname`, secondary interfaces with `deviceSelector`, VIP placement, or extra etcd args). When `talm apply -f node.yaml` runs the template-rendering branch, that body is applied as a strategic merge patch on top of the rendered template before the result is sent to the node — so per-node fields survive even when the template auto-generates conflicting values (e.g. `hostname: talos-XXXXX`). -> -> **Talos v1.12+ caveat.** The multi-document output format introduced in v1.12 splits network configuration into typed documents (`LinkConfig`, `BondConfig`, `VLANConfig`, `Layer2VIPConfig`, `HostnameConfig`, `ResolverConfig`). Legacy node-body fields under `machine.network.interfaces` have no safe 1:1 mapping to those types and the chart cannot translate them yet — pin per-node network settings by patching the typed resources (e.g. a `LinkConfig` document below the modeline) rather than legacy `machine.network.interfaces`. Fields outside the network area (`machine.network.hostname` via `HostnameConfig`, `machine.install.disk`, extra etcd args, etc.) still merge as expected. -> -> **Upgrade-from-legacy guardrail.** Nodes originally bootstrapped on a chart that emitted the legacy schema still carry `machine.network.interfaces[]` in their running `MachineConfig`. On v1.12 multi-doc rendering the chart cannot reconstruct equivalent typed documents from those entries automatically, and silently dropping them on the next apply would erase the user's network declarations. The renderer therefore fails the render with `talm: the multi-doc renderer cannot translate legacy machine.network.interfaces[] from the running MachineConfig...`, spelling out the migration path: move the interfaces, vlans, and addresses into per-node body overlays as v1.12 typed documents (`LinkConfig`, `VLANConfig`, `BondConfig`, `RouteConfig`) before re-running `talm apply`, or pin `templateOptions.talosVersion: "v1.11"` in `Chart.yaml` until the translator lands. -> -> **One body, one node.** A non-empty body is a per-node pin, so the modeline for that file must target exactly one node. `talm apply` refuses a multi-node modeline when the body is non-empty; modeline-only files (no body) are still allowed and drive the same rendered template on every listed target. -> -> **Idempotent applies.** Repeated `talm apply` runs against an already-configured node do not duplicate entries. Before the strategic merge runs, the engine prunes from the body every primitive-list entry the rendered template already carries (e.g. certSANs, nameservers, validSubnets). For object arrays the upstream patcher merges by identity (machine.network.interfaces by `interface:` or `deviceSelector:`, vlans by `vlanId:`, apiServer admissionControl by `name:`), the prune descends into matched pairs and dedupes the inner primitive lists too — so re-applying after `talm template -I` does not double interface addresses, vlan addresses, or admission-control exemption namespaces. For object arrays without an upstream identity merge (extraVolumes, kernel.modules, wireguard.peers, ...), body items that deep-equal a rendered counterpart are dropped, covering the dominant full-restate case. Fields tagged `merge:"replace"` upstream are passed through verbatim — pruning them would let the upstream replace silently drop the rendered entries on a partial edit. This covers v1alpha1 root paths `cluster.network.podSubnets`, `cluster.network.serviceSubnets`, `cluster.apiServer.auditPolicy`, and the typed `NetworkRuleConfig` paths `ingress` and `portSelector.ports`. -> -> `talm template -f node.yaml` (with or without `-I`) does **not** apply the same overlay: its output is the rendered template plus the modeline and the auto-generated warning, byte-identical to what the template alone would produce. Routing it through the patcher would drop every YAML comment (including the modeline) and re-sort keys, breaking downstream commands that read the file back. Use `apply --dry-run` if you want to preview the exact bytes that will be sent to the node. - -## Keeping charts in sync after a binary upgrade - -`talm init` **vendors** its preset and library charts into the project directory — the preset templates plus a copy of the talm library chart under `charts/talm/`: - -```text -mycluster/ -├── Chart.yaml -├── values.yaml -├── .talm-preset.lock # pinned preset baseline — commit it (see "Preset drift") -├── templates/ # preset templates — you own and edit these -└── charts/ - └── talm/ # talm library chart — vendored from the binary - ├── Chart.yaml - └── templates/_helpers.tpl -``` - -Render commands (`template`, `apply`, `upgrade`) read this **local** copy, never the binary's built-in charts. That makes a project self-contained and reproducible — but it also means upgrading the `talm` binary does not touch `charts/talm/`. The vendored library stays frozen at whatever version last ran `init`, so a binary upgrade can leave you rendering with stale chart logic. - -Re-sync the vendored library with `talm init --update`: - -```bash -talm init --update --preset -``` - -This refreshes `charts/talm/` (always) and offers to update the preset templates (interactively, since you may have edited them). Your `values.yaml`, secrets, and node files are left untouched. - -To catch drift automatically, a release build compares the vendored `charts/talm/` against its own built-in copy on every config-loading command. The comparison is by **content**, not version number — re-vendoring after a binary bump that did not change the library is a no-op and raises no warning. When the content genuinely differs, talm prints a non-fatal warning to stderr (stdout and the exit code are unchanged): - -```text -WARN: project's vendored charts/talm/ library differs from the copy built into talm (modified: templates/_helpers.tpl); run `talm init --update --preset ` to re-sync (or ignore if this is intentional) -``` - -The remediation needs the preset name because `talm init --update` resolves the preset from `Chart.yaml`, which an init'd project does not record — pass `--preset ` (the one you ran `talm init` with) explicitly. - -Teams that want this enforced can turn the warning into a hard error (exit 1): set `strictCharts: true` in `Chart.yaml` so the whole team and CI inherit it, or pass `--strict-charts` for a single run. Strict mode applies to every config-loading command, including read-only ones such as `talm get` — run `talm init --update --preset `, or drop the flag / unset `strictCharts`, to unblock. Strict mode also escalates a check that cannot run at all — an unreadable `charts/talm/` or a corrupted `.talm-preset.lock` — into the same hard error, where the default behaviour degrades it to a `WARN: could not check drift` line: an unverifiable baseline passing silently would defeat the enforcement. A *missing* baseline (no `charts/talm/`, no `.talm-preset.lock`) blocks under strict for the same reason — deleting the baseline must not be a quieter bypass than corrupting it — while staying silent without strict, so projects generated before baseline pinning are not nagged. The check stays silent for `dev`/source builds, whose embedded charts are a moving target the developer controls. - -### Preset drift - -The vendored library (`charts/talm/`) is not the whole story. `talm init` also copies the **preset** — the `templates/` that render your machine config (sysctls, etcd args, the cozystack opinions) — into the project, and those you are *expected* to edit. That makes content comparison the wrong tool: it would flag every legitimate customization. So the preset is tracked differently. At `init` (and `init --update`) time talm pins the hash of the preset **as shipped** into `.talm-preset.lock`: - -```yaml -preset: cozystack -presetHash: -``` - -A release build then compares the binary's *current* preset hash against that pinned baseline — never against your edited `templates/` — so operator customizations are never reported as drift. When a newer binary ships changed preset defaults, the baseline no longer matches and talm warns: - -```text -WARN: project's cozystack preset differs from the copy built into talm ; run `talm init --update --preset cozystack` to pull the new preset defaults (your templates/ edits are preserved via the interactive diff) -``` - -`talm init --update --preset ` shows you an interactive diff of the new preset against your `templates/`, lets you merge what you want, and advances the baseline — which clears the warning even if you decline individual diffs to keep your customizations. `--strict-charts` / `strictCharts: true` escalate this to a hard error exactly as for the library. Projects with no `.talm-preset.lock` (generated before preset pinning) stay silent — there is no baseline to compare — unless strict mode is on, which treats a missing baseline as a blocker. Commit `.talm-preset.lock` so the baseline is shared across your team. - -## Apply with side-patches - -`talm apply -f` accepts a chain of files. The FIRST `-f` is the **anchor** — it must carry a `# talm: nodes=[…], templates=[…]` modeline and live under a `talm init`'d project (Chart.yaml + secrets.yaml). Any subsequent `-f` files are **side-patches**: they are merged in order on top of the anchor's rendered config, and a single `ApplyConfiguration` is issued per node carrying the composed result. - -```bash -# Single node file (anchor only): -talm apply -f nodes/cp01.yaml - -# Side-patch stacked on top — useful for one-shot overlays -# (debug kubelet flags, temporary cert SANs, mode=staged drills): -talm apply -f nodes/cp01.yaml -f /tmp/debug-kubelet.yaml -``` - -Side-patches do not need to live under the project root; the first file anchors detection. Reversing the order is an error — the first file must be the rooted anchor. - -If you were relying on the previous "apply N independent node files" shape (`talm apply -f n1.yaml -f n2.yaml -f n3.yaml` triggering three separate applies), invoke `talm apply` once per node file instead: - -```bash -for n in nodes/*.yaml; do talm apply -f "$n"; done -``` - -The current shape rejects this misuse loudly: if any of the subsequent `-f` files carries its own `# talm: …` modeline, the apply errors out before any RPC fires with a hint pointing at the shell-loop pattern above. Stripping the modeline turns a file into a legitimate side-patch. - -Side-patches with a non-empty body are restricted to **single-node anchors**. The same body cannot be distinguished from per-node fields (hostname, address, VIP) versus cluster-wide knobs (NTP servers, KubeProxy mode) by static inspection, and stamping per-node fields across N machines is the original foot-gun the per-node-body guard was designed to prevent. If your anchor's `nodes=[…]` lists more than one target and your side-patch is non-empty, talm rejects the apply early with a hint pointing at the per-file shell loop. For cluster-wide overlays on multi-node anchors, fold the overlay into `values.yaml` or templates rather than passing it as a side-patch; for per-node overrides, generate per-node files via `talm template -I` and feed them into the per-file shell loop. - -## Using talosctl commands - -Talm offers a similar set of commands to those provided by talosctl. However, you can specify the --file option for them. - -For example, to run a dashboard for three nodes: - -``` -talm dashboard -f node1.yaml -f node2.yaml -f node3.yaml -``` - -### `talm reset` — META-preserving default - -`talm reset` diverges from upstream `talosctl reset` on one default. Upstream defaults to `--wipe-mode=all`, which wipes the Talos META partition along with STATE and EPHEMERAL — the node cannot self-recover and comes up in maintenance mode requiring a full re-apply. Talm instead populates `--system-labels-to-wipe=STATE,EPHEMERAL` when neither `--wipe-mode` nor `--system-labels-to-wipe` was passed, which preserves META so the node rejoins the cluster from its META-stored bootstrap config on the next boot. - -Explicit operator intent is honored unchanged: - -```bash -# talm default — preserves META, node self-recovers. -talm reset --reboot --graceful=true --nodes $NODE --endpoints $OTHER_NODE - -# Explicit destructive opt-in (upstream's default). -talm reset --wipe-mode=all --reboot --nodes $NODE --endpoints $OTHER_NODE - -# Operator-specified narrower scope is honored byte-for-byte. -talm reset --system-labels-to-wipe=STATE --reboot --nodes $NODE --endpoints $OTHER_NODE -``` - -## Customization - -You're free to edit template files in `./templates` directory. - -All the [Helm](https://helm.sh/docs/chart_template_guide/functions_and_pipelines/) and [Sprig](https://masterminds.github.io/sprig/) functions are supported, including lookup for talos resources! - -Lookup function example: - -```helm -{{ lookup "nodeaddresses" "network" "default" }} -``` - -\- is equivalent to: - -```bash -talosctl get nodeaddresses --namespace=network default -``` - - -Querying disks map example: - -```helm -{{ range .Disks }}{{ if .system_disk }}{{ .device_name }}{{ end }}{{ end }} -``` - -\- will return the system disk device name - - -### `--set` vs `--set-string` for IP / version literals - -Helm's `--set` parser interprets dots in the right-hand side as YAML key nesting: - -```bash -talm template --set endpoint=10.0.0.1 # parsed as: endpoint: {10: {0: {0: 1}}} -``` - -For IP addresses, CIDR blocks, or version strings, use `--set-string` to keep the value verbatim: - -```bash -talm template --set-string endpoint=10.0.0.1 # parsed as: endpoint: "10.0.0.1" -``` - -`talm` warns on stderr when it detects an IP-, CIDR-, or version-shaped value in `--set` and points at `--set-string` as the fix. The warning is non-fatal — rendering proceeds with the (likely-broken) nested map so existing automation does not break. For values containing characters Helm's strvals treats specially (e.g. `=`, `,` inside the value, or content that should be opaque to all parsing), use `--set-literal` — it stores the entire RHS as a verbatim string without any escape interpretation. - -## Encryption - -Talm provides built-in encryption support using [age](https://age-encryption.org/) encryption. Sensitive files are encrypted with their values stored in SOPS format (`ENC[AGE,data:...]`), while YAML keys remain unencrypted for better readability. - -### Encrypting Files - -To encrypt all sensitive files (secrets.yaml, talosconfig, kubeconfig): - -```bash -talm init --encrypt -# or -talm init -e -``` - -This command will: -- Generate `talm.key` if it doesn't exist -- Encrypt `secrets.yaml` → `secrets.encrypted.yaml` -- Encrypt `talosconfig` → `talosconfig.encrypted` -- Encrypt `kubeconfig` → `kubeconfig.encrypted` (if exists) -- Encrypt `values-secret.yaml` → `values-secret.encrypted.yaml` (if exists) -- Update `.gitignore` with sensitive files - -### Decrypting Files - -To decrypt all encrypted files: - -```bash -talm init --decrypt -# or -talm init -d -``` - -This command will: -- Decrypt `secrets.encrypted.yaml` → `secrets.yaml` -- Decrypt `talosconfig.encrypted` → `talosconfig` -- Decrypt `kubeconfig.encrypted` → `kubeconfig` (if exists) -- Decrypt `values-secret.encrypted.yaml` → `values-secret.yaml` (if exists) -- Update `.gitignore` with sensitive files - -### Encrypted user values - -Beyond Talos' own PKI/tokens, you can store **arbitrary secret values that chart templates consume** (a registry password, a KMS plugin's secret-id, etc.) encrypted at rest with the same `talm.key`: - -1. Author the secrets in plaintext `values-secret.yaml` (git-ignored), e.g.: - - ```yaml - registryPassword: hunter2 - ``` - -2. Encrypt them with `talm init --encrypt` → produces the committable `values-secret.encrypted.yaml` (per-value `ENC[AGE,...]` envelopes; keys stay readable). - -3. Reference the **encrypted** file from `Chart.yaml`: - - ```yaml - templateOptions: - valueFiles: - - values-secret.encrypted.yaml - ``` - -`talm template` and `talm apply` decrypt it **in memory** via `talm.key` — the plaintext never has to be present at render time. Both commands now honor the full value-source set (`--values`, `--set`, `--set-string`, `--set-file`, `--set-json`, `--set-literal`) plus `templateOptions.*`, so a value renders identically whether you preview with `template` or push with `apply`. - -Secret values are kept out of committed and printed output: - -- `talm template -I` **omits** secret-bearing fields from the rendered `nodes/*.yaml`; the real value is re-injected only at `apply` (which re-renders from the encrypted file). -- `talm template` (stdout) and `talm apply` (drift preview) **redact** them to `***` by default. Reveal verbatim with `talm template --show-secrets` / `talm apply --show-secrets-in-drift` (debugging only). - -> Reference the encrypted file from `Chart.yaml templateOptions.valueFiles` (as shown above), NOT only via `template --values`. The node-file modeline does not persist value files, so `apply` only re-reads what is in `Chart.yaml` (plus its own `--values`). If an encrypted file is passed solely to `template -I`, the omitted secret is absent from the node file AND never re-rendered at apply — silently lost from the applied config. `template -I` prints a warning when it omits secrets from a file that is not in `Chart.yaml`. - -> Sealing matches by exact value across the whole rendered config, so do not encrypt low-entropy values that collide with ordinary config strings (e.g. a bare port, or a password literally set to `controlplane`) — that unrelated field would be sealed too. Prefer high-entropy secrets. Secret values must be strings (quote them in `values-secret.yaml`); the encryption only covers string leaves. - -### Key Management - -The `talm.key` file is generated in age keygen format and contains: -- Creation timestamp -- Public key (for sharing) -- Private key (keep secure!) +Full documentation lives at **[talm.cozystack.io](https://talm.cozystack.io/)**. -**Important**: Always backup your `talm.key` file! Without it, you won't be able to decrypt your encrypted secrets. The key file is automatically added to `.gitignore` to prevent accidental commits. +- [Quickstart](https://talm.cozystack.io/getting-started/quickstart/) — from an empty directory to a configured node. +- [Initializing a project](https://talm.cozystack.io/getting-started/init/) — `--image`, `--cluster-endpoint`, `--root`. +- [Node files](https://talm.cozystack.io/configuration/node-files/) — the modeline, discovery comments, per-node overrides. +- [Endpoints and VIPs](https://talm.cozystack.io/configuration/endpoints-and-vips/) — `endpoint`, `floatingIP`, `vipLink`. +- [Talos versions and output format](https://talm.cozystack.io/configuration/talos-versions/) — the v1.12 multi-document split. +- [Templates and values](https://talm.cozystack.io/configuration/templates/) — `lookup`, `--set` vs `--set-string`. +- [Encryption](https://talm.cozystack.io/configuration/encryption/) — age-encrypted secrets and user values. +- [Applying with side-patches](https://talm.cozystack.io/operations/side-patches/) — the `-f` chain. +- [Apply-time safety gates](https://talm.cozystack.io/operations/safety-gates/) — what `apply` and `upgrade` check. +- [talosctl-compatible commands](https://talm.cozystack.io/operations/talosctl-commands/) — what talm wraps and what it does not. +- [Upgrading talm](https://talm.cozystack.io/operations/upgrading/) — keeping vendored charts in sync. +- [CLI reference](https://talm.cozystack.io/reference/) — commands and flags. -Encrypted files (`*.encrypted.yaml`, `*.encrypted`) can be safely committed to Git, while plain files (`secrets.yaml`, `talosconfig`, `kubeconfig`, `talm.key`) are ignored. +The site is built from `docs/` in this repository; the CLI reference under `docs/reference/` is generated from the command tree. diff --git a/docs/.nav.yml b/docs/.nav.yml new file mode 100644 index 00000000..f39c3a0d --- /dev/null +++ b/docs/.nav.yml @@ -0,0 +1,22 @@ +# Site navigation. This lives here rather than in mkdocs.yml because +# awesome-nav owns the nav tree, and only from here can the generated +# reference/ section expand through its own .nav.yml. +nav: + - Home: index.md + - Getting started: + - Installation: getting-started/installation.md + - Quickstart: getting-started/quickstart.md + - Initializing a project: getting-started/init.md + - Configuration: + - Node files: configuration/node-files.md + - Endpoints and VIPs: configuration/endpoints-and-vips.md + - Talos versions and output format: configuration/talos-versions.md + - Templates and values: configuration/templates.md + - Encryption: configuration/encryption.md + - Operations: + - Applying with side-patches: operations/side-patches.md + - Apply-time safety gates: operations/safety-gates.md + - talosctl-compatible commands: operations/talosctl-commands.md + - Upgrading talm: operations/upgrading.md + - CLI reference: reference + - Cozystack: https://cozystack.io diff --git a/docs/assets/favicon.svg b/docs/assets/favicon.svg new file mode 100644 index 00000000..7f4f89b9 --- /dev/null +++ b/docs/assets/favicon.svg @@ -0,0 +1 @@ +cozystack-icon-color diff --git a/docs/assets/logo.svg b/docs/assets/logo.svg new file mode 100644 index 00000000..ea188f85 --- /dev/null +++ b/docs/assets/logo.svg @@ -0,0 +1 @@ +Cozystack diff --git a/docs/configuration/encryption.md b/docs/configuration/encryption.md new file mode 100644 index 00000000..5e78cf7a --- /dev/null +++ b/docs/configuration/encryption.md @@ -0,0 +1,86 @@ +# Encryption + +Talm provides built-in encryption support using [age](https://age-encryption.org/) encryption. Sensitive files are encrypted with their values stored in SOPS format (`ENC[AGE,data:...]`), while YAML keys remain unencrypted for better readability. + +## Encrypting files + +To encrypt all sensitive files (secrets.yaml, talosconfig, kubeconfig): + +```bash +talm init --encrypt +# or +talm init -e +``` + +This command will: +- Generate `talm.key` if it doesn't exist +- Encrypt `secrets.yaml` → `secrets.encrypted.yaml` +- Encrypt `talosconfig` → `talosconfig.encrypted` +- Encrypt `kubeconfig` → `kubeconfig.encrypted` (if exists) +- Encrypt `values-secret.yaml` → `values-secret.encrypted.yaml` (if exists) +- Update `.gitignore` with sensitive files + +## Decrypting files + +To decrypt all encrypted files: + +```bash +talm init --decrypt +# or +talm init -d +``` + +This command will: +- Decrypt `secrets.encrypted.yaml` → `secrets.yaml` +- Decrypt `talosconfig.encrypted` → `talosconfig` +- Decrypt `kubeconfig.encrypted` → `kubeconfig` (if exists) +- Decrypt `values-secret.encrypted.yaml` → `values-secret.yaml` (if exists) +- Update `.gitignore` with sensitive files + +## Encrypted user values + +Beyond Talos' own PKI/tokens, you can store **arbitrary secret values that chart templates consume** (a registry password, a KMS plugin's secret-id, etc.) encrypted at rest with the same `talm.key`: + +1. Author the secrets in plaintext `values-secret.yaml` (git-ignored), e.g.: + + ```yaml + registryPassword: hunter2 + ``` + +2. Encrypt them with `talm init --encrypt` → produces the committable `values-secret.encrypted.yaml` (per-value `ENC[AGE,...]` envelopes; keys stay readable). + +3. Reference the **encrypted** file from `Chart.yaml`: + + ```yaml + templateOptions: + valueFiles: + - values-secret.encrypted.yaml + ``` + +`talm template` and `talm apply` decrypt it **in memory** via `talm.key` — the plaintext never has to be present at render time. Both commands honor the full value-source set (`--values`, `--set`, `--set-string`, `--set-file`, `--set-json`, `--set-literal`) plus `templateOptions.*`, so a value renders identically whether you preview with `template` or push with `apply`. + +Secret values are kept out of committed and printed output: + +- `talm template -I` **omits** secret-bearing fields from the rendered `nodes/*.yaml`; the real value is re-injected only at `apply` (which re-renders from the encrypted file). +- `talm template` (stdout) and `talm apply` (drift preview) **redact** them to `***` by default. Reveal verbatim with `talm template --show-secrets` / [`talm apply --show-secrets-in-drift`](../operations/safety-gates.md) (debugging only). + +!!! danger "Put the encrypted file in Chart.yaml, not only on the command line" + + Reference the encrypted file from `Chart.yaml templateOptions.valueFiles` (as shown above), NOT only via `template --values`. The node-file modeline does not persist value files, so `apply` only re-reads what is in `Chart.yaml` (plus its own `--values`). If an encrypted file is passed solely to `template -I`, the omitted secret is absent from the node file AND never re-rendered at apply — silently lost from the applied config. `template -I` prints a warning when it omits secrets from a file that is not in `Chart.yaml`. + +!!! warning "Encrypt only high-entropy values" + + Sealing matches by exact value across the whole rendered config, so do not encrypt low-entropy values that collide with ordinary config strings (e.g. a bare port, or a password literally set to `controlplane`) — that unrelated field would be sealed too. Prefer high-entropy secrets. Secret values must be strings (quote them in `values-secret.yaml`); the encryption only covers string leaves. + +## Key management + +The `talm.key` file is generated in age keygen format and contains: +- Creation timestamp +- Public key (for sharing) +- Private key (keep secure!) + +!!! danger "Back up talm.key" + + Always backup your `talm.key` file! Without it, you won't be able to decrypt your encrypted secrets. The key file is automatically added to `.gitignore` to prevent accidental commits. + +Encrypted files (`*.encrypted.yaml`, `*.encrypted`) can be safely committed to Git, while plain files (`secrets.yaml`, `talosconfig`, `kubeconfig`, `talm.key`) are ignored. diff --git a/docs/configuration/endpoints-and-vips.md b/docs/configuration/endpoints-and-vips.md new file mode 100644 index 00000000..81c9d313 --- /dev/null +++ b/docs/configuration/endpoints-and-vips.md @@ -0,0 +1,28 @@ +# Endpoints and VIPs + +`values.yaml` carries three related network knobs: `endpoint` (the Kubernetes control-plane URL), `floatingIP` (the shared VIP address, if any), and `vipLink` (the link that VIP is pinned to). This page covers how they combine and what the chart derives when you leave them alone. + +## Endpoint and floatingIP combinations + +- **cozystack VIP setup**: set `endpoint` and `floatingIP` together to the same IP — single shared VIP. +- **single-node cluster**: set `endpoint` to the node's routable IP and leave `floatingIP` blank. +- **multi-node with external load balancer**: set `endpoint` to the LB URL and leave `floatingIP` blank. + +## Automatic vipLink selection + +When `vipLink` is left empty the chart picks the link automatically using a two-step rule: + +1. **Longest-prefix match across configurable links.** If `floatingIP` falls inside the CIDR of any address on a configurable link (physical NIC, bond, VLAN, bridge), the most specific subnet wins. This handles the Hetzner-style topology where a public NIC carries the default route and a VLAN child carries the private cluster subnet — the VIP lands on the VLAN child. +2. **Fallback to the IPv4-default-gateway-bearing link.** Used when no configurable link's CIDR contains the `floatingIP` — typical for upstream-routable VIPs that arrive via the default route. + +Addresses on links the chart does not emit a per-link document for (Wireguard, kernel-managed loopback, slave NICs of a bond, anything outside the configurable set) are skipped — a VIP pinned there would have no surrounding network document. + +## Overriding vipLink + +Set `vipLink` explicitly when the target link does not yet exist on the live system at first apply (typically a VLAN sub-interface). The chart pins `Layer2VIPConfig.link` to it directly and emits the document even on a fresh node where discovery has not yet populated the addresses table. The chart does not auto-emit a `LinkConfig` or `VLANConfig` for the override link; the operator is responsible for ensuring the link comes up, typically by adding a `LinkConfig` or `VLANConfig` for that link to the per-node body overlay alongside `vipLink`. + +The [per-node body overlay](node-files.md) is the node file's own Talos config, below its modeline. + +## Subnet selectors + +Subnet-selector fields (`kubelet.validSubnets`, `etcd.advertisedSubnets`) are derived automatically from the node's default-gateway-bearing link, so no override is needed unless you have a multi-homed node that requires a specific subnet pinned. diff --git a/docs/configuration/node-files.md b/docs/configuration/node-files.md new file mode 100644 index 00000000..e661142e --- /dev/null +++ b/docs/configuration/node-files.md @@ -0,0 +1,80 @@ +# Node files + +A node file is what `talm template -i` writes and what every later command reads back: one YAML document per node, carrying a `# talm:` modeline on the first line, the discovered hardware as comments, and optionally your own per-node config below it. See [Quickstart](../getting-started/quickstart.md) for the command that produces one. + +## Anatomy + +A freshly written `nodes/node1.yaml` for a single control-plane node at `192.0.2.4`: + +```yaml +# talm: nodes=["192.0.2.4"], endpoints=["192.0.2.4"], templates=["templates/controlplane.yaml"] +machine: + network: + # -- Discovered interfaces: + # enx9c6b0047066c: + # name: enp193s0f0 + # mac:9c:6b:00:47:06:6c + # bus:0000:c1:00.0 + # driver:bnxt_en + # vendor: Broadcom Inc. and subsidiaries + # product: BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller) + # enx9c6b0047066d: + # name: enp193s0f1 + # mac:9c:6b:00:47:06:6d + # bus:0000:c1:00.1 + # driver:bnxt_en + # vendor: Broadcom Inc. and subsidiaries + # product: BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller) + interfaces: + - interface: enx9c6b0047066c + addresses: + - 192.0.2.4/26 + routes: + - network: 0.0.0.0/0 + gateway: 192.0.2.1 + nameservers: + - 8.8.8.8 + - 8.8.4.4 + install: + # -- Discovered disks: + # /dev/nvme0n1: + # model: SAMSUNG MZQL21T9HCJR-00A07 + # serial: S64GNE0RB00153 + # wwid: eui.3634473052b001530025384500000001 + # size: 1.75 TB + # /dev/nvme1n1: + # model: SAMSUNG MZQL21T9HCJR-00A07 + # serial: S64GNE0R811820 + # wwid: eui.36344730528118200025384500000001 + # size: 1.75 TB + disk: /dev/nvme0n1 + type: controlplane +cluster: + clusterName: talm + controlPlane: + endpoint: https://192.0.2.4:6443 +``` + +## Per-node patches inside node files + +A node file can carry Talos config below its modeline (for example, a custom `hostname`, secondary interfaces with `deviceSelector`, VIP placement, or extra etcd args). When `talm apply -f node.yaml` runs the template-rendering branch, that body is applied as a strategic merge patch on top of the rendered template before the result is sent to the node — so per-node fields survive even when the template auto-generates conflicting values (e.g. `hostname: talos-XXXXX`). + +!!! warning "Talos v1.12+ caveat" + + The multi-document output format introduced in v1.12 splits network configuration into typed documents (`LinkConfig`, `BondConfig`, `VLANConfig`, `Layer2VIPConfig`, `HostnameConfig`, `ResolverConfig`). Legacy node-body fields under `machine.network.interfaces` have no safe 1:1 mapping to those types and the chart cannot translate them yet — pin per-node network settings by patching the typed resources (e.g. a `LinkConfig` document below the modeline) rather than legacy `machine.network.interfaces`. Fields outside the network area (`machine.network.hostname` via `HostnameConfig`, `machine.install.disk`, extra etcd args, etc.) still merge as expected. + +!!! warning "Upgrade-from-legacy guardrail" + + Nodes originally bootstrapped on a chart that emitted the legacy schema still carry `machine.network.interfaces[]` in their running `MachineConfig`. On v1.12 multi-doc rendering the chart cannot reconstruct equivalent typed documents from those entries automatically, and silently dropping them on the next apply would erase the user's network declarations. The renderer therefore fails the render with `talm: the multi-doc renderer cannot translate legacy machine.network.interfaces[] from the running MachineConfig...`, spelling out the migration path: move the interfaces, vlans, and addresses into per-node body overlays as v1.12 typed documents (`LinkConfig`, `VLANConfig`, `BondConfig`, `RouteConfig`) before re-running `talm apply`, or pin `templateOptions.talosVersion: "v1.11"` in `Chart.yaml` until the translator lands. + +!!! warning "One body, one node" + + A non-empty body is a per-node pin, so the modeline for that file must target exactly one node. `talm apply` refuses a multi-node modeline when the body is non-empty; modeline-only files (no body) are still allowed and drive the same rendered template on every listed target. + +## Idempotent applies + +Repeated `talm apply` runs against an already-configured node do not duplicate entries. Before the strategic merge runs, the engine prunes from the body every primitive-list entry the rendered template already carries (e.g. certSANs, nameservers, validSubnets). For object arrays the upstream patcher merges by identity (machine.network.interfaces by `interface:` or `deviceSelector:`, vlans by `vlanId:`, apiServer admissionControl by `name:`), the prune descends into matched pairs and dedupes the inner primitive lists too — so re-applying after `talm template -I` does not double interface addresses, vlan addresses, or admission-control exemption namespaces. For object arrays without an upstream identity merge (extraVolumes, kernel.modules, wireguard.peers, ...), body items that deep-equal a rendered counterpart are dropped, covering the dominant full-restate case. Fields tagged `merge:"replace"` upstream are passed through verbatim — pruning them would let the upstream replace silently drop the rendered entries on a partial edit. This covers v1alpha1 root paths `cluster.network.podSubnets`, `cluster.network.serviceSubnets`, `cluster.apiServer.auditPolicy`, and the typed `NetworkRuleConfig` paths `ingress` and `portSelector.ports`. + +## What `talm template` does not do + +`talm template -f node.yaml` (with or without `-I`) does **not** apply the same overlay: its output is the rendered template plus the modeline and the auto-generated warning, byte-identical to what the template alone would produce. Routing it through the patcher would drop every YAML comment (including the modeline) and re-sort keys, breaking downstream commands that read the file back. Use [`apply --dry-run`](../operations/safety-gates.md) if you want to preview the exact bytes that will be sent to the node. diff --git a/docs/configuration/talos-versions.md b/docs/configuration/talos-versions.md new file mode 100644 index 00000000..983a48e5 --- /dev/null +++ b/docs/configuration/talos-versions.md @@ -0,0 +1,44 @@ +# Talos versions and output format + +`templateOptions.talosVersion` in `Chart.yaml` (or `--talos-version` on the command line) selects which Talos config schema talm renders. It changes the shape of every node file. + +## Which format each version gets + +Selected via `Chart.yaml` (`templateOptions.talosVersion`) or `--talos-version`: + +- **Talos < v1.12** — single YAML document with `machine.network` and `machine.registries` sections (the shape shown in [Node files](node-files.md)). +- **Talos >= v1.12** — multi-document format with separate typed documents instead of the deprecated monolithic fields. + +## Documents emitted in multi-doc mode + +For v1.12+ multi-doc output, one document is emitted per configurable link on the node, plus any link declared through `network.extraLinks` and a fixed pair on every render: + +- `HostnameConfig` and `ResolverConfig` — always emitted. +- `LinkConfig` — physical NICs. +- `BondConfig` — bond masters. Bond slaves are filtered out so they do not collide with the master's document. +- `VLANConfig` — VLAN sub-interfaces. +- `BridgeConfig` — bridges, symmetric to `BondConfig` for bonds. Ports discovered via `spec.slaveKind == "bridge"` + `spec.masterIndex`; STP / VLAN-filtering settings reach the output when the bridge controller reports them on `spec.bridgeMaster`. +- `Layer2VIPConfig` — one per VIP. The `floatingIP` shorthand emits it on controlplane nodes; each `vips` entry emits one on any node, so a storage VIP works on a worker. +- `RegistryMirrorConfig` and `RegistryTLSConfig` — from the `registryMirrors` and `registryTLS` values, available on both charts. + +### Per-link emission rules + +- The link carrying the IPv4 default route gets the `routes.gateway` entry on its document; every other link is emitted gateway-less. Applies uniformly to `LinkConfig`, `BondConfig`, `VLANConfig`, `BridgeConfig`. +- Both IPv4 and IPv6 global-scope addresses on a link are surfaced. +- Every declared VIP ip (`floatingIP` plus each `vips[].ip`) is stripped from the addresses discovery reports, so a VIP currently held by a leader does not leak into the static document. Addresses are compared canonically, so a VIP spelled differently from what the node reports (`2001:0DB8::5` against `2001:db8::5/64`) is still recognised. An address the operator writes by hand under `network.extraLinks` is refused rather than stripped — the render does not silently drop what it was told to emit. + +Multi-NIC nodes therefore produce one document per NIC, not one document total. + +### Declaring links discovery cannot see + +`network.extraLinks` declares links that discovery cannot see — a bond, VLAN or address the node does not carry yet — so documents are emitted for links that are not (or not yet) on the node. A link named in `bond.interfaces` becomes a slave and stops getting a document of its own, the same filter discovery applies once the bond exists. Moving an already-addressed NIC into a bond works, provided the entry restates everything the slave was carrying — its `addresses`, a destination-less `routes` entry when it held the default route, and a matching `routes` entry per static route. Anything left behind fails the render rather than silently costing the node its connectivity or a reachable subnet. + +### Preserving links talm does not manage + +`network.preserveExisting` goes the other way: the running `machine.network.interfaces` block is carried over verbatim and the typed per-link rebuild is skipped entirely, so no per-link document is emitted at all. VIP and registry documents are unaffected by either. + +## Version compatibility + +!!! danger "The configured version must match the Talos actually running on the node" + + This setting must match the **Talos version actually running on the target node** — i.e. the maintenance ISO/PXE the node booted from for `apply -i`, or the installed Talos for an authenticated apply. It is **not** the same as `install.image`, which only controls what gets written to disk after a successful apply. When the configured contract is newer than the running binary, machinery injects fields (e.g. `machine.install.grubUseUKICmdline` from v1.12) that the running parser does not know, and the apply fails on the node side with `failed to parse config: unknown keys found during decoding: ...`. `talm apply` runs a best-effort pre-flight check against the running version and prints a `warning: pre-flight: ...` line with a hint when it detects this mismatch; if the warning is missed, the same hint is appended to the apply error. Either reboot the node into a maintenance image that matches the configured contract, or lower `templateOptions.talosVersion` / `--talos-version` to match what is running. diff --git a/docs/configuration/templates.md b/docs/configuration/templates.md new file mode 100644 index 00000000..3eaba10e --- /dev/null +++ b/docs/configuration/templates.md @@ -0,0 +1,43 @@ +# Templates and values + +You're free to edit template files in the project's `templates/` directory — the one [`talm init`](../operations/upgrading.md) writes alongside the vendored library chart. + +All the [Helm](https://helm.sh/docs/chart_template_guide/functions_and_pipelines/) and [Sprig](https://masterminds.github.io/sprig/) functions are supported, including lookup for talos resources! + +Lookup function example: + +=== "Template" + + ```helm + {{ lookup "nodeaddresses" "network" "default" }} + ``` + +=== "Equivalent talosctl call" + + ```bash + talosctl get nodeaddresses --namespace=network default + ``` + +Querying disks map example: + +```helm +{{ range .Disks }}{{ if .system_disk }}{{ .device_name }}{{ end }}{{ end }} +``` + +This returns the system disk device name. + +## `--set` vs `--set-string` for IP / version literals + +Helm's `--set` parser interprets dots in the right-hand side as YAML key nesting: + +```bash +talm template --set endpoint=10.0.0.1 # parsed as: endpoint: {10: {0: {0: 1}}} +``` + +For IP addresses, CIDR blocks, or version strings, use `--set-string` to keep the value verbatim: + +```bash +talm template --set-string endpoint=10.0.0.1 # parsed as: endpoint: "10.0.0.1" +``` + +`talm` warns on stderr when it detects an IP-, CIDR-, or version-shaped value in `--set` and points at `--set-string` as the fix. The warning is non-fatal — rendering proceeds with the (likely-broken) nested map so existing automation does not break. For values containing characters Helm's strvals treats specially (e.g. `=`, `,` inside the value, or content that should be opaque to all parsing), use `--set-literal` — it stores the entire RHS as a verbatim string without any escape interpretation. diff --git a/docs/getting-started/init.md b/docs/getting-started/init.md new file mode 100644 index 00000000..42cfe5d3 --- /dev/null +++ b/docs/getting-started/init.md @@ -0,0 +1,45 @@ +# Initializing a project + +`talm init` creates a project directory, vendors the preset and library charts into it, and writes the files every later command reads. This page covers the flags that shape that first run. + +```bash +talm init -p cozystack -N myawesomecluster +``` + +!!! warning "`--image` and `--cluster-endpoint` apply on the first `init` only" + + Both flags write into `values.yaml` at creation time. On an existing project they are not re-applied — edit `values.yaml` directly instead. + +## Re-initializing inside an existing project + +`talm init` refuses to run when the current directory is inside an existing talm project (it would otherwise walk up and partially overwrite the parent). To create a project under the current directory anyway — e.g. a sub-project nested inside another talm project — pass `--root .` explicitly. To re-initialise the parent itself, run `talm init` from the parent directory. + +## Pinning the installer image + +To pin a specific Talos installer image at init time (e.g. a [Talos Factory](https://factory.talos.dev/) image with extensions), pass `--image`: + +```bash +talm init -p cozystack -N myawesomecluster --image factory.talos.dev/installer/: +``` + +`--image` rewrites the top-level `image:` field in the preset's `values.yaml` before write. The `cozystack` preset declares `image:`; the `generic` preset does not, so `--image --preset generic` is rejected up front. + +## Setting the control-plane URL + +To set the Kubernetes control-plane URL at init time, pass `--cluster-endpoint`: + +```bash +talm init -p cozystack -N myawesomecluster --cluster-endpoint https://vip.example.test:6443 +``` + +`--cluster-endpoint` writes the URL into `values.yaml::endpoint`, which the chart renders into `cluster.controlPlane.endpoint` of every node's MachineConfig (the URL kubelet and kube-proxy dial). + +## `--endpoints` vs `--cluster-endpoint` + +`--endpoints` and `--cluster-endpoint` address different concepts: `--endpoints` (plural, list) populates the `talosconfig` context for the talosctl client; `--cluster-endpoint` (singular, full URL) populates the Kubernetes control-plane address inside the chart. When `--endpoints` is given a single value, init auto-derives `values.yaml::endpoint` as `https://:6443` — the single-target case is unambiguous. Multi-endpoint inputs never auto-derive (picking one node would silently couple cluster availability to it); the operator must pass `--cluster-endpoint` explicitly or fill `values.yaml::endpoint` later. The init flow prints a hint at the end when the field is left empty. + +## Filling the endpoint by hand + +Edit `values.yaml` to set your cluster's control-plane endpoint if neither flag set it. This is the URL every node's kubelet and kube-proxy will dial. The chart leaves it empty by default so a missed override fails loudly instead of silently embedding a placeholder. + +See [Endpoints and VIPs](../configuration/endpoints-and-vips.md) for how `endpoint` interacts with `floatingIP` and `vipLink`. diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md new file mode 100644 index 00000000..b1f9c14b --- /dev/null +++ b/docs/getting-started/installation.md @@ -0,0 +1,21 @@ +# Installation + +## Homebrew +For macOS and Linux users, the recommended way to install talm is with Homebrew. + +```bash +brew install talm +``` + +## Binary + +Download binary from Github [releases page](https://github.com/cozystack/talm/releases/latest) + +Or use simple script to install it: +```bash +curl -sSL https://github.com/cozystack/talm/raw/refs/heads/main/hack/install.sh | sh -s +``` + +## Windows + +Windows is supported. Download the `talm-windows-*.zip` archive from the [releases page](https://github.com/cozystack/talm/releases/latest) and extract `talm.exe`. On Windows, template paths passed to the `-t` / `--template` flag accept either `\` or `/` separators, so `-t templates\controlplane.yaml` and `-t templates/controlplane.yaml` are equivalent. Other path flags (`--talosconfig`, `-f` / `--file`) are delegated to the underlying OS file loader and follow standard Windows path rules. diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md new file mode 100644 index 00000000..fc90b0a1 --- /dev/null +++ b/docs/getting-started/quickstart.md @@ -0,0 +1,80 @@ +# Quickstart + +From an empty directory to a configured Talos node. The example uses a single control-plane node at `192.0.2.4`; substitute your own address. + +!!! note "All commands run from the project root" + + `talm init` creates the project directory and everything below assumes you are inside it. Node paths like `nodes/node1.yaml` are relative to that root. + +## 1. Create a project + +```bash +mkdir newcluster +cd newcluster +talm init -p cozystack -N myawesomecluster --endpoints 192.0.2.4 +``` + +Passing a single `--endpoints` value lets init derive `values.yaml::endpoint` as `https://192.0.2.4:6443`, so there is nothing to edit by hand. With more than one endpoint it does not derive anything — see [Initializing a project](init.md) for `--cluster-endpoint` and the rest of the init flags. + +!!! note + + `talm init` refuses to run inside an existing talm project. If that is deliberate, see [Re-initializing inside an existing project](init.md#re-initializing-inside-an-existing-project). + +`values.yaml` should now read: + +```yaml +# values.yaml (single-node example) +endpoint: "https://192.0.2.4:6443" +floatingIP: "" +``` + +[Endpoints and VIPs](../configuration/endpoints-and-vips.md) covers what to put here for a VIP or a load-balanced control plane. + +## 2. Gather node information + +Boot the Talos node and, while it is in maintenance mode, render its config: + +```bash +talm --nodes 192.0.2.4 -e 192.0.2.4 template -t templates/controlplane.yaml -i > nodes/node1.yaml +``` + +This writes `nodes/node1.yaml` with a `# talm:` modeline recording the node and endpoint addresses, the discovered interfaces and disks as comments, and the rendered machine config. Every later command reads those addresses back out of the file, so you never retype them. See [Node files](../configuration/node-files.md) for the file's anatomy and how to add per-node overrides. + +## 3. Apply the config + +```bash +talm apply -f nodes/node1.yaml -i +``` + +`-i` (`--insecure`) is the maintenance-mode connection used for a node that has no config yet. Drop it once the node is configured. + +Before anything is sent, `apply` checks that every link and disk your config names actually exists on the node and prints a diff of what is about to change — see [Apply-time safety gates](../operations/safety-gates.md). + +## 4. Day-to-day commands + +Preview what an apply would change, without applying it: + +```bash +talm apply -f nodes/node1.yaml --dry-run +``` + +Upgrade the node: + +```bash +talm upgrade -f nodes/node1.yaml +``` + +`talm upgrade` resolves the target installer image from `values.yaml::image` (the cluster-wide knob). To pick the new version, bump `values.yaml::image` and re-run `talm upgrade -f nodes/.yaml`; there is no need to re-template the node files first. Pass `--image ` to override per-invocation (e.g. for an experimental installer build); the flag wins over the `values.yaml` lookup. + +Re-template a node file in place after editing templates or values (this overwrites it): + +```bash +talm template -f nodes/node1.yaml -I +``` + +## Next steps + +- [Node files](../configuration/node-files.md) — per-node overrides below the modeline. +- [Templates and values](../configuration/templates.md) — editing templates, `lookup`, `--set-string`. +- [Encryption](../configuration/encryption.md) — keeping secrets out of Git. +- [CLI reference](../reference/index.md) — generated from the command tree. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..a1c4fd1a --- /dev/null +++ b/docs/index.md @@ -0,0 +1,87 @@ +--- +hide: + - navigation +--- + +# Talm + +**Manage Talos the GitOps way.** + +Talm is just like Helm, but for Talos Linux. It renders per-node machine configs from Go templates, discovers each node's real disks and interfaces, and applies the result with the flags you already know from `talosctl` — while the generated files stay clean enough to commit. + +[Quickstart](getting-started/quickstart.md){ .md-button .md-button--primary } +[Install talm](getting-started/installation.md){ .md-button } + +## Why Talm + +
+ +- :material-magnify-scan:{ .lg .middle } **Automatic discovery** + + --- + + Bare-metal servers differ in disks and interfaces. Talm reads the node's real hardware and writes the discovered names into the node file as comments you pick from. + + [:octicons-arrow-right-24: Node files](configuration/node-files.md) + +- :material-file-code-outline:{ .lg .middle } **Helm templating** + + --- + + Standard Go template syntax with the full Helm and Sprig function set — including `lookup` against live Talos COSI resources. + + [:octicons-arrow-right-24: Templates and values](configuration/templates.md) + +- :material-source-branch:{ .lg .middle } **GitOps friendly** + + --- + + Generated patches carry no sensitive data, so they live in Git in the clear. Secrets your templates need are age-encrypted at rest and decrypted in memory at render time. + + [:octicons-arrow-right-24: Encryption](configuration/encryption.md) + +- :material-shield-check-outline:{ .lg .middle } **Guarded applies** + + --- + + Every apply checks that the links and disks your config references exist on the node, and prints a diff of what is about to change before it changes it. + + [:octicons-arrow-right-24: Apply-time safety gates](operations/safety-gates.md) + +- :material-console-line:{ .lg .middle } **talosctl compatible** + + --- + + The same subcommands, plus `-f nodes/.yaml` so you never retype `--nodes` and `--endpoints`. Configs stay usable with talosctl and Omni. + + [:octicons-arrow-right-24: talosctl-compatible commands](operations/talosctl-commands.md) + +- :material-package-variant-closed:{ .lg .middle } **Reproducible projects** + + --- + + `talm init` vendors the preset and library chart into your repo, and warns when a binary upgrade leaves them stale. + + [:octicons-arrow-right-24: Upgrading talm](operations/upgrading.md) + +
+ +## From zero to a configured node + +```bash +brew install talm +mkdir mycluster && cd mycluster +talm init -p cozystack -N mycluster --endpoints 192.0.2.4 +talm --nodes 192.0.2.4 -e 192.0.2.4 template -t templates/controlplane.yaml -i > nodes/node1.yaml +talm apply -f nodes/node1.yaml -i +``` + +[The same five lines, explained :octicons-arrow-right-24:](getting-started/quickstart.md) + +## Where to next + +- [Initializing a project](getting-started/init.md) — `--image`, `--cluster-endpoint`, `--root`. +- [Endpoints and VIPs](configuration/endpoints-and-vips.md) — `endpoint`, `floatingIP`, `vipLink`. +- [Talos versions and output format](configuration/talos-versions.md) — the v1.12 multi-document split. +- [Applying with side-patches](operations/side-patches.md) — the `-f` chain. +- [CLI reference](reference/index.md) — generated from the command tree. diff --git a/docs/operations/safety-gates.md b/docs/operations/safety-gates.md new file mode 100644 index 00000000..1529fb68 --- /dev/null +++ b/docs/operations/safety-gates.md @@ -0,0 +1,52 @@ +# Apply-time safety gates + +`talm apply` and `talm upgrade` run additional gates around each operation. Each is opt-out through its own flag; the flags do not suppress each other. + +| Gate | Flag | Gate runs by default | +| --- | --- | --- | +| Declared-resource existence | `--skip-resource-validation` | on | +| Pre-apply drift preview | `--skip-drift-preview` | on | +| Post-apply state verification | `--skip-post-apply-verify` | **off** | +| Post-upgrade version verify | `--skip-post-upgrade-verify` | on | + +## 1. Declared-resource existence + +Before sending the config to the node, the gate walks the rendered MachineConfig, extracts every reference to a host-side resource (network links from v1.12 multi-doc — `LinkConfig.name`, `BondConfig.links[]`, `VLANConfig.parent`, `BridgeConfig.links[]`, `Layer2VIPConfig.link`, `HCloudVIPConfig.link`, `DHCPv4Config.name` / `DHCPv6Config.name` / `EthernetConfig.name`; v1.11 legacy `machine.network.interfaces[].interface`; install disk via `machine.install.disk` literal or `machine.install.diskSelector`; `UserVolumeConfig.provisioning.diskSelector`), and verifies each against the node's COSI `LinkStatus`/`Disk` snapshots. A reference that doesn't resolve fails the apply with a `[blocker]` line listing the available names so the typo or migration miss is fixable from the values without re-running discovery. + +Disk selectors must match at least one (non-readonly, non-CDROM, non-virtual) disk — zero matches block, multiple matches warn (install picks the first). + +### Virtual links this apply creates + +Virtual-link-creator documents (`BondConfig.name`, `VLANConfig.name`, `BridgeConfig.name`, `WireguardConfig.name`, `DummyLinkConfig.name`, `LinkAliasConfig.name`) are intentionally NOT validated against existing links — those `.name` fields describe new virtual links the apply is creating, not references to pre-existing host resources. Five of them (`BondConfig`, `VLANConfig`, `BridgeConfig`, `DummyLinkConfig`, `LinkAliasConfig`) additionally register their `.name` as a link this apply brings into existence, so a `VLANConfig.parent`, `BondConfig.links[]` or `Layer2VIPConfig.link` pointing at one of them resolves rather than blocking. That is what makes a `network.extraLinks` bond usable on first apply, before the node carries it. + +A `LinkAliasConfig` name ending in `%d` is registered as a pattern rather than a literal, because Talos expands it into one sequential alias per matched link (`net0`, `net1`, …) — so a reference to `net0` resolves while the literal `net%d`, which never exists on the node, is not treated as a link. + +`WireguardConfig` is the exception: it is handled by the net-addr walker (for its `peers[].endpoint`), which stays disjoint from the link walker, so it does not register its name — a VLAN or VIP layered on a wireguard link still blocks on first apply and needs `--skip-resource-validation` until the link exists. + +### Address and CIDR checks + +The gate also runs a syntactic net-addr walker against `StaticHostConfig.name` (must parse as an IP literal — the `name` field on this kind doubles as the IP the hostnames map to), `NetworkRuleConfig.ingress[].subnet` and `.except` (per-entry CIDR), and `WireguardConfig.peers[].endpoint` (host:port; empty / absent endpoint is a listener-only peer, NOT a finding). + +### Limits and escape hatch + +`machine.disks[].device` (extra-disk partitioning) is not covered — a reference there is neither validated nor blocked. + +With `network.preserveExisting` the rendered config carries the running `machine.network.interfaces` block instead of typed per-link documents, so the gate validates the legacy `interface` fields from that block. + +Pass `--skip-resource-validation` for recovery into a maintenance image with mismatched hardware or pre-staging values for hardware that isn't installed yet. + +## 2. Pre-apply drift preview + +Reads the node's current MachineConfig via COSI and prints a `+`/`-`/`~`/`=` diff of what's about to change, keyed by `(kind, name)`. Informational only — never blocks. The `-` lines are the most useful: they surface stale documents from a previous apply that the new render no longer emits (e.g. an `eth1` LinkConfig lingering after a migration to `eth0`). Reading the current config requires the auth path — `MachineConfig` is a Sensitive COSI resource and is unreachable on the `--insecure` maintenance connection; the gate prints `drift verification unavailable on maintenance connection` (per-node-prefixed on multi-node insecure apply) and proceeds in that case. Secret-bearing field values (`cluster.token`, `cluster.{ca,aggregatorCA,serviceAccount,etcd.ca}.key`, `machine.token` / `machine.ca.key`, the `cluster.acceptedCAs` / `machine.acceptedCAs` slices, `WireguardConfig.privateKey`, the `peers` slice carrying `presharedKey`s) are redacted by default — both sides render as `***redacted (len=N)***` so a rotation surfaces as different-length sentinels without leaking the value. In addition to that static path allowlist, any value originating from an encrypted user value file (`*.encrypted.yaml` referenced via `templateOptions.valueFiles`) is redacted **by value** wherever it surfaces in the diff (at any path, including nested in a slice) — symmetric with how `talm template` redacts the same values. Pass `--show-secrets-in-drift` to see the raw values verbatim (debugging only — disables both the path-based and value-based redaction for the run). **`--dry-run` runs this gate** — the diff is read-only and "show me what would change" is exactly the dry-run contract. + +## 3. Post-apply state verification + +After `ApplyConfiguration` returns success, re-reads the on-node MachineConfig and structurally compares it against the bytes that were sent. Divergence blocks the apply chain with a per-document diff, primarily catching silent doc drops (Talos parser ignored an unknown field) and controller reverts. Disabled by default because Talos mutates a handful of leaf fields post-apply (cert hashes, timestamps) that would surface as false-positive divergence without an allowlist. The verify runs only on `--mode=no-reboot`. `--mode=staged`, `--mode=try`, `--mode=reboot`, and `--mode=auto` all skip the gate — each for a documented reason: staged stores rather than activates; try auto-rolls back; reboot kills the COSI connection mid-verify; auto is promoted by Talos to REBOOT internally when the change requires it, so the verify would race the reboot. `--dry-run` skips it too. + +## 4. Post-upgrade version verify + +After `talm upgrade` reports success, waits the configured reconcile window (default 90s; tune via `--post-upgrade-reconcile-window` for slow hardware / large image pulls) for the node to finish booting, then reads `runtime.Version` COSI and compares the running version's `(Major, Minor)` contract against the contract parsed from the target image tag. Point releases share a minor contract; cross-minor mismatch surfaces as a hint-bearing blocker. Catches the silent A/B rollback case where the upgrade RPC acks success but Talos rolled back to the previous partition (cross-vendor image, missing extensions, failed boot readiness check, slow boot exceeding the configured window). Best-effort surrender on digest-pinned images and unparseable tags. + +## Skip flags and the maintenance path + +The skip flags don't suppress each other — pass them independently. On the `--insecure` (maintenance) path the gates are functionally unreachable for charts that drive discovery via `lookup` — those COSI lookups require an authenticated connection and the render itself errors before any gate runs. Charts that render fully offline (no `lookup` calls) reach the gates on `--insecure` as well, with the Phase 2 hooks degrading gracefully because the `MachineConfig` resource is Sensitive. diff --git a/docs/operations/side-patches.md b/docs/operations/side-patches.md new file mode 100644 index 00000000..22c27175 --- /dev/null +++ b/docs/operations/side-patches.md @@ -0,0 +1,24 @@ +# Applying with side-patches + +`talm apply -f` accepts a chain of files. The FIRST `-f` is the **anchor** — it must carry a `# talm: nodes=[…], templates=[…]` modeline and live under a `talm init`'d project (Chart.yaml + secrets.yaml). Any subsequent `-f` files are **side-patches**: they are merged in order on top of the anchor's rendered config, and a single `ApplyConfiguration` is issued per node carrying the composed result. + +```bash +# Single node file (anchor only): +talm apply -f nodes/node1.yaml + +# Side-patch stacked on top — useful for one-shot overlays +# (debug kubelet flags, temporary cert SANs, mode=staged drills): +talm apply -f nodes/node1.yaml -f /tmp/debug-kubelet.yaml +``` + +Side-patches do not need to live under the project root; the first file anchors detection. Reversing the order is an error — the first file must be the rooted anchor. + +Applying several nodes at once is a separate operation, not a longer `-f` chain — `talm apply -f n1.yaml -f n2.yaml -f n3.yaml` does not run three applies. Invoke `talm apply` once per node file: + +```bash +for n in nodes/*.yaml; do talm apply -f "$n"; done +``` + +That misuse is rejected loudly: if any of the subsequent `-f` files carries its own `# talm: …` modeline, the apply errors out before any RPC fires with a hint pointing at the shell loop above. Stripping the modeline turns a file into a legitimate side-patch. + +Side-patches with a non-empty body are restricted to **single-node anchors**. The same body cannot be distinguished from per-node fields (hostname, address, VIP) versus cluster-wide knobs (NTP servers, KubeProxy mode) by static inspection, and stamping per-node fields across N machines is the original foot-gun the per-node-body guard was designed to prevent. If your anchor's `nodes=[…]` lists more than one target and your side-patch is non-empty, talm rejects the apply early with a hint pointing at the per-file shell loop. For cluster-wide overlays on multi-node anchors, fold the overlay into `values.yaml` or templates rather than passing it as a side-patch; for per-node overrides, generate per-node files via `talm template -I` and feed them into the per-file shell loop. diff --git a/docs/operations/talosctl-commands.md b/docs/operations/talosctl-commands.md new file mode 100644 index 00000000..574af5d7 --- /dev/null +++ b/docs/operations/talosctl-commands.md @@ -0,0 +1,43 @@ +# talosctl-compatible commands + +Talm offers a similar set of commands to those provided by talosctl. However, you can specify the `--file` option for them, so the node and endpoint addresses come from the node file instead of being retyped on every invocation. + +For example, to run a dashboard for three nodes: + +```bash +talm dashboard -f nodes/node1.yaml -f nodes/node2.yaml -f nodes/node3.yaml +``` + +!!! warning "`-f` means something different here than it does for `apply`" + + On a wrapped talosctl command each `-f` names another **target**: the example above opens one dashboard covering three nodes. On [`talm apply`](side-patches.md) the first `-f` is the anchor and every later one is a side-patch merged onto it, so passing three node files there applies one node, not three. + +## Commands talm does not wrap + +Every talosctl command is re-exported except these, which talm either replaces or does not need: + +| Command | Why | +| --- | --- | +| `apply-config` | talm has its own [`apply`](safety-gates.md) | +| `config` | talm manages project configuration through `Chart.yaml` and `values.yaml` | +| `talosconfig` | talm has its own `talosconfig` command | +| `patch` | superseded by templates and [side-patches](side-patches.md) | +| `upgrade-k8s` | out of scope; talm configures machines, not the Kubernetes control plane | +| `dmesg` | retired upstream — use `talm logs kernel --tail=N` | + +## `talm reset` — META-preserving default + +`talm reset` diverges from upstream `talosctl reset` on one default. Upstream defaults to `--wipe-mode=all`, which wipes the Talos META partition along with STATE and EPHEMERAL — the node cannot self-recover and comes up in maintenance mode requiring a full re-apply. Talm instead populates `--system-labels-to-wipe=STATE,EPHEMERAL` when neither `--wipe-mode` nor `--system-labels-to-wipe` was passed, which preserves META so the node rejoins the cluster from its META-stored bootstrap config on the next boot. + +Explicit operator intent is honored unchanged. In the examples below `$NODE` is the node being reset and `$OTHER_NODE` is a surviving control-plane node to talk to, since the node under reset stops answering partway through: + +```bash +# talm default — preserves META, node self-recovers. +talm reset --reboot --graceful=true --nodes $NODE --endpoints $OTHER_NODE + +# Explicit destructive opt-in (upstream's default). +talm reset --wipe-mode=all --reboot --nodes $NODE --endpoints $OTHER_NODE + +# Operator-specified narrower scope is honored byte-for-byte. +talm reset --system-labels-to-wipe=STATE --reboot --nodes $NODE --endpoints $OTHER_NODE +``` diff --git a/docs/operations/upgrading.md b/docs/operations/upgrading.md new file mode 100644 index 00000000..f0c4a197 --- /dev/null +++ b/docs/operations/upgrading.md @@ -0,0 +1,54 @@ +# Keeping charts in sync after a binary upgrade + +`talm init` **vendors** its preset and library charts into the project directory — the preset templates plus a copy of the talm library chart under `charts/talm/`: + +```text +mycluster/ +├── Chart.yaml +├── values.yaml +├── .talm-preset.lock # pinned preset baseline — commit it +├── templates/ # preset templates — you own and edit these +└── charts/ + └── talm/ # talm library chart — vendored from the binary + ├── Chart.yaml + └── templates/_helpers.tpl +``` + +That is what `init` vendors, not the whole project — `nodes/`, `secrets.yaml` and `talosconfig` land there too. `.talm-preset.lock` records which preset the project was built from so a later binary upgrade can detect [preset drift](#preset-drift); commit it so the baseline is shared across the team. + +Render commands (`template`, `apply`, `upgrade`) read this **local** copy, never the binary's built-in charts. That makes a project self-contained and reproducible — but it also means upgrading the `talm` binary does not touch `charts/talm/`. The vendored library stays frozen at whatever version last ran `init`, so a binary upgrade can leave you rendering with stale chart logic. + +Re-sync the vendored library with `talm init --update`: + +```bash +talm init --update --preset +``` + +This refreshes `charts/talm/` (always) and offers to update the preset templates (interactively, since you may have edited them). Your `values.yaml`, secrets, and node files are left untouched. + +To catch drift automatically, a release build compares the vendored `charts/talm/` against its own built-in copy on every config-loading command. The comparison is by **content**, not version number — re-vendoring after a binary bump that did not change the library is a no-op and raises no warning. When the content genuinely differs, talm prints a non-fatal warning to stderr (stdout and the exit code are unchanged): + +```text +WARN: project's vendored charts/talm/ library differs from the copy built into talm (modified: templates/_helpers.tpl); run `talm init --update --preset ` to re-sync (or ignore if this is intentional) +``` + +The remediation needs the preset name because `talm init --update` resolves the preset from `Chart.yaml`, which an init'd project does not record — pass `--preset ` (the one you ran `talm init` with) explicitly. + +Teams that want this enforced can turn the warning into a hard error (exit 1): set `strictCharts: true` in `Chart.yaml` so the whole team and CI inherit it, or pass `--strict-charts` for a single run. Strict mode applies to every config-loading command, including read-only ones such as `talm get` — run `talm init --update --preset `, or drop the flag / unset `strictCharts`, to unblock. Strict mode also escalates a check that cannot run at all — an unreadable `charts/talm/` or a corrupted `.talm-preset.lock` — into the same hard error, where the default behaviour degrades it to a `WARN: could not check drift` line: an unverifiable baseline passing silently would defeat the enforcement. A *missing* baseline (no `charts/talm/`, no `.talm-preset.lock`) blocks under strict for the same reason — deleting the baseline must not be a quieter bypass than corrupting it — while staying silent without strict, so projects generated before baseline pinning are not nagged. The check stays silent for `dev`/source builds, whose embedded charts are a moving target the developer controls. + +## Preset drift + +The vendored library (`charts/talm/`) is not the whole story. `talm init` also copies the **preset** — the `templates/` that render your machine config (sysctls, etcd args, the cozystack opinions) — into the project, and those you are *expected* to edit. That makes content comparison the wrong tool: it would flag every legitimate customization. So the preset is tracked differently. At `init` (and `init --update`) time talm pins the hash of the preset **as shipped** into `.talm-preset.lock`: + +```yaml +preset: cozystack +presetHash: +``` + +A release build then compares the binary's *current* preset hash against that pinned baseline — never against your edited `templates/` — so operator customizations are never reported as drift. When a newer binary ships changed preset defaults, the baseline no longer matches and talm warns: + +```text +WARN: project's cozystack preset differs from the copy built into talm ; run `talm init --update --preset cozystack` to pull the new preset defaults (your templates/ edits are preserved via the interactive diff) +``` + +`talm init --update --preset ` shows you an interactive diff of the new preset against your `templates/`, lets you merge what you want, and advances the baseline — which clears the warning even if you decline individual diffs to keep your customizations. `--strict-charts` / `strictCharts: true` escalate this to a hard error exactly as for the library. Projects with no `.talm-preset.lock` (generated before preset pinning) stay silent — there is no baseline to compare — unless strict mode is on, which treats a missing baseline as a blocker. Commit `.talm-preset.lock` so the baseline is shared across your team. diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 00000000..af440d30 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,31 @@ +/* Cozystack brand palette. Both schemes declare `primary: custom` and + `accent: custom` in mkdocs.yml, which is what routes them here. */ +:root { + --md-primary-fg-color: #3d6ddd; + --md-primary-fg-color--light: #5f86e3; + --md-primary-fg-color--dark: #243f80; + --md-accent-fg-color: #3eaf7c; +} + +/* On the slate background #243f80 is too close to the surface to read as a + link, so the scale shifts one step lighter. */ +[data-md-color-scheme="slate"] { + --md-primary-fg-color: #5f86e3; + --md-primary-fg-color--light: #c3d2f4; + --md-primary-fg-color--dark: #3d6ddd; + --md-accent-fg-color: #3eaf7c; +} + +/* Command names, flags and Talos document kinds run long and are full of + hyphens; breaking mid-identifier makes them unreadable in the narrow + content column. */ +.md-typeset code { + word-break: normal; + overflow-wrap: anywhere; +} + +/* Rendered machine configs and discovery comments carry meaning in their + alignment — let them scroll instead of reflowing. */ +.md-typeset pre > code { + overflow-x: auto; +} diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..5c07ce68 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,156 @@ +# yaml-language-server: $schema=https://squidfunk.github.io/mkdocs-material/schema.json + +site_name: Talm +site_url: https://talm.cozystack.io +site_author: Cozystack Authors +site_description: >- + Manage Talos Linux the GitOps way. Talm renders per-node machine configs from + Go templates, discovers each node's real disks and interfaces, and applies the + result with the flags you already know from talosctl. + +repo_name: cozystack/talm +repo_url: https://github.com/cozystack/talm +edit_uri: edit/main/docs/ + +copyright: Copyright © 2026 Cozystack Authors + +# docs/manual-test-plan.md is an internal QA script, not user documentation. +# Leaving it out of the nav is not enough: MkDocs would still copy it into the +# site and index it for search. Patterns follow the gitignore format. +exclude_docs: | + manual-test-plan.md + +theme: + name: material + language: en + logo: assets/logo.svg + favicon: assets/favicon.svg + + # Brand colours are not in Material's named palettes, so both schemes use + # `custom` and take their values from stylesheets/extra.css. + palette: + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Switch to light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: custom + accent: custom + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: custom + accent: custom + toggle: + icon: material/brightness-4 + name: Switch to auto mode + + font: + text: Montserrat + code: Roboto Mono + + features: + - content.action.edit + - content.action.view + - content.code.annotate + - content.code.copy + - content.tabs.link + - navigation.footer + - navigation.indexes + - navigation.instant + - navigation.instant.progress + - navigation.sections + - navigation.top + - navigation.tracking + - search.highlight + - search.share + - search.suggest + - toc.follow + + icon: + repo: fontawesome/brands/github + edit: material/pencil + view: material/eye + +plugins: + - search: + lang: en + # The CLI reference is generated from the cobra command tree, so its page + # list changes whenever a command is added — including on a Talos bump, since + # talm wraps talosctl's commands. A glob keeps that out of this file. + - awesome-nav + - git-revision-date-localized: + enable_creation_date: true + type: timeago + fallback_to_build_date: true + - minify: + minify_html: true + +# --strict fails the build on WARNINGS, and MkDocs reports a dead anchor, an +# unrecognized link and a page missing from the nav at INFO — only a broken +# link to a PAGE warns by default. Raising these three is what makes the CI +# gate mean what it claims: a cross-reference lost while splitting a page +# fails the build instead of shipping. +validation: + anchors: warn + unrecognized_links: warn + nav: + omitted_files: warn + not_found: warn + +use_directory_urls: true + +markdown_extensions: + - abbr + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - tables + - toc: + permalink: true + toc_depth: 3 + + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.magiclink: + repo_url_shorthand: true + user: cozystack + repo: talm + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + combine_header_slug: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/cozystack/talm + name: GitHub + - icon: material/web + link: https://cozystack.io + name: Cozystack + generator: false + +extra_css: + - stylesheets/extra.css diff --git a/pkg/commands/upgrade_handler_test.go b/pkg/commands/upgrade_handler_test.go index 454f9883..c0024f6c 100644 --- a/pkg/commands/upgrade_handler_test.go +++ b/pkg/commands/upgrade_handler_test.go @@ -443,26 +443,25 @@ func TestWrapUpgradeCommand_BadReconcileWindow_FailsFastBeforeOriginalRunE(t *te } } -// TestReadmePostUpgradeVerify_NoHardcoded90s mirrors +// TestPostUpgradeVerifyDocs_NoHardcoded90s mirrors // TestPostUpgradeVersionMismatchHint_NoHardcoded90s for the -// operator-facing README. An earlier copy claimed "waits 90s for -// the node to finish booting"; the window is now operator-tunable -// via --post-upgrade-reconcile-window, so the README must reference -// "the configured reconcile window" rather than a literal 90s. -// Pin the absence of the literal so a future README edit -// re-introducing it fails this test. -func TestReadmePostUpgradeVerify_NoHardcoded90s(t *testing.T) { +// operator-facing documentation. An earlier copy claimed "waits 90s for +// the node to finish booting"; the window is operator-tunable via +// --post-upgrade-reconcile-window, so the docs must reference "the +// configured reconcile window" rather than a literal 90s. Pin the +// absence of the literal so a future edit re-introducing it fails here. +func TestPostUpgradeVerifyDocs_NoHardcoded90s(t *testing.T) { t.Parallel() - readmePath := filepath.Join("..", "..", "README.md") + docsPath := filepath.Join("..", "..", "docs", "operations", "safety-gates.md") - body, err := os.ReadFile(readmePath) + body, err := os.ReadFile(docsPath) if err != nil { - t.Skipf("README.md not present at %s (likely a vendored source release without the repo layout): %v", readmePath, err) + t.Skipf("%s not present (likely a vendored source release without the repo layout): %v", docsPath, err) } if strings.Contains(string(body), "waits 90s") { - t.Errorf("README.md must not hardcode 'waits 90s' — the post-upgrade reconcile window is operator-tunable via --post-upgrade-reconcile-window; replace with 'the configured reconcile window (default 90s, tune via --post-upgrade-reconcile-window)'") + t.Errorf("%s must not hardcode 'waits 90s' — the post-upgrade reconcile window is operator-tunable via --post-upgrade-reconcile-window; replace with 'the configured reconcile window (default 90s, tune via --post-upgrade-reconcile-window)'", docsPath) } } diff --git a/requirements-docs.in b/requirements-docs.in new file mode 100644 index 00000000..d34e73ed --- /dev/null +++ b/requirements-docs.in @@ -0,0 +1,20 @@ +# What mkdocs.yml loads. This is the SOURCE; requirements-docs.txt is the +# compiled lock that CI installs — edit here, then regenerate: +# +# pip-compile --generate-hashes --no-index --output-file=requirements-docs.txt requirements-docs.in +# +# The lock exists because pinning only these five leaves the ~35 packages +# underneath them floating, and one of those owns the output: python-markdown +# ships the toc slugify that decides every heading anchor on the site, so a +# release changing it would silently move every deep link. + +# MkDocs core +mkdocs==1.6.1 + +# Material theme +mkdocs-material==9.7.7 + +# Plugins +mkdocs-awesome-nav==3.3.0 +mkdocs-git-revision-date-localized-plugin==1.5.4 +mkdocs-minify-plugin==0.8.0 diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 00000000..6a0a08cc --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,688 @@ +# +# This file is autogenerated by pip-compile with Python 3.14 +# by the following command: +# +# pip-compile --generate-hashes --no-index --output-file=requirements-docs.txt requirements-docs.in +# +annotated-types==0.8.0 \ + --hash=sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7 \ + --hash=sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0 + # via pydantic +babel==2.18.0 \ + --hash=sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d \ + --hash=sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35 + # via + # mkdocs-git-revision-date-localized-plugin + # mkdocs-material +backrefs==8.0 \ + --hash=sha256:4a627b817fd2dce43b79ab48da63613340509381cd8ce0897078a0bce79a2ab8 \ + --hash=sha256:601ce68ca12385dbda06ce264406b4c4210cf5b79fd0fd627592365c92f29a88 \ + --hash=sha256:87f0fae8c5f207fe9f4b2887efc71d42f4900ac78faa1af08d675ef303692dc5 \ + --hash=sha256:9ec96efa080938be92323e8e730e57718c9c88eb15ad70bbef4e1766df591408 \ + --hash=sha256:b556cd7d36c3a3a2f256b89590b176b8eddfb73bcfaee3a3ddd84ea66d21ce50 \ + --hash=sha256:f0c35cf0102ba6b6070c12a492be3c1c1d3f5839529784b9a9565d6d04569a01 + # via mkdocs-material +bracex==3.0.1 \ + --hash=sha256:4e38e32392e4a4780fe15d644bfc7c8514057cfc3861e060b11814ce829c25e4 \ + --hash=sha256:6523ad83aeb5098a4ee597cff0f964442ff74e460bd3fafaffab6a013ff2288c + # via wcmatch +certifi==2026.7.22 \ + --hash=sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 \ + --hash=sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55 + # via requests +charset-normalizer==3.5.1 \ + --hash=sha256:00668ebb0609751758682eb0b5857e7c35b9f00e84dfdef062e103244ec94d45 \ + --hash=sha256:012a22b88a77ca2e59b98ac5889b0deb604147666032f45e6d6e217634d2550d \ + --hash=sha256:01e93745f7f219b703b60ba7afead36cfc4242782be5af484673fc500df12da5 \ + --hash=sha256:04368edf83514385ffc3e1cfd4546e595f4f1272dd23ba437a93a9cc3741d47b \ + --hash=sha256:0722590aabf9dc6a6c0343d523c05458fa2b5047dbe6302fd526bb570600753f \ + --hash=sha256:07ffd07412fc5d5e84cd8952acf9ff7e4ed7a708e69d1bada19d8ba91711353f \ + --hash=sha256:09a7bba9f739468c8e78c36a75c33768e53cb1959fc638f510454c14683f00d5 \ + --hash=sha256:0b2b1b3fa5670c127b246df1d0c059defd41f689a868a3b9d79df9b1cac42d22 \ + --hash=sha256:0c6dfb5ca6723eeed15aa8e564a014d69fcb8812f94eef11fe3631e0508199f5 \ + --hash=sha256:0d929fc574b4d6fd9e7c0f5c2ede8716a41911923aa7fa5fce38e0818aa4a1ac \ + --hash=sha256:13e3afe97712e8887cd516e960c63f0b93122971e5b5e4b2622fe7701771e838 \ + --hash=sha256:15f024313246a4ed976c60f440bb8d257815513a681d212ff74fd46f7d715a90 \ + --hash=sha256:195ce897c6153c0700078142cf8efe3e6454ca4cf4357499e4078dfd83396626 \ + --hash=sha256:19a3dd5aa73cef1c99687c4fc57db016a9c17104ae1185da88ba566a5d3bebe4 \ + --hash=sha256:1d1c7a53a6c2103925cdd6d7229f8c567379f211c869793df679f2e9f738c369 \ + --hash=sha256:1f5883d77fd409a261abb5dc8ccbe335720d798b1de4abb3b1d47ccbbc76b53b \ + --hash=sha256:21b82d8082f6f5e7f456ef0bd16323d08de1266efbfeb476e64b2a91d1471a4e \ + --hash=sha256:252d099029bcbea642f2a06c4ed5046bdf8b5a8150b64afa5e027e88b106e5ee \ + --hash=sha256:256dd4d85d9e4dc595e2bc983c980e73f62ddeb3165c58b4c3dfe78c5c8548c1 \ + --hash=sha256:26422d45fd13551cf564c58932f7d72b4f58b93b0fcf18c35ba6be12b46bb102 \ + --hash=sha256:2679de311c7946dde5d3b6f44941844133ff5c7cb86099c0061ab1e8901c20a8 \ + --hash=sha256:29880d17a8eb0b5cfdfd8944b468322928059aa35f1f5fa8ff22b149ec0b42f8 \ + --hash=sha256:2bced4061f000f7187254a02ad3433ae17eaf991747ceea2f478422590a5bba9 \ + --hash=sha256:2e9cf9253119d8e5d111f05d71626786fd3d6193817316eab1ca088cdb8593cf \ + --hash=sha256:2f06b7eae9dbe77fe1d644ca244dad508de8d302870a43f3c559b521270938a0 \ + --hash=sha256:2f293479cce755c75f1697e87c409b7ae4c555c7dfecb6e988ad13abba943031 \ + --hash=sha256:329fc3ccb63ad22d867d84c2adea759a64079a37ba4a343433b02c7a2816871e \ + --hash=sha256:343fb4f2821043bd87095f7b08a1a181febc8e36ac64212143bbfd0a0e1bc235 \ + --hash=sha256:3588e376b3ea2eea84976f67273d679f229e24c66dce7b82ae45aef04ff6e072 \ + --hash=sha256:35aea775dc2bd5f54cd84a1cd2696cc3207c479cb9cf0bd346f0d343e4300ddb \ + --hash=sha256:35fe081843b35aad20ffeccec3eeffbe637b15d14f3fb22cc1b59cd8ec17e93c \ + --hash=sha256:36047af20e17097c3bb9476c2b7655f2f7aa51322c0ba58c07695bedf755a950 \ + --hash=sha256:3617ac3cfd8b9888f145ad89dd6e692285834b0201c6074a5eeaad3fd4d668c2 \ + --hash=sha256:366ec70f5547c640d3ce1985722490f23faf4eb5216a7eeba78277490e78dacb \ + --hash=sha256:394fea06235c8543390050ed5f529187074b029fb027213f6c46ac11ab5d950e \ + --hash=sha256:3d27167433c0d5f18dc850f07d0b3816221984fecdc405d6c157a6f0b8f8e9e6 \ + --hash=sha256:3e5e1224c0a6a90e05843e07adfec669edebec17801c67072f51e59561d63c0b \ + --hash=sha256:41876ee62a3dddf48ff1121ad8f0798032aa03f2fd35f21f34a4cab14f18d8d2 \ + --hash=sha256:433c5a81eade63b47e522303bad236f59dba55ea6951746f5558355eeed8c75d \ + --hash=sha256:4582c27e8c889d64811987b5967fbd3ae0c823fe1fd933b543d55ac20bb475fa \ + --hash=sha256:485a0d363cafefcd2538a73c7c838daa2035f09b2c9f9b5e3133f80c6aeb84c2 \ + --hash=sha256:494b70049a4d69aec6e8137c13af4cf8db8c9f9820a1392ac293b0dd2987a818 \ + --hash=sha256:496846868fea80e479324862fa877f02411f2fd0f83b79ccee2607aa68b2a032 \ + --hash=sha256:4abdc5f9ad448c1ecbfae2974b820535d6bc6e7eef63babbab3d81cf46968c71 \ + --hash=sha256:4b599739b93b2cbeded49645ae3c8d1405c29ddfbceac1545c87a3f9580a9e96 \ + --hash=sha256:4bea7f8ebe90bbd7f0e4a2de42ca6924ba23e3e76418c408ff82f1d46fabd687 \ + --hash=sha256:4c4fb141a727957c93edfe5c32a26ceb6b5f6461d67146e2d39f51e16170bea8 \ + --hash=sha256:4c9548dc78002099910abaebc0a72ac58b7d30931869e0351c09b507dff4ece3 \ + --hash=sha256:4d26f14f041e83dd8edfd61f4cd4fa7285d31798b5bf1f28e70c367ba6c41d61 \ + --hash=sha256:4f298bdadb8f0b9e5672877f647d1be9373ef5320c9e2f049795e26cad28b6a9 \ + --hash=sha256:52ec005752a56ae79547a05c0139ca2501a0c866390b6115008456b9f0e7cde1 \ + --hash=sha256:55261ac0d2941c42f196dd576f543d87a8ee03cd6f5e30dfb4d807b2e3b9121a \ + --hash=sha256:56490c595a28b1bb27dfc583e816152a9767721ef58b2c03b13f954d2f707420 \ + --hash=sha256:58d3e12c88e0950bca850ae1f7c256055c097639c2edb9eb123af9807d8b15e4 \ + --hash=sha256:58d4aa13a59c969dbfdf9e6a9560e242cbfd9e8a8f50c2747714df1a423adf65 \ + --hash=sha256:59171c6e45bf07d0d5cab3b0bf81d945035530f6873398b3b531c31184d46663 \ + --hash=sha256:5b6d1386bf0096d26d3a863dc0a487a5b4eb9aa93cf5ba69683d29dde6b9d60f \ + --hash=sha256:5c0ea61a470e070686aa30892fed79e297d2c8d0ab46b8bcdf027d38c51da591 \ + --hash=sha256:5c84bec0ab5ae0c64bfe73a7d2adcb5ce73b467523fc27fd6a28ab2aa6cbe35a \ + --hash=sha256:5ca0555312ae2fe82715cada7fac375530c2f3349e1eaa1bcb33d0283ac79a18 \ + --hash=sha256:5d8531a6569d025f68e2321e7638fb7978f23db58e5f69f56913837aae03816e \ + --hash=sha256:5e2d0e146dcb57034f8b97dc58d2d512cb90aba253960ce449f695fec6a82c6f \ + --hash=sha256:5fc45d653ea8c9a20479167e11d4a0f8cb2fa3470737ab6f9c827532313187b7 \ + --hash=sha256:6117b84ea48435e5356dc737f5121485c30920ba43375fa7b434fd753df0eac3 \ + --hash=sha256:6199d5606e2bbf2b096cf64d03f8b6790c91081d5ac866b8e7bb6422738cc60c \ + --hash=sha256:62b55f6722735a6c472f88361cde6640608773d9443cebdbb51abf436a1fcdd3 \ + --hash=sha256:687c9ca3035544b113bea2055e180af96fb63c0c476e22a9180f51925186e7b7 \ + --hash=sha256:6b7430cf5728e68f6c462254009a6ef4086e1bea43cf2f57aa9c55fb4f50ff96 \ + --hash=sha256:6ba32c4d2abf1d2fe7cf27d280f4cca5664233b0f885549c7761719eb977f486 \ + --hash=sha256:6c9cdde8becb25a7fde49924511aa2644d6f8081cc8df8e9452724303348d8e3 \ + --hash=sha256:6df0ec430f9a831772c23ca5a224cba36517a58a84bb32c32bb59a9fa67c47f6 \ + --hash=sha256:6e2912d4babbc65196ac13c2f53468dc57fb8b9c25ef913e8c59ddf7c6dc0e1b \ + --hash=sha256:6e5e4d73d588ca5ed09df1b7dcd1b203d1df3c542e3f50d126c947d432b10731 \ + --hash=sha256:70055ff39b97c99e7ae40ea3e393fb62aa2e44dbd9b29f8d14f42fb0025c3959 \ + --hash=sha256:706bfd38730a5ac7a365793269a00f4e988178cec121391f4248d84ad8c972e9 \ + --hash=sha256:7235dc28fc6dd9d832ac7c7bce95367dedb85929f17368a0c2bee1e080b9acbf \ + --hash=sha256:774d157f112367ff4abd29019f38f023c24e00e56edc7829c20e358a5a913ad8 \ + --hash=sha256:77efcff2b23071c349402ac1066667a3d011f62398d81408c9b88ad991747c9e \ + --hash=sha256:789b8982559ae28dad2356519f841655756cdcd96616410590ae0b17454ee64f \ + --hash=sha256:7ac76cf9afd34929d76eb7fcb63be476a4853d8a96f0dcf2d0db68a0cbdf9885 \ + --hash=sha256:7c0c10730342b0c9b35dd1d619beb8214e520bd96a1f870f452680b238aab3e0 \ + --hash=sha256:823f82903d189af463d7df250ef1f7f696f3cee08cc8d91deb565e8d425f6506 \ + --hash=sha256:838648accb3a7fd9803fd45c87bce8509648eb0c11bc34e216141300977244f2 \ + --hash=sha256:854066be00447fa8de2ccbbe893e2ffc4b123ef16d897af794c1e18bd4a714b0 \ + --hash=sha256:85d5855daafc240cc045c026d7a15fd198a09b0fc8ff6f5ecbb5297b509cb11e \ + --hash=sha256:85de3134b5379856e323ba37c19c9256d39425f7b76a63af52b09fb4664c2e8f \ + --hash=sha256:87e4f41d375c0b9be2fb5251aee4b8a689169e134535aed81bf085c3b647451e \ + --hash=sha256:88ca277405c2d3b71c4e1c2ee0e7966e807bcba86a69d11e19ba199d18ae4491 \ + --hash=sha256:88e85ab89cb822c1e635f51d6d32e488f94e002e70e2f492bdb8b945543f345a \ + --hash=sha256:8ac8c94b6539074e0f40899301273ac8402b9b3e01c7b7ba269ff30340aaaf20 \ + --hash=sha256:8fe532b3c966d1fb794e0698e4589d0444017ae77fc0b31edea13c0e35bcc449 \ + --hash=sha256:9085f87b0e38a2b92b8923059b4e8789fe40d9279712d15dcc670048d77079af \ + --hash=sha256:90b7481fb62fbe172c558bc6fd1c4c98d82004a54a7551f20e11ac9bf0b8708c \ + --hash=sha256:92caef967d287a407085d61176fce4012b1dd62daed4eb6d5ceb26d3d2538712 \ + --hash=sha256:9362dd90aa7dab48c0054a21187791ccf05473f7dba5d92b8033ae62164675e7 \ + --hash=sha256:94d78ecec2605a8d0398b0f365d5f12a63248438516f5dac536a5eff7337df4a \ + --hash=sha256:94fbf1c0c6cc0d3d5e50f9a9313a8cdca90dd696d34b381cd1704f8c9e939f20 \ + --hash=sha256:950f23cb393f85543777b0433f082cddd25b51ab398eac7971146495679efe5f \ + --hash=sha256:96eefc178f8636b9c760c5829345307fd81cfae9ab1e80997dbddeb0f54ee9a3 \ + --hash=sha256:96fef3e886d6a9874b14f27fc193fbdc69d5d8035783d86aa4e1cea594e695f9 \ + --hash=sha256:977cdbd483a9cff38179bea4fd754289a6f2195c7abd414aba85410b3e66cc5e \ + --hash=sha256:978eab16f55b4ab2c2a745be9a0a840bf8f09a7f227d9c76eb30214d078865a5 \ + --hash=sha256:994e883d17c559cdfd38c84003c8b27d25424a1077272a17e7cd27bfe0bf57b2 \ + --hash=sha256:9ac4444d8d4fd4c4bd08bf451ed3167aa9e7ec6cdb41b648794f1d1103652e36 \ + --hash=sha256:9b5db6052055d34d41230fb78d7c439c23dc536a9896f6cb039e8dd92cfc1263 \ + --hash=sha256:9d9a0dc7cbe9bec24c3f767c9122c41fe5a1bc43f47cd099d00d393e09769de4 \ + --hash=sha256:9dbdd9205662134957cf0c324f639bdc5031c0ca056e2369e238db75187c0f11 \ + --hash=sha256:9eea3ab2597a5e65fe65296e2d6a84570845a6b55532d90333d740d48bbc850a \ + --hash=sha256:a2028475ba855475b8b4d3cfeb4994269c967aea8b9892dfba907f4263a863a3 \ + --hash=sha256:a3a370082ce34d0612f421e15fe011c53bb1feff21a26d06ad4fb244dab5a375 \ + --hash=sha256:a545775cfe815855ea32d7c27731d79da358ef2055b4a25830231b1622dd18aa \ + --hash=sha256:a5cbd90ecf0fc62e64726917ad083b73001f0563657a87ec3c0b504e277dc90d \ + --hash=sha256:a6d095662e73e74f0a49988e0593373e243e3a52e27bfeea0a859e88acf4a0f5 \ + --hash=sha256:a6dac12ff6b846103483683f60c5f8fee205121adc58ffd87e90a90a3af69e99 \ + --hash=sha256:a951ad59cad9145664a730d3036b40b844e74d2d3683da40111463cd3a83845d \ + --hash=sha256:aa1099b956fb795e686d073568f6dc002a0bb89765ea6d5b055dd7d9bf1b116c \ + --hash=sha256:aa2bb0b37202dca27175591f761108b5d34096ade1191ffe4808bdf6b1571488 \ + --hash=sha256:aae2ee51122d3ae968a3837d97dc24a0aeebb0dea23694422cd172bd30017cd6 \ + --hash=sha256:ab743e9bc90c1f73552ec33e10e3331315acd2c397b36065b591b0181de533cc \ + --hash=sha256:ac00177c4831ffa650f8609e4bdddd5fe09c03b1c0c47acece7e6ea20421598b \ + --hash=sha256:ac13b004224fb341e1e25a1ed5e19d32f57cdb2a403e01f003b46f051a550f6f \ + --hash=sha256:acaf604462bf330b0d07e7a07c1d6e4adac79e5fb13e9c5140590542cafacc00 \ + --hash=sha256:ae31a1a1db2ee6cc2942fccaf695c934bc7f3db9f2133a3fef1f367cf1a4ab10 \ + --hash=sha256:ae4a097991662cd4fff0ddc74e0fe7874f82e00042fa0ea00855645ed0c79598 \ + --hash=sha256:aea996a6aba25260827c9ea511d1addfde2da9eb686ac961838509086188b7e6 \ + --hash=sha256:b39b69b347e5e47a3b5b8cfc005c68c1ba347474e3960236c4944a8ecd174962 \ + --hash=sha256:b54e7e13267d49ffbfe68e25b3cbd774dab38fa37238f71265e91b36146eb21c \ + --hash=sha256:b9af956078716df40d985fb0dfeb2c2120c5ca92ba4ff4b388acfd01cdc14d08 \ + --hash=sha256:ba2f37ee79e6338845261a3c5b1784e5d1acdff2c0785b284f1b633033d136ab \ + --hash=sha256:ba501e667c17d8411f98e67a022d9604ef179aff0e459b7e292c796837c13573 \ + --hash=sha256:baf3775a2635e5a11fbd5e4e64ee69c7e86875d224a5c72aca4c141064589a90 \ + --hash=sha256:bb57753e36e4855b8ca375069482250a6246372331a3e4f3407eaebb007443f5 \ + --hash=sha256:bd6c173f04743d483881bffa1478d5a4624475b8cd1d2194956a75548e191c18 \ + --hash=sha256:be47f99644b208bff7766314013f9acf57b056b04191d570d68ad14022cf5b1d \ + --hash=sha256:c010f5581d9c612804cc59fcf7b524b707fbcb72828551237ab545bb5c7034af \ + --hash=sha256:c1dcc36dcb96abc02236e182d17e0f71430152a6c2c7447421da2d2dc144edea \ + --hash=sha256:c428c6c31eb5f4277d7f8eccaf767fbd548ddd5ce3c8b4f4cbbfab3d96b5904c \ + --hash=sha256:c658c50ac0c98cd755a2dd50b7977d3bca7df401dcc47fbdfa87db53ef7d4e8b \ + --hash=sha256:c71fb0d56c920c269cd3e2e3fe7c610e3f1fdb21a6ce60efa6430ff63676cea6 \ + --hash=sha256:c7b742bf31c88566b4bb6335a7f393bb322e580b6bb98df7bd0c25e6e3519ce8 \ + --hash=sha256:cc0329df4caaceb950d2f580b5ac716a377f7059624a0bafaeaf8a218c6ed774 \ + --hash=sha256:cc5d36d96478aa9c60654bd932525bf32964c62a7281eafdf16d85003a8d6004 \ + --hash=sha256:ce854f5f478050ade5a238731c4ca985a7d3b3cb53ff600a9b5c3b689b5f0a7a \ + --hash=sha256:ced3fdd71aaa83ce593746c2edb42b7a59cb4c19c8b5c407781c72e493aae55a \ + --hash=sha256:cee5dd7c6fb5dd52a0fe2a740f9bc6e3593f5f8b1788bde49de02086f30182b2 \ + --hash=sha256:cfa1c0cc3a8f9f53f1243a5a99ac36fd003880199383b37672e86ddda9cb07e2 \ + --hash=sha256:d1ee1e296209fdce05b81b663250eefa02213a2da7b41bf26f7829b8ba3545aa \ + --hash=sha256:d59b75732e9b6f27388e10c14b0259cc5f2e48c78627d185e6a177b58ad3cffe \ + --hash=sha256:d63600d620ad0064c3a748b950ac5ea38a80190e5498532efefa4b7b3f1da1f3 \ + --hash=sha256:dd732602a7009217f658d5863d12d79d373a4de0eebc111094bcdd3bb8e0a6cc \ + --hash=sha256:e06efa066f7dbadbc84ebc126a97c452a6451dfcf589d89d788484949e1cf795 \ + --hash=sha256:e199fb99720074809a7720f1c0b4d919eea8b87e88713e0f8f602f7bef543d9d \ + --hash=sha256:e4b018dc5a0eee4676e38fe84a47a427816c590b93b55d9025274ec4d6ffc2dc \ + --hash=sha256:e6621fb2a4988d6e53eedc455e5903e2679f3967b8acb3d639f1b63c14a2e893 \ + --hash=sha256:e71c909f353863b2b89c83de2ebed71ea6d0df8a6ef65a128193c5e650766bef \ + --hash=sha256:e90251c0c7bdd54a100a0dce3c07b7e637278c93af29dbf78ebb89a58c4bac7d \ + --hash=sha256:e9fbdce1e47394b09bc9f26ab117dfc8d6491977a11d86f592bb42c779db2fda \ + --hash=sha256:eb12fb2ba69ffa05f8695f61c69e591dc4b4a12ac3757ac8af8adb259bf56d17 \ + --hash=sha256:eda059b6bc8bc0812d626fd91a7ce01bf583df0a61296eff390fd94141a34e30 \ + --hash=sha256:f03ac127268b43ef4fe9e6ab6794a6794b49485a0cc0c1db79876d2f33f75bc7 \ + --hash=sha256:f298e218441525d3794428b4c8b8fb8662c6d3ea79925d4807ee6b9a96a3bca5 \ + --hash=sha256:f5542f9b941279d82d41eb0aa9f98eba36fe4df5c7086c651df7944935b37182 \ + --hash=sha256:f6f7deae3feb4edfa2efaf7c574fe88cbf055038a6abdb40188e4fff66d5699f \ + --hash=sha256:f9b1e28d0e8dbfa858abdba91d6b547beaf2df1a59bec6da6faae7b96a4991a9 \ + --hash=sha256:f9f8405c2c758532c74fed975dbee57be1f31a6e865c031870c79a6ed3212ada \ + --hash=sha256:fa48b1b63d639f9483e0633e092f5851e2348c352f1f9bb6c8182f87884ef876 \ + --hash=sha256:fb78f6e7fcd8ad785d28cd577168bc1aaee827b25bb8755638f694794ea98f0a \ + --hash=sha256:fbc597639158fd7c14d55e808718848319540f51b0e6746e3eefa59723a4a348 \ + --hash=sha256:fce8cbd4997efeb450bd298b54f755dcdff18d496f7a5ddbb4867c6d7c88fdc3 \ + --hash=sha256:fd0350afdc3aabd5576f60ea109228bd5538139713c7b094c5cd27c73a98bc6f \ + --hash=sha256:fd0a274c0e5f9a21565cd9d3dd749b61f96b7aa1e20a93aa1ba4029518f2e5c0 \ + --hash=sha256:fdb8a068947befafba9952162645dc2fecaeb400e64584829ed5e9b2fbe21a7f + # via requests +click==8.5.0 \ + --hash=sha256:255bc9599cf7748b4b1a446ccc735421bd08a2ae529a8b88597d3de5664ee360 \ + --hash=sha256:ba0d2089de75ea0310e2dde03160e6ca10009947fb95a182f9b54021bb272e34 + # via mkdocs +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via mkdocs-material +csscompressor==0.9.5 \ + --hash=sha256:afa22badbcf3120a4f392e4d22f9fff485c044a1feda4a950ecc5eba9dd31a05 + # via mkdocs-minify-plugin +ghp-import==2.1.0 \ + --hash=sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 \ + --hash=sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343 + # via mkdocs +gitdb==4.0.12 \ + --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ + --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf + # via gitpython +gitpython==3.1.61 \ + --hash=sha256:8ab28c9da863cdd9e7d7694ec46cf3e6c9a12d8a30a1acd3447aec11975d530c \ + --hash=sha256:f51c24d8c0f733a195447385f5774a5dfe8767f5acfd7994a33755644c6ecc95 + # via mkdocs-git-revision-date-localized-plugin +htmlmin2==0.1.13 \ + --hash=sha256:75609f2a42e64f7ce57dbff28a39890363bde9e7e5885db633317efbdf8c79a2 + # via mkdocs-minify-plugin +idna==3.19 \ + --hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \ + --hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4 + # via requests +jinja2==3.1.6 \ + --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ + --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + # via + # mkdocs + # mkdocs-material +jsmin==3.0.1 \ + --hash=sha256:c0959a121ef94542e807a674142606f7e90214a2b3d1eb17300244bbb5cc2bfc + # via mkdocs-minify-plugin +markdown==3.10.3 \ + --hash=sha256:3589362618f743188b4d955b874402bc814f4f83f544dc207719f4baa7d9c45f \ + --hash=sha256:fa6c92a00a4a3c98b22728c64a935ae1928250ae65058a6ded814d2cc29a4cea + # via + # mkdocs + # mkdocs-material + # pymdown-extensions +markupsafe==3.0.3 \ + --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ + --hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \ + --hash=sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf \ + --hash=sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19 \ + --hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \ + --hash=sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c \ + --hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \ + --hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \ + --hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \ + --hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \ + --hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \ + --hash=sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26 \ + --hash=sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1 \ + --hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \ + --hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \ + --hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \ + --hash=sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695 \ + --hash=sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad \ + --hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \ + --hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \ + --hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \ + --hash=sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa \ + --hash=sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 \ + --hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \ + --hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \ + --hash=sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758 \ + --hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \ + --hash=sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8 \ + --hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \ + --hash=sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c \ + --hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \ + --hash=sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a \ + --hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \ + --hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \ + --hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \ + --hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \ + --hash=sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2 \ + --hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \ + --hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \ + --hash=sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50 \ + --hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \ + --hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \ + --hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \ + --hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \ + --hash=sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115 \ + --hash=sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e \ + --hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \ + --hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \ + --hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \ + --hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \ + --hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \ + --hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \ + --hash=sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b \ + --hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \ + --hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \ + --hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \ + --hash=sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d \ + --hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \ + --hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \ + --hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \ + --hash=sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f \ + --hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \ + --hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \ + --hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \ + --hash=sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c \ + --hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \ + --hash=sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8 \ + --hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \ + --hash=sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6 \ + --hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \ + --hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \ + --hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \ + --hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \ + --hash=sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7 \ + --hash=sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 \ + --hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \ + --hash=sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1 \ + --hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \ + --hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \ + --hash=sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42 \ + --hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \ + --hash=sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda \ + --hash=sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e \ + --hash=sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737 \ + --hash=sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523 \ + --hash=sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 \ + --hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \ + --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \ + --hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50 + # via + # jinja2 + # mkdocs +mergedeep==1.3.4 \ + --hash=sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8 \ + --hash=sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 + # via + # mkdocs + # mkdocs-get-deps +mkdocs==1.6.1 \ + --hash=sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2 \ + --hash=sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e + # via + # -r requirements-docs.in + # mkdocs-awesome-nav + # mkdocs-git-revision-date-localized-plugin + # mkdocs-material + # mkdocs-minify-plugin +mkdocs-awesome-nav==3.3.0 \ + --hash=sha256:330edf4129995a7be8a9751edd8739d312fddf591c6cbd95ec80f12f4bfe8578 \ + --hash=sha256:bf80f14bff9571df79129bbdf103b4198589ee7616f8a29720ae2e7ac2455930 + # via -r requirements-docs.in +mkdocs-get-deps==0.2.2 \ + --hash=sha256:8ee8d5f316cdbbb2834bc1df6e69c08fe769a83e040060de26d3c19fad3599a1 \ + --hash=sha256:e7878cbeac04860b8b5e0ca31d3abad3df9411a75a32cde82f8e44b6c16ff650 + # via mkdocs +mkdocs-git-revision-date-localized-plugin==1.5.4 \ + --hash=sha256:07a785522008e881ff4c307e3259ad3ce00931b2d2147a22cdfbb532ff25e4ab \ + --hash=sha256:b5e6b4b9e7d169750b6eb078fd91151bc855e65c019a065accce537ec6e69e05 + # via -r requirements-docs.in +mkdocs-material==9.7.7 \ + --hash=sha256:8ea9bb1737a5b524a5f9dcf2e1b4ebda8274ae3008aa7845720a97083bef708f \ + --hash=sha256:c0649c065b1b0512d60aad8c10f947f8e455284475239b364b610f2deb4d0855 + # via -r requirements-docs.in +mkdocs-material-extensions==1.3.1 \ + --hash=sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443 \ + --hash=sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 + # via mkdocs-material +mkdocs-minify-plugin==0.8.0 \ + --hash=sha256:5fba1a3f7bd9a2142c9954a6559a57e946587b21f133165ece30ea145c66aee6 \ + --hash=sha256:bc11b78b8120d79e817308e2b11539d790d21445eb63df831e393f76e52e753d + # via -r requirements-docs.in +natsort==8.4.0 \ + --hash=sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581 \ + --hash=sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c + # via mkdocs-awesome-nav +packaging==26.3 \ + --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ + --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c + # via mkdocs +paginate==0.5.7 \ + --hash=sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945 \ + --hash=sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591 + # via mkdocs-material +pathspec==1.1.1 \ + --hash=sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a \ + --hash=sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189 + # via mkdocs +platformdirs==4.11.7 \ + --hash=sha256:4f41487eeeeeb07f3a6625e61d9bc0ae6809f92d3386dbd74392fbb76108104d \ + --hash=sha256:8a02cb259042c79d1cd0450facc2fe6dc9d303ae7901afbe33bf8ea0b188cef6 + # via mkdocs-get-deps +pydantic==2.13.5 \ + --hash=sha256:346a034f080da3755d8e9cb5e00e8b07de1d39e4f6e2c87d8ab7cafa0b269a73 \ + --hash=sha256:51a9c5f7b2f8e636f04c6cada605d9b6a3bf1348fdf945a3d8869b19bba0ee08 + # via mkdocs-awesome-nav +pydantic-core==2.46.5 \ + --hash=sha256:013d6f3483d81e02e7c328831808f336c8596ee33b4bd4026b9ffb1e960b8942 \ + --hash=sha256:03b9666e41e35d8909852ba191a0607520f81b74eaf12ccf8737005dbb313821 \ + --hash=sha256:045ab3b6d308439e32b81cc173bba5b9018bc6ed896afd0c65b3b009b1699af5 \ + --hash=sha256:0bddb4020d8f04175865ccd17eff3040874fc11fb593f424edb452653b4b947c \ + --hash=sha256:0cdbada856a1c69a7624a64d3d9aefe79300bd6ef827b43a4f265010b9b55184 \ + --hash=sha256:0fc5be0abd4a407e200d844b404e33639a554e7bd0d448e7b9ae181be4789ac2 \ + --hash=sha256:10416c15b8839ecc4ef4d0885da76da6fd0f67333a0eb8aff6d93c4b8f2910fc \ + --hash=sha256:15f4a94963c95accac15b7b657bb177d3ad82bb90b0d0526d9a9b85079925db5 \ + --hash=sha256:18a09e1e1011b462f2e32774f25859ef1223d5c2b0546a633cf56654710721e0 \ + --hash=sha256:193375f3548919d3f0b60936ca113ada3e38f264f91b9b8e0508efaad57be931 \ + --hash=sha256:1a353f84de772f423b5ffb11d7ae352fbbef0f446f3c0b0af0f8236d7233606e \ + --hash=sha256:1e449def1945a462c464331254e5a44fca7c3b4f9aedf59ec2f50f8066dd8e25 \ + --hash=sha256:1e5aad1220a1192c42341c8fd4a8686657e73ab2a920c970bdc4de334fe3193d \ + --hash=sha256:200aa3dc9f8d54f0754f43247c0bad0999fdcfbfd2488384dd44f37279271fe6 \ + --hash=sha256:2471fd51c61c610e1dcf7de44d7299283661654d11264ab4802b303368d69c47 \ + --hash=sha256:24922243639cbdac66c75fcb6fd6495a9cb52b213d62f9a0d16f0310b1ff8038 \ + --hash=sha256:28a6a556cd3b6066bea827857f9d9cce027c96f776e512f544a581f9e42161f8 \ + --hash=sha256:2bc9419666990c06d7397831f2126a1ecc3594aaa3ff7de5bf2d066802f4e07b \ + --hash=sha256:2cbd9a5eff05e51c447c34dfa4632145b26b09120cf04bd0c871e44c1a5e1c9a \ + --hash=sha256:2d330aaba8621b1edcec8ae2c4050f63b84ccf6d98723a8f212e9684713abf0e \ + --hash=sha256:2d5d76654becf5efd62c9e51c3756c67b49498b0c9a40884934c40807adbd074 \ + --hash=sha256:337639ba62a11acde6ef3aeb08c8ea755f8ef1fe5e513356c0f36a2b0d7568b0 \ + --hash=sha256:347ec774390c87326a2e4929d58d3f7e8763a104d5d35f4cd595a4c952366433 \ + --hash=sha256:356c8368cbc321050b169595683a2e1d63413b1e0e2868b330af9fc14c616d3f \ + --hash=sha256:37ae34309d7bd8c0d61ab839668058f2a7962ea1fc51d105d2db228fe0618034 \ + --hash=sha256:37ea7b83c935e5b0d68c9449b82651accf78a10828b2c02b2f2d9e9496446c21 \ + --hash=sha256:3a3e26b6a8274211bddee2d0e4d0d42778f17a34510f49d2ec44b58abfc41736 \ + --hash=sha256:3aa166e99c4f2985407fb8714aebede877ecb5455cf321b606adca926d30d5a0 \ + --hash=sha256:3d2652072b2d774947ba5cf78a9e59644ac62ee572daf6dd2e1dfe905e15b2b7 \ + --hash=sha256:40375c2d05acec10323e45dfe2077ac44bc74659008614af5069034e2cfc781c \ + --hash=sha256:413a717a410d0c817ef5b786a059415550b3794e1d0c2abffd9efb93a3d9f7b4 \ + --hash=sha256:46c25dda9d092a06c08db76ffe0a197107904d0dfac653f7d5306bbcd6d6119c \ + --hash=sha256:49776eab08766a08dfff7012f8b422dcd7e25e43b316eedf0477c24fcfa84b7c \ + --hash=sha256:4d44cf99ddebf875f9b68cc267aa684c99b7b44fe63ee1cac4ec163807290069 \ + --hash=sha256:4dedce55295becb61921e386b99d4f2706045306e7fa52249a33004c837379fb \ + --hash=sha256:4f8507560a9284e1370bb048ed4282012fbef4e8d109875b95e884d228552061 \ + --hash=sha256:4fdc8b93a41521988916eeaa271173fcca7fa0803d62f87675aac8dcec1c8e29 \ + --hash=sha256:5086029a57366b8cf81b130a43908738095c270c21a8d7f0e8bdfdb89718e2f3 \ + --hash=sha256:52e24eacdb536cade636aa90fb851835222becff8484b7001fdc78cb0290f2aa \ + --hash=sha256:53feb344243bb9510a9dec7bf3cf1b64d88a98af5dc7872a5160465f8b198c8e \ + --hash=sha256:545f26c504b27c3758439a5e6d9349931f0a04f855668d5fe323c89e82300a38 \ + --hash=sha256:54d510bac3ee52247af28ed4bb18a1e799f040ac60fd2bf5ccd4c92f1fbe786f \ + --hash=sha256:5cb482e9e84c851f4e623fe4acc1ced89168cf1fe18f7089db4548c8f5bbb65b \ + --hash=sha256:5e81740c09e310f5aa5cbd3e434a01c154d4bef93241c7877b39f211d2b78ba8 \ + --hash=sha256:5ee239d575f80b08eca11f6e20f90c4c695de7825c67eefe6091fbf20dda648e \ + --hash=sha256:5f194189415698233dd1114a093a9b56e61e2c57e11b469be3b0506f46f0771c \ + --hash=sha256:5f93c5fe914d75fbec9a49209b00da5f08e9e467d69da2b1510c81940cfd10be \ + --hash=sha256:657b40d6240c0a7b6a64b30f22d1e3aa631c7e846c621b0c0f6d1d75e2e15ea6 \ + --hash=sha256:6d30e1a4f138b8951063e9a394752a9179b51da288ffa507b1e659222f4c1793 \ + --hash=sha256:6f7b393a8b3da82f5c1fc0751e6d01ac6c55b93c18226a60bdfba4a724efafd1 \ + --hash=sha256:701b2e04b560eeb4bddf7a25ab8ca476176e34fdbd9a0e18196f0d12d4685f0b \ + --hash=sha256:771cf63ae0b1b50dd22e5f3e3549fab5f3f4ff1635d352a9e1a97fe01c7b2e64 \ + --hash=sha256:79bdfa52f843137045b2d081cc05c120ba6665d29b7559c2c47690906f39279f \ + --hash=sha256:7ac031912d54f3d83ef3b3eb98dfabc1608802e2202263d25957eeed40b94761 \ + --hash=sha256:7b0fc826b16c55e561e5d2a0c5c77b051ba1d92808118c4e4b5390f5e0cf191d \ + --hash=sha256:7c6be839a5a8312626b32029a415644a0846b420bc8b52b95b28cd92da162168 \ + --hash=sha256:816ff0a6550ffc06c098ccd2e0698600f9aa7da192a79eaa6f9af504a35db869 \ + --hash=sha256:82a36973cf8a2ef5406f4fe2edbf8ed0c99629535d959e0b100c76a32535a111 \ + --hash=sha256:837b396ca3d7b74091ca623f6cbd8351bd42d670a79c2683e79fb089f06a2de5 \ + --hash=sha256:850a08d167dde16db8702c274f320c7be9d7da6f6dff2b58b18f9e815bd94f5b \ + --hash=sha256:8816f3d218beb4b787de5c9759c259b8fa61f9dec42dc7811f320a33771778b7 \ + --hash=sha256:892a881d5f68c2b9ea304b7a6c2c60d9343df578a311b0f86b94bc8f1ffe8129 \ + --hash=sha256:895395f8918627b04efb1ad2a4cf605387143300ba03304cd1dfa6d03f5e095e \ + --hash=sha256:8b10e3e8fd7ddc2bd915848a2768e44c15b22936f1cc54c462ad1164deb02655 \ + --hash=sha256:8e24d8f05fa2d28513d94e877e9c75ad66175376209b3977f916e240e623193c \ + --hash=sha256:8feeac04b5794e513e710af2f9c87d49f31a6dc47967bb264a1fed61a8989bec \ + --hash=sha256:9432f3598db432cb51c5b37fdbf29a60fcccc79e30d37a05022776a6bc4ab689 \ + --hash=sha256:976e1128455aa595ea04c79ccfedff1aaeab96ee013fcc916bed120c4f0ad94f \ + --hash=sha256:978e7b97d4824b5be09c69fb70507cbde3b0323fc147332ca40a94d9a6a0ebbf \ + --hash=sha256:97bf8de4d541598c94a59344eeb988a94c08ff76b5723c41f6567ec18c7892ea \ + --hash=sha256:97cf3eb53a8cccacf9d46686a0926186c9bfb5574f2ed66d3639d5fe117cd3a9 \ + --hash=sha256:9b68938dd5b0c783d88ff8e2dcc69451b5eb936fe212d516b21b9d5567f6d464 \ + --hash=sha256:9c4b71f10dd532fb7a5cbc8f58707779e64f03a258c2bf8bfbaecfcd9970b519 \ + --hash=sha256:9f47b8a949e60f027f0aa0a6f6c7b7e9c55cbf4380d10b344e282fa4e7ab1e1b \ + --hash=sha256:a1dee1b804ff4d11c663636cf15d2ea47e9f79cd56c033fb1cbf08924842a48f \ + --hash=sha256:a2468d93d181667a7abd66e1b64bb9f76f361b0fef8faddf687456453576f5ee \ + --hash=sha256:a2a5e1d0ff29adddc9f6d6821a66302e4493f8ca898b715b6b1182c2c201ea0a \ + --hash=sha256:a39ac25a9a2fa4072efdb429833c4a4c8009a51ff9eea3eeae131713cd27991e \ + --hash=sha256:a445486499897b88a7d6c310c88ed64dd37b1b59bfd7ae9107490bbb362f47d6 \ + --hash=sha256:a91c17edf6eea2402cb5457b4c89e99bc5ed1004aa34c4adf1d4258c1a5c22c2 \ + --hash=sha256:ab4b66edffb32d9e951efb3814bd104b8367a7501b81b955cacb5726d897389f \ + --hash=sha256:aca6c767f552b21b10f774aeac128e828eafb796adfa1b666a18bf6321453c3a \ + --hash=sha256:acf8a67ba51f4ca9ddbd0e6b3000a65ac51ab734661778b3e7ba64d99a710f2f \ + --hash=sha256:b10ec717381bdbfafef34607824db4c91de69ff085e4fca3b2af91b4fa17e68a \ + --hash=sha256:b49924c73a235e969511bf2aabdff3beebf9820931f646c80274d5d780010c47 \ + --hash=sha256:b6acfb46a814762367fb7ba0828b0a17d441b92ce249a0e007474c9072662dda \ + --hash=sha256:b7ca9034437b6022f941f4857459562ee00a560b97e7cce8a0ec5a74fc6766e0 \ + --hash=sha256:b98134087d9de723658d17a42c7d0da8d6e2ef08015dee7dc93889047315f5e4 \ + --hash=sha256:b9fe6fb92520e3fd61f2e49000b6911b188824f089b75973ea06d6267f0b476d \ + --hash=sha256:bce57638e08ac148e5778cce7feb968307a727d66f8e2274a543d0cf0c9ad6a3 \ + --hash=sha256:c14ad3bdc85ee7f318742c457ca3968a92126d144b15721c759033bfb06296c2 \ + --hash=sha256:c1c43ad4339643d70ebb8124e1305a7dab423001eff58bb41a0f731adbc98355 \ + --hash=sha256:c3471e5c4a949c26ec00a77f01df59096aa9495877de76fd60a980f8ee6be461 \ + --hash=sha256:c583b927a8838dab890706a6fa7573fbb8b70e24000ef9f7238e2d6f6435a5ed \ + --hash=sha256:c76fe65e607be28c7fd4d56fc3c42b1583aa058ce3408b7ad0fd540171d31f9f \ + --hash=sha256:c7ea57fc63aa7da93a1bd2d644e6577befae10c52c4e36377635eea1056a74f5 \ + --hash=sha256:cd5214352ae68f3b5e9af7768bdc5253695ee069675db3480518420b3be881f2 \ + --hash=sha256:cdbb78909f52b981d3b2d56b97328d71eb0b974c36bd77c920123a7ebb192829 \ + --hash=sha256:cdc8b74ecc48c0cb1e9607a05ec4e9e88db60a19ffcc9a1d5f9088ede40c8dc0 \ + --hash=sha256:d0a24b40877af2de4950252be9d21eaf7fb07660f3c2cae1f56c6b599ada5266 \ + --hash=sha256:d22a945598fb91236b4dd793a6e42e4f3dd7740bb5aace5ebd7d4c08d13bb575 \ + --hash=sha256:d2f9fc07a8042a8f95925b35c4f04f469707c981fc33245b6ca187cf5d2dd290 \ + --hash=sha256:d625a186a65201c23a9e3b8ed9c47e90a026e03256608cc91851c6709096844f \ + --hash=sha256:d925f3d9afd05a8c0fb3a1031463a8d59ebe5e2afad297e29c78be19e13b4e62 \ + --hash=sha256:e64e88d5585bea9ce95861079de72006c7fa6d3df4e3a3b65ba31eb979c15c9f \ + --hash=sha256:e652ab17569c94bff5475520f907b7148b8c24036a8ebbe5cf7cf7493d28579a \ + --hash=sha256:e7b891faeedeafba41b2983e5001a81b6a915b69544c7e7570d1989ce1c36ac7 \ + --hash=sha256:e80675d75ae2cd14372cb65cad5400d9347a3d3f6c13000183f22dfd027283ed \ + --hash=sha256:e9c134bb666dd54b778b9fc0d2b50cbb7f979b9e3716f26a88c9ab3b6fc1dd0f \ + --hash=sha256:eb7d8d0e5886a89a55d2eef490e272fa965a9d57c6b29a5b5088a7997ec2cad1 \ + --hash=sha256:ecb42011e12ee19cafbc312887cbf3546959fe02fbad44f272d4be5baa997615 \ + --hash=sha256:ef3fbbf161dc9351a2fe0422e51b129f9e97e42385bd0320b309c15f7d287dd8 \ + --hash=sha256:efd62a42486f1bda5d24cb4f63d15a3c7768375fe83d36f9417b4ad7a2fb20b3 \ + --hash=sha256:f077d0b97ab11fa7dcc633fca53515f290bca8a8a633e966d5b6d1879d9ed01a \ + --hash=sha256:f332f0e72a5a0400141f830744e141bf9f97917878dbe968669e8a7fefea78ff \ + --hash=sha256:f7b0ec93a2893de856652154d73b7ba622f26fa97726487dcac373de5f4c6084 \ + --hash=sha256:fa10ef4112775900e7a0661068635eb67b2ab824fbde764de6e0e21982a93db0 \ + --hash=sha256:fc5d783bd4a2387e97b8a2d5ec781cfb92b3d893bf82370548e99db5915935d3 \ + --hash=sha256:fc8515076c11f3cfdf4fb142dcca0fe384b1230a3b5415458ac84f3e0903ec13 \ + --hash=sha256:ff218293c9c806138dca139765e3b067621be52bcd93cdc14c7711be7ddc90a9 + # via pydantic +pygments==2.21.0 \ + --hash=sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9 \ + --hash=sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c + # via mkdocs-material +pymdown-extensions==11.0.2 \ + --hash=sha256:259910762019732caa1dfd76f3faa62c59f191d46573e80bcb1d13c0f675bbe5 \ + --hash=sha256:9506fcbe66fa355a775b768084334238dd6805020ac4b92bea0c0dda6f8f223d + # via mkdocs-material +python-dateutil==2.9.0.post0 \ + --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ + --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 + # via ghp-import +pyyaml==6.0.3 \ + --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ + --hash=sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a \ + --hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \ + --hash=sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 \ + --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \ + --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \ + --hash=sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65 \ + --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \ + --hash=sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0 \ + --hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \ + --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \ + --hash=sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6 \ + --hash=sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7 \ + --hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \ + --hash=sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007 \ + --hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \ + --hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \ + --hash=sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9 \ + --hash=sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295 \ + --hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \ + --hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \ + --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \ + --hash=sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac \ + --hash=sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9 \ + --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \ + --hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \ + --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \ + --hash=sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b \ + --hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \ + --hash=sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5 \ + --hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \ + --hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \ + --hash=sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369 \ + --hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \ + --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \ + --hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \ + --hash=sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065 \ + --hash=sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c \ + --hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \ + --hash=sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764 \ + --hash=sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196 \ + --hash=sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b \ + --hash=sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00 \ + --hash=sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac \ + --hash=sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8 \ + --hash=sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e \ + --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \ + --hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \ + --hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \ + --hash=sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4 \ + --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \ + --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \ + --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \ + --hash=sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702 \ + --hash=sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8 \ + --hash=sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788 \ + --hash=sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da \ + --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \ + --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ + --hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \ + --hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \ + --hash=sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f \ + --hash=sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917 \ + --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \ + --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \ + --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \ + --hash=sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \ + --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \ + --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \ + --hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \ + --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ + --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ + --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 + # via + # mkdocs + # mkdocs-get-deps + # pymdown-extensions + # pyyaml-env-tag +pyyaml-env-tag==1.1 \ + --hash=sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04 \ + --hash=sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff + # via mkdocs +requests==2.34.2 \ + --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ + --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed + # via mkdocs-material +six==1.17.0 \ + --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ + --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 + # via python-dateutil +smmap==5.0.3 \ + --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \ + --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f + # via gitdb +typing-extensions==4.16.0 \ + --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ + --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 + # via + # pydantic + # pydantic-core + # typing-inspection +typing-inspection==0.4.4 \ + --hash=sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47 \ + --hash=sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147 + # via pydantic +urllib3==2.7.0 \ + --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ + --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 + # via requests +watchdog==6.0.0 \ + --hash=sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a \ + --hash=sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 \ + --hash=sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f \ + --hash=sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c \ + --hash=sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c \ + --hash=sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c \ + --hash=sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 \ + --hash=sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13 \ + --hash=sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134 \ + --hash=sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa \ + --hash=sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e \ + --hash=sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379 \ + --hash=sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a \ + --hash=sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11 \ + --hash=sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282 \ + --hash=sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b \ + --hash=sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f \ + --hash=sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c \ + --hash=sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112 \ + --hash=sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948 \ + --hash=sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881 \ + --hash=sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860 \ + --hash=sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3 \ + --hash=sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680 \ + --hash=sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26 \ + --hash=sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26 \ + --hash=sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e \ + --hash=sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8 \ + --hash=sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c \ + --hash=sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2 + # via mkdocs +wcmatch==11.0.1 \ + --hash=sha256:1ea2b4fa678b8ca268253798d5963935df39132d47c3e241c0a0732224005e7d \ + --hash=sha256:fd149ecddb9f0a88ea780017d6dde17c994e494e7f7303d4e3c9d6251f978f4b + # via mkdocs-awesome-nav From b012d2080ba5bd39ac3bb3a01d06972cfdd35d9e Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Sun, 6 Sep 2026 23:38:59 +0000 Subject: [PATCH 3/3] fix(values): stop claiming --set nests dots in a value talm warned that strvals reads a dot in a --set value as YAML key nesting, so that `--set endpoint=10.0.0.1` rendered as {endpoint: {10: {0: {0: 1}}}}, and steered operators to --set-string for IP, CIDR and version literals. The flag help and the manual said the same thing. It does not. strvals stops key scanning at '=', so a dot only opens a nesting level on the left of it; the value scanner stops at ',' and typedVal falls back to the raw string once ParseInt fails. Behaviour is identical on helm v3.15.2 and v4, so the migration between them did not introduce this. The screen fired on shapes that were never at risk and told operators their config was silently corrupt when it was not. Drop the screen and describe what --set actually does: it converts integers and booleans, which is the real and only reason to prefer --set-string. A new engine test pins the parser behaviour the old text described, and the help contract now rejects the claim instead of requiring it. Assisted-by: LLM Signed-off-by: Aleksei Sviridkin --- docs/configuration/templates.md | 15 +- docs/reference/apply.md | 4 +- docs/reference/template.md | 4 +- pkg/commands/apply.go | 4 +- .../contract_template_set_help_test.go | 102 ++++---- pkg/commands/template.go | 4 +- pkg/engine/contract_setvalue_warning_test.go | 243 ------------------ pkg/engine/engine.go | 7 - pkg/engine/setvalue_test.go | 82 ++++++ pkg/engine/setvalue_warn.go | 117 --------- 10 files changed, 157 insertions(+), 425 deletions(-) delete mode 100644 pkg/engine/contract_setvalue_warning_test.go create mode 100644 pkg/engine/setvalue_test.go delete mode 100644 pkg/engine/setvalue_warn.go diff --git a/docs/configuration/templates.md b/docs/configuration/templates.md index 3eaba10e..bc1d8f46 100644 --- a/docs/configuration/templates.md +++ b/docs/configuration/templates.md @@ -26,18 +26,21 @@ Querying disks map example: This returns the system disk device name. -## `--set` vs `--set-string` for IP / version literals +## `--set` vs `--set-string` -Helm's `--set` parser interprets dots in the right-hand side as YAML key nesting: +`--set` converts a value that parses as an integer or a boolean into that type: ```bash -talm template --set endpoint=10.0.0.1 # parsed as: endpoint: {10: {0: {0: 1}}} +talm template --set port=8080 # port: 8080 (integer) +talm template --set enabled=true # enabled: true (boolean) ``` -For IP addresses, CIDR blocks, or version strings, use `--set-string` to keep the value verbatim: +Use `--set-string` where the template or the Talos schema wants a string: ```bash -talm template --set-string endpoint=10.0.0.1 # parsed as: endpoint: "10.0.0.1" +talm template --set-string port=8080 # port: "8080" ``` -`talm` warns on stderr when it detects an IP-, CIDR-, or version-shaped value in `--set` and points at `--set-string` as the fix. The warning is non-fatal — rendering proceeds with the (likely-broken) nested map so existing automation does not break. For values containing characters Helm's strvals treats specially (e.g. `=`, `,` inside the value, or content that should be opaque to all parsing), use `--set-literal` — it stores the entire RHS as a verbatim string without any escape interpretation. +Dots only nest on the left of the `=`, so `--set a.b=x` sets `a.b` while a dotted value stays whole: `--set endpoint=10.0.0.1` renders `endpoint: "10.0.0.1"`, and IP addresses, CIDR blocks and version strings need no special handling. + +For values containing characters Helm's strvals treats specially (e.g. `=`, `,` inside the value, or content that should be opaque to all parsing), use `--set-literal` — it stores the entire RHS as a verbatim string without any escape interpretation. diff --git a/docs/reference/apply.md b/docs/reference/apply.md index 3fd07980..9e557155 100644 --- a/docs/reference/apply.md +++ b/docs/reference/apply.md @@ -42,11 +42,11 @@ talm apply [flags] -i, --insecure apply using the insecure (encrypted with no auth) maintenance service --kubernetes-version string desired kubernetes version to run (default "1.36.2") -m, --mode auto, no-reboot, reboot, staged, try apply config mode (default auto) - --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). For IP / CIDR / version literals use --set-string — dots in --set values are interpreted as YAML key nesting. + --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Values that parse as an integer or a boolean are converted to that type; use --set-string to keep them as strings. --set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2) --set-json stringArray set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2) --set-literal stringArray set a literal STRING value on the command line - --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Use for IP addresses, CIDR blocks, version strings, or any literal value where dots must NOT be interpreted as YAML key nesting. + --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Nothing is type-converted, so the value reaches the template exactly as typed. --show-secrets-in-drift show secret-bearing field values verbatim in drift preview / post-apply verify output (default: redacted). Covers both the Talos bootstrap allowlist (cluster.token, cluster.ca.key, machine.token, Wireguard private keys, etc.) and values from encrypted value files (*.encrypted.yaml). Counterpart on template is --show-secrets, which governs the same values in template's stdout render. --skip-drift-preview skip the pre-apply diff of on-node vs rendered MachineConfig --skip-post-apply-verify skip the post-apply structural verification of on-node vs sent MachineConfig (default skip until the Talos-mutated field allowlist lands) (default true) diff --git a/docs/reference/template.md b/docs/reference/template.md index 8c466164..f908a824 100644 --- a/docs/reference/template.md +++ b/docs/reference/template.md @@ -29,11 +29,11 @@ talm template [flags] -i, --insecure template using the insecure (encrypted with no auth) maintenance service --kubernetes-version string desired kubernetes version to run (default "1.36.2") --offline disable gathering information and lookup functions - --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). For IP / CIDR / version literals use --set-string — dots in --set values are interpreted as YAML key nesting. + --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Values that parse as an integer or a boolean are converted to that type; use --set-string to keep them as strings. --set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2) --set-json stringArray set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2) --set-literal stringArray set a literal STRING value on the command line - --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Use for IP addresses, CIDR blocks, version strings, or any literal value where dots must NOT be interpreted as YAML key nesting. + --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Nothing is type-converted, so the value reaches the template exactly as typed. --show-secrets print values from encrypted value files (*.encrypted.yaml) verbatim in stdout output (default: redacted to ***; never affects -I, which always omits them). Counterpart on apply is --show-secrets-in-drift, which governs the same values in apply's drift preview. --talos-version string the desired Talos version to generate config for (backwards compatibility, e.g. v0.8) -t, --template strings specify templates to render manifest from (can specify multiple) diff --git a/pkg/commands/apply.go b/pkg/commands/apply.go index a21ea84f..9d27b535 100644 --- a/pkg/commands/apply.go +++ b/pkg/commands/apply.go @@ -1222,8 +1222,8 @@ func init() { applyCmd.Flags().BoolVarP(&applyCmdFlags.insecure, "insecure", "i", false, "apply using the insecure (encrypted with no auth) maintenance service") applyCmd.Flags().StringSliceVarP(&applyCmdFlags.configFiles, "file", "f", nil, "node config files / patches (`.yaml` / `.yml`; shell completion narrows to these extensions). First -f is the modelined anchor (must live under a `talm init`'d project root); subsequent -f files are side-patches stacked onto the anchor's rendered config and may live anywhere.") applyCmd.Flags().StringSliceVar(&applyCmdFlags.valueFiles, "values", []string{}, "specify values in a YAML file (can specify multiple). Must match `talm template` — apply re-renders from the modeline and would otherwise drop value files supplied at template time.") - applyCmd.Flags().StringArrayVar(&applyCmdFlags.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). For IP / CIDR / version literals use --set-string — dots in --set values are interpreted as YAML key nesting.") - applyCmd.Flags().StringArrayVar(&applyCmdFlags.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Use for IP addresses, CIDR blocks, version strings, or any literal value where dots must NOT be interpreted as YAML key nesting.") + applyCmd.Flags().StringArrayVar(&applyCmdFlags.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Values that parse as an integer or a boolean are converted to that type; use --set-string to keep them as strings.") + applyCmd.Flags().StringArrayVar(&applyCmdFlags.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Nothing is type-converted, so the value reaches the template exactly as typed.") applyCmd.Flags().StringArrayVar(&applyCmdFlags.fileValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)") applyCmd.Flags().StringArrayVar(&applyCmdFlags.jsonValues, "set-json", []string{}, "set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2)") applyCmd.Flags().StringArrayVar(&applyCmdFlags.literalValues, "set-literal", []string{}, "set a literal STRING value on the command line") diff --git a/pkg/commands/contract_template_set_help_test.go b/pkg/commands/contract_template_set_help_test.go index 631fadf9..55d6d844 100644 --- a/pkg/commands/contract_template_set_help_test.go +++ b/pkg/commands/contract_template_set_help_test.go @@ -19,58 +19,72 @@ import ( "testing" ) -// TestTemplateFlag_SetHelpText_MentionsSetString pins the operator- -// facing UX: `talm template --help` must surface the --set-string -// escape hatch directly in the --set flag description. Operators -// hitting the strvals dot-nesting footgun (e.g. -// `--set endpoint=10.0.0.1` parsed as nested map) check --help -// before CHANGELOG. The Usage string must name --set-string so the -// hint lands in front of them. -func TestTemplateFlag_SetHelpText_MentionsSetString(t *testing.T) { - flag := templateCmd.Flags().Lookup("set") - if flag == nil { - t.Fatal("expected templateCmd to register a --set flag, got nil") - } +// setFlagCommands are the commands that expose the --set family. The help +// contracts below hold for every one of them, so a flag reworded on one +// command and not the other is a failure. +// +//nolint:gochecknoglobals // immutable lookup table read by the help contract tests. +var setFlagCommands = map[string]func(name string) string{ + "template": func(name string) string { return templateCmd.Flags().Lookup(name).Usage }, + "apply": func(name string) string { return applyCmd.Flags().Lookup(name).Usage }, +} + +// TestSetHelpText_PointsAtSetString pins the operator-facing UX: an +// operator deciding between the two flags reads `--help`, so the --set +// description has to name --set-string as the alternative. +func TestSetHelpText_PointsAtSetString(t *testing.T) { + t.Parallel() + + for name, usage := range setFlagCommands { + t.Run(name, func(t *testing.T) { + t.Parallel() - if !strings.Contains(flag.Usage, "--set-string") { - t.Errorf("--set Usage must point at --set-string as the escape hatch for IP / version literals; got:\n%s", flag.Usage) + if got := usage("set"); !strings.Contains(got, "--set-string") { + t.Errorf("talm %s --set Usage must name --set-string as the alternative; got:\n%s", name, got) + } + }) } } -// TestTemplateFlag_SetStringHelpText_MentionsLiteralStability pins -// the sibling contract: --set-string Usage must describe its niche -// (IP / CIDR / version literals — values that must not be type- -// coerced or dot-nested). Without this, the help text reads as -// "set STRING values" with no clue when to prefer it over --set. -func TestTemplateFlag_SetStringHelpText_MentionsLiteralStability(t *testing.T) { - flag := templateCmd.Flags().Lookup("set-string") - if flag == nil { - t.Fatal("expected templateCmd to register a --set-string flag, got nil") - } +// TestSetStringHelpText_ExplainsTypeConversion pins the reason to reach +// for --set-string. Integers and booleans are the only values --set +// converts, so "set STRING values" alone leaves an operator with no way +// to tell when it matters. +func TestSetStringHelpText_ExplainsTypeConversion(t *testing.T) { + t.Parallel() + + for name, usage := range setFlagCommands { + t.Run(name, func(t *testing.T) { + t.Parallel() - // The Usage must surface the literal-stability niche. The - // word "literal" is the canonical anchor; the sibling words - // (IP / CIDR / version) all describe shapes that need it. - usage := strings.ToLower(flag.Usage) - if !strings.Contains(usage, "literal") { - t.Errorf("--set-string Usage must name the literal-stability use case; got:\n%s", flag.Usage) + if got := usage("set-string"); !strings.Contains(strings.ToLower(got), "convert") { + t.Errorf("talm %s --set-string Usage must say that nothing is type-converted; got:\n%s", name, got) + } + }) } } -// TestTemplateFlag_SetStringHelpText_DoesNotOverpromiseHostnames pins -// the alignment between the --set-string Usage copy and the actual -// detector in pkg/engine/setvalue_warn.go. The screener matches -// IPv4 / IPv4 CIDR / semver shapes only — hostnames like -// `foo.example.com` are NOT flagged, so the Usage must NOT advertise -// hostname coverage. A previous revision did, which mislead operators -// into thinking `--set host=foo.example.com` would be screened. -func TestTemplateFlag_SetStringHelpText_DoesNotOverpromiseHostnames(t *testing.T) { - flag := templateCmd.Flags().Lookup("set-string") - if flag == nil { - t.Fatal("expected templateCmd to register a --set-string flag, got nil") - } +// TestSetHelpText_DoesNotClaimDotNesting keeps a long-standing false +// claim from coming back. The help text used to tell operators that a +// dot in a --set value nested it into a map, so that +// `--set endpoint=10.0.0.1` supposedly rendered +// {endpoint: {10: {0: {0: 1}}}} and IP literals needed --set-string. +// strvals stops key scanning at '=', so dots only nest on the left of +// it and a dotted value stays whole — see +// TestSetValueDotsNestOnlyInTheKey in pkg/engine, which pins the +// parser behaviour this text describes. +func TestSetHelpText_DoesNotClaimDotNesting(t *testing.T) { + t.Parallel() + + for name, usage := range setFlagCommands { + t.Run(name, func(t *testing.T) { + t.Parallel() - if strings.Contains(strings.ToLower(flag.Usage), "hostname") { - t.Errorf("--set-string Usage must NOT claim hostname coverage — the screener does not detect hostname-shaped values; got:\n%s", flag.Usage) + for _, flag := range []string{"set", "set-string"} { + if got := strings.ToLower(usage(flag)); strings.Contains(got, "nesting") || strings.Contains(got, "nested") { + t.Errorf("talm %s --%s Usage must not describe dots in a value as key nesting; got:\n%s", name, flag, got) + } + } + }) } } diff --git a/pkg/commands/template.go b/pkg/commands/template.go index f858c550..c2e43164 100644 --- a/pkg/commands/template.go +++ b/pkg/commands/template.go @@ -490,8 +490,8 @@ func init() { templateCmd.Flags().BoolVarP(&templateCmdFlags.inplace, "in-place", "I", false, "re-template and update generated files in place (overwrite them)") templateCmd.Flags().StringSliceVarP(&templateCmdFlags.valueFiles, "values", "", []string{}, "specify values in a YAML file (can specify multiple)") templateCmd.Flags().StringSliceVarP(&templateCmdFlags.templateFiles, "template", "t", []string{}, "specify templates to render manifest from (can specify multiple)") - templateCmd.Flags().StringArrayVar(&templateCmdFlags.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). For IP / CIDR / version literals use --set-string — dots in --set values are interpreted as YAML key nesting.") - templateCmd.Flags().StringArrayVar(&templateCmdFlags.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Use for IP addresses, CIDR blocks, version strings, or any literal value where dots must NOT be interpreted as YAML key nesting.") + templateCmd.Flags().StringArrayVar(&templateCmdFlags.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Values that parse as an integer or a boolean are converted to that type; use --set-string to keep them as strings.") + templateCmd.Flags().StringArrayVar(&templateCmdFlags.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Nothing is type-converted, so the value reaches the template exactly as typed.") templateCmd.Flags().StringArrayVar(&templateCmdFlags.fileValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)") templateCmd.Flags().StringArrayVar(&templateCmdFlags.jsonValues, "set-json", []string{}, "set JSON values on the command line (can specify multiple or separate values with commas: key1=jsonval1,key2=jsonval2)") templateCmd.Flags().StringArrayVar(&templateCmdFlags.literalValues, "set-literal", []string{}, "set a literal STRING value on the command line") diff --git a/pkg/engine/contract_setvalue_warning_test.go b/pkg/engine/contract_setvalue_warning_test.go deleted file mode 100644 index cd935d23..00000000 --- a/pkg/engine/contract_setvalue_warning_test.go +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright Cozystack Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package engine - -import ( - "bytes" - "strings" - "testing" -) - -// withCapturedSetValueWarnings redirects setValueWarningWriter to a -// caller-supplied buffer for the duration of the test, restoring the -// original writer via t.Cleanup. The package-level writer defaults -// to os.Stderr, so tests must isolate it to read the warning stream. -func withCapturedSetValueWarnings(t *testing.T) *bytes.Buffer { - t.Helper() - - buf := &bytes.Buffer{} - prev := setValueWarningWriter - setValueWarningWriter = buf - - t.Cleanup(func() { - setValueWarningWriter = prev - }) - - return buf -} - -// TestLoadValues_IPShapedSetValue_EmitsWarning pins the operator- -// footgun guard added for `--set =`. Helm's strvals.ParseInto -// interprets dots in the RHS as YAML key nesting, so -// `--set endpoint=192.168.1.1` produces the map -// `{endpoint: {192: {168: {1: 1}}}}` — silently corrupt config the -// operator notices only when the rendered manifest is wrong. The -// warning steers them to `--set-string` BEFORE the bad render lands. -func TestLoadValues_IPShapedSetValue_EmitsWarning(t *testing.T) { - buf := withCapturedSetValueWarnings(t) - - if _, err := loadValues(Options{Values: []string{"endpoint=192.168.1.1"}}); err != nil { - t.Fatalf("loadValues should succeed even when the value is IP-shaped (warning, not fatal); got: %v", err) - } - - out := buf.String() - if !strings.Contains(out, "endpoint=192.168.1.1") { - t.Errorf("warning must echo the offending key=value so the operator can correlate; got:\n%s", out) - } - if !strings.Contains(out, "--set-string") { - t.Errorf("warning must point at --set-string as the fix; got:\n%s", out) - } -} - -// TestLoadValues_CIDRShapedSetValue_EmitsWarning extends the IPv4 -// case to a CIDR. The same nesting trap applies: dots in the RHS -// stay dots; the `/24` suffix is irrelevant to strvals' parser. -func TestLoadValues_CIDRShapedSetValue_EmitsWarning(t *testing.T) { - buf := withCapturedSetValueWarnings(t) - - if _, err := loadValues(Options{Values: []string{"subnet=10.0.0.0/24"}}); err != nil { - t.Fatalf("loadValues: %v", err) - } - - if !strings.Contains(buf.String(), "--set-string") { - t.Errorf("CIDR value must trigger the same --set-string warning; got:\n%s", buf.String()) - } -} - -// TestLoadValues_ColonSeparatedLiteral_NoWarning pins the no- -// false-positive contract for colon-separated values. The warning -// targets the strvals dot-nesting trap; colons are not strvals -// separators, so `--set startTime=12:34:56`, -// `--set mac=00:11:22:33:44:55`, and IPv6 literals must not emit -// a warning whose copy says "dots are interpreted as YAML key -// nesting". -func TestLoadValues_ColonSeparatedLiteral_NoWarning(t *testing.T) { - cases := []string{ - "startTime=12:34:56", - "mac=00:11:22:33:44:55", - "endpoint=2001:db8::1", - "hex=ABCD:1234:EF56", - } - - for _, v := range cases { - t.Run(v, func(t *testing.T) { - buf := withCapturedSetValueWarnings(t) - - if _, err := loadValues(Options{Values: []string{v}}); err != nil { - t.Fatalf("loadValues: %v", err) - } - - if buf.Len() > 0 { - t.Errorf("colon-separated literal %q must not emit IP-shape warning (colons are not strvals separators); got:\n%s", v, buf.String()) - } - }) - } -} - -// TestLoadValues_SemverShapedSetValue_EmitsWarning covers the -// version-string case (`v1.13.0` or `1.13.0`). Same root cause: -// dots become nesting separators. -func TestLoadValues_SemverShapedSetValue_EmitsWarning(t *testing.T) { - cases := []string{ - "image.tag=v1.13.0", // v-prefixed three-component - "image.tag=v1.13", // v-prefixed two-component - "image.tag=1.13.0", // bare three-component - } - - for _, v := range cases { - t.Run(v, func(t *testing.T) { - buf := withCapturedSetValueWarnings(t) - - if _, err := loadValues(Options{Values: []string{v}}); err != nil { - t.Fatalf("loadValues: %v", err) - } - - if !strings.Contains(buf.String(), "--set-string") { - t.Errorf("semver-shaped value must trigger the --set-string warning; got:\n%s", buf.String()) - } - }) - } -} - -// TestLoadValues_BareDecimalSetValue_NoWarning pins the negative -// contract for two-component bare decimals: `cpu=1.5`, -// `weight=2.0`, and similar plain-numeric values that share the -// "single dot, digits on both sides" shape with semver-two but -// carry no operator-intent signal toward strvals nesting. Without -// this guard the warning generates noise on every Helm chart that -// uses `--set cpu=1.5` to override resource requests. -func TestLoadValues_BareDecimalSetValue_NoWarning(t *testing.T) { - cases := []string{ - "cpu=1.5", - "weight=2.0", - "ratio=0.95", - } - - for _, v := range cases { - t.Run(v, func(t *testing.T) { - buf := withCapturedSetValueWarnings(t) - - if _, err := loadValues(Options{Values: []string{v}}); err != nil { - t.Fatalf("loadValues: %v", err) - } - - if buf.Len() > 0 { - t.Errorf("bare decimal %q must not emit semver warning; got:\n%s", v, buf.String()) - } - }) - } -} - -// TestLoadValues_InvalidIPv4OctetSetValue_NoWarning pins that the -// IPv4 detector rejects out-of-range octets. `999.999.999.999` -// shares the four-dotted-numeric shape with a real IPv4 literal -// but is overwhelmingly likely to be a chart-internal magic -// number, not an accidental IP literal. Tightening the regex -// avoids the false positive at zero cost to legitimate IPv4 -// detection. -func TestLoadValues_InvalidIPv4OctetSetValue_NoWarning(t *testing.T) { - buf := withCapturedSetValueWarnings(t) - - if _, err := loadValues(Options{Values: []string{"magic=999.999.999.999"}}); err != nil { - t.Fatalf("loadValues: %v", err) - } - - if buf.Len() > 0 { - t.Errorf("invalid-octet four-dotted-numeric must not trigger IPv4 warning; got:\n%s", buf.String()) - } -} - -// TestLoadValues_IPShapedSetStringValue_NoWarning pins the negative -// contract: when the operator already uses --set-string, no warning -// fires. The guard is for the `--set` footgun specifically. -func TestLoadValues_IPShapedSetStringValue_NoWarning(t *testing.T) { - buf := withCapturedSetValueWarnings(t) - - if _, err := loadValues(Options{StringValues: []string{"endpoint=192.168.1.1"}}); err != nil { - t.Fatalf("loadValues: %v", err) - } - - if buf.Len() > 0 { - t.Errorf("--set-string must not emit the IP-shape warning; got:\n%s", buf.String()) - } -} - -// TestLoadValues_PlainSetValue_NoWarning pins the no-false-positive -// contract: plain string / numeric / bool values must not trigger -// the warning. The detector matches IP / CIDR / semver shapes only. -func TestLoadValues_PlainSetValue_NoWarning(t *testing.T) { - cases := []string{ - "clusterName=test", - "count=5", - "enabled=true", - "image.repository=ghcr.io/foo/bar", - } - - for _, v := range cases { - t.Run(v, func(t *testing.T) { - buf := withCapturedSetValueWarnings(t) - - if _, err := loadValues(Options{Values: []string{v}}); err != nil { - t.Fatalf("loadValues: %v", err) - } - - if buf.Len() > 0 { - t.Errorf("plain value %q must not emit IP-shape warning; got:\n%s", v, buf.String()) - } - }) - } -} - -// TestLoadValues_ChainedSetValue_WarnsOnEachIPLiteral covers Helm's -// comma-chained shorthand: `--set k1=v1,k2=v2`. Each comma-segment -// is parsed independently and each must be screened independently. -func TestLoadValues_ChainedSetValue_WarnsOnEachIPLiteral(t *testing.T) { - buf := withCapturedSetValueWarnings(t) - - if _, err := loadValues(Options{Values: []string{"a=1.2.3.4,b=plain,c=5.6.7.8"}}); err != nil { - t.Fatalf("loadValues: %v", err) - } - - out := buf.String() - if !strings.Contains(out, "a=1.2.3.4") { - t.Errorf("first IP literal must be flagged; got:\n%s", out) - } - if !strings.Contains(out, "c=5.6.7.8") { - t.Errorf("third IP literal must be flagged; got:\n%s", out) - } - if strings.Contains(out, "b=plain") { - t.Errorf("plain pair must not be flagged; got:\n%s", out) - } -} diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 3b6492e3..30109ac7 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -1728,13 +1728,6 @@ func loadValues(opts Options) (map[string]any, error) { base = mergeMaps(base, currentMap) } - // Screen --set values for IP / CIDR / version literals BEFORE - // strvals.ParseInto chews them. The parser interprets dots in - // the RHS as YAML key nesting, so `--set endpoint=10.0.0.1` - // produces `{endpoint: {10: {0: {0: 1}}}}` — silently corrupt - // config. The warning steers operators to --set-string. - screenSetValuesForCoercion(opts.Values) - // Parse and merge values from --set for _, value := range opts.Values { err := strvals.ParseInto(value, base) diff --git a/pkg/engine/setvalue_test.go b/pkg/engine/setvalue_test.go new file mode 100644 index 00000000..9d72708a --- /dev/null +++ b/pkg/engine/setvalue_test.go @@ -0,0 +1,82 @@ +// Copyright Cozystack Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package engine_test + +import ( + "testing" + + "helm.sh/helm/v4/pkg/strvals" +) + +// TestSetValueDotsNestOnlyInTheKey pins what --set actually does with a +// dotted value, because talm used to warn that it did something else: +// that `--set endpoint=10.0.0.1` rendered as {endpoint: {10: {0: {0: 1}}}} +// and that operators had to reach for --set-string to avoid it. +// +// It never did. strvals' key scanner stops at '=', so a dot only starts a +// new nesting level on the left of it; the value scanner stops at ',' and +// hands whatever it read to typedVal, which falls back to the raw string +// once ParseInt fails. Verified identical on helm v3.15.2 and v4, so this +// is not something the v3-to-v4 migration changed. +// +// What --set does convert is integers and booleans. That is the real +// reason to prefer --set-string, and the only one worth documenting. +func TestSetValueDotsNestOnlyInTheKey(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + name string + set string + key string + want any + }{ + {"ipv4 literal stays a string", "endpoint=10.0.0.1", "endpoint", "10.0.0.1"}, + {"cidr stays a string", "cidr=10.0.0.0/24", "cidr", "10.0.0.0/24"}, + {"version stays a string", "talosVersion=v1.13.0", "talosVersion", "v1.13.0"}, + {"bare version stays a string", "talosVersion=1.13", "talosVersion", "1.13"}, + {"integers are converted", "port=8080", "port", int64(8080)}, + {"booleans are converted", "enabled=true", "enabled", true}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + got := map[string]any{} + if err := strvals.ParseInto(tc.set, got); err != nil { + t.Fatalf("ParseInto(%q): %v", tc.set, err) + } + + if got[tc.key] != tc.want { + t.Errorf("--set %s produced %s = %#v (%T), want %#v (%T)", + tc.set, tc.key, got[tc.key], got[tc.key], tc.want, tc.want) + } + }) + } + + // A dot on the left of '=' does nest, which is the behaviour the + // warning mistook for value handling. + nested := map[string]any{} + if err := strvals.ParseInto("a.b=10.0.0.1", nested); err != nil { + t.Fatalf("ParseInto nested key: %v", err) + } + + inner, ok := nested["a"].(map[string]any) + if !ok { + t.Fatalf("--set a.b=... produced %#v, want a nested map under \"a\"", nested["a"]) + } + + if inner["b"] != "10.0.0.1" { + t.Errorf("--set a.b=10.0.0.1 produced a.b = %#v, want \"10.0.0.1\"", inner["b"]) + } +} diff --git a/pkg/engine/setvalue_warn.go b/pkg/engine/setvalue_warn.go deleted file mode 100644 index ed40ad2f..00000000 --- a/pkg/engine/setvalue_warn.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright Cozystack Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package engine - -import ( - "fmt" - "io" - "os" - "regexp" - "strings" -) - -// setValueWarningWriter is the sink for the operator-facing warning -// emitted by loadValues when a `--set` value's RHS looks like an IP, -// CIDR, or version literal — shapes that strvals.ParseInto would -// interpret as nested map keys, silently corrupting the rendered -// config. Defaulted to os.Stderr; redirected in tests via -// withCapturedSetValueWarnings. -// -//nolint:gochecknoglobals // package-level writer is the standard Go pattern for test-overridable side-channel output; an Options-borne writer would propagate through the public engine API for a single internal-use warning. -var setValueWarningWriter io.Writer = os.Stderr - -// ipShapedValueRe matches a valid IPv4 literal or IPv4 CIDR. dots -// in these shapes are not separators (they belong to the address) -// but strvals.ParseInto reads them as YAML key nesting. The per- -// octet alternation rejects out-of-range numbers (256.x.y.z) so -// the heuristic does not flag arbitrary four-dotted numeric strings -// like 999.999.999.999 — which carry no operator-intent signal. -var ipShapedValueRe = regexp.MustCompile(`^(?:25[0-5]|2[0-4]\d|1?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|1?\d?\d)){3}(?:/(?:3[0-2]|[12]?\d))?$`) - -// semverShapedValueRe matches semantic-version literals: either a -// `v`-prefixed two-or-three-component form (`v1.13`, `v1.13.0`) or -// a bare three-component form (`1.13.0`). A bare two-component form -// (`1.5`, `2.0`) is deliberately NOT matched — those shapes are -// indistinguishable from plain decimal values like -// `cpu=1.5` / `weight=2.0` and would generate noise. Same dot-as- -// nesting trap as the IP shape; bare two-component decimals are -// the common false-positive class. -var semverShapedValueRe = regexp.MustCompile(`^(?:v\d+\.\d+(?:\.\d+)?|\d+\.\d+\.\d+)$`) - -// looksLikeAccidentalSetCoercion screens a single `key=value` pair -// for the canonical strvals footgun shapes. Returns true when the -// RHS contains dots that strvals.ParseInto would interpret as YAML -// key nesting against the operator's intent. IPv6 / MAC / colon- -// separated literals are deliberately NOT flagged: colons are not -// strvals separators, so `--set startTime=12:34:56` and -// `--set mac=00:11:22:33:44:55` do not hit the nesting trap and -// must not emit a misleading "use --set-string" warning. -func looksLikeAccidentalSetCoercion(pair string) bool { - // Split on the first '=' only; chained values are screened - // upstream by splitChainedSetValue. A pair without '=' - // can't have a footgun RHS to flag. - _, value, ok := strings.Cut(pair, "=") - if !ok || value == "" { - return false - } - - switch { - case ipShapedValueRe.MatchString(value): - return true - case semverShapedValueRe.MatchString(value): - return true - } - - return false -} - -// splitChainedSetValue splits a chained --set value -// (`k1=v1,k2=v2,k3=v3`) into its constituent pairs. The actual Helm -// strvals parser handles escape semantics; this helper exists only -// to screen each pair for the IP-shape footgun before strvals chews -// the string. A simple Split on ',' is enough for the canonical -// shapes the warning targets — operators with embedded commas in -// values should already be reaching for --set-literal or --set-json. -func splitChainedSetValue(value string) []string { - return strings.Split(value, ",") -} - -// emitSetValueCoercionWarning writes the operator-facing warning to -// setValueWarningWriter for the offending pair. Format matches the -// rest of the cobra error / hint conventions ("talm:" prefix, one -// line per warning). -func emitSetValueCoercionWarning(pair string) { - fmt.Fprintf(setValueWarningWriter, - "talm: --set %s looks like an IP / CIDR / version literal; "+ - "strvals.ParseInto interprets dots as YAML key nesting, "+ - "so the rendered value will be a nested map. Pass --set-string %s "+ - "to keep the literal verbatim.\n", - pair, pair, - ) -} - -// screenSetValuesForCoercion walks every comma-separated pair in -// every --set entry and emits a warning per footgun-shape match. -// The screen is non-fatal: parsing proceeds as before, the warning -// is the only behavioural change. -func screenSetValuesForCoercion(values []string) { - for _, value := range values { - for _, pair := range splitChainedSetValue(value) { - if looksLikeAccidentalSetCoercion(pair) { - emitSetValueCoercionWarning(pair) - } - } - } -}