- DAG architecture: `dag show/validate/export` (nulib/main_provisioning/dag.nu),
config loader (lib_provisioning/config/loader/dag.nu), taskserv dag-executor.
Backed by schemas/lib/dag/*.ncl; orchestrator emits NATS events via
WorkspaceComposition::into_workflow. See ADR-020, ADR-021.
- Unified Component Architecture: components/mod.nu, main_provisioning/
{components,workflow,extensions,ontoref-queries}.nu. Full workflow engine with
topological sort and NATS subject emission. Blocks A-H complete (libre-daoshi).
- Commands-registry: nulib/commands-registry.ncl (Nickel source, 314 lines) +
JSON cache at ~/.cache/provisioning/commands-registry.json rebuilt on source
change. cli/provisioning fast-path alias expansion avoids cold Nu startup.
ADDING_COMMANDS.md documents new-command workflow.
- Platform service manager: service-manager.nu (+573), startup.nu (+611),
service-check.nu (+255); autostart/bootstrap/health/target refactored.
- Nushell 0.112.2 migration: removed all try/catch and bash redirections;
external commands prefixed with ^; type signatures enforced. Driven by
scripts/refactor-try-catch{,-simplified}.nu.
- TTY stack: removed shlib/*-tty.sh; replaced by cli/tty-dispatch.sh,
tty-filter.sh, tty-commands.conf.
- New domain modules: images/ (golden image lifecycle), workspace/{state,sync}.nu,
main_provisioning/{bootstrap,cluster-deploy,fip,state}.nu, commands/{state,
build,integrations/auth,utilities/alias}.nu, platform.nu expanded (+874).
- Config loader overhaul: loader/core.nu slimmed (-759), cache/core.nu
refactored (-454), removed legacy loaders/file_loader.nu (-330).
- Thirteen new provisioning-<domain>.nu top-level modules for bash dispatcher.
- Tests: test_workspace_state.nu (+351); updates to test_oci_registry,
test_services.
- README + CHANGELOG updated.
127 lines
5.5 KiB
Text
127 lines
5.5 KiB
Text
use ../../lib_provisioning/config/accessor.nu *
|
||
use ../../lib_provisioning/utils/interface.nu [_print]
|
||
use ../../workspace/state.nu *
|
||
use ../../workspace/sync.nu *
|
||
|
||
export def handle_state_command [cmd: string, ops: string, flags: record] {
|
||
let workspace_path = if ($env.PROVISIONING_WORKSPACE_PATH? | is-not-empty) {
|
||
$env.PROVISIONING_WORKSPACE_PATH
|
||
} else {
|
||
$env.PWD
|
||
}
|
||
|
||
let infra = ($flags | get -o infra | default "")
|
||
let server = ($flags | get -o server | default "")
|
||
let taskserv = ($flags | get -o taskserv | default "")
|
||
let kubeconfig = ($flags | get -o kubeconfig | default "")
|
||
|
||
# When help_category == command name ("state"), the subcommand lands in $ops, not $cmd.
|
||
let subcmd = if ($ops | is-not-empty) { ($ops | split row " " | first) } else { $cmd }
|
||
|
||
match $subcmd {
|
||
"show" | "s" => {
|
||
state-show $workspace_path --server $server
|
||
},
|
||
|
||
"init" | "i" => {
|
||
let curr_settings = (find_get_settings --infra $infra)
|
||
state-init $workspace_path $curr_settings
|
||
_print $"State initialized at (state-path $workspace_path)"
|
||
},
|
||
|
||
"reset" | "r" => {
|
||
if ($server | is-empty) or ($taskserv | is-empty) {
|
||
error make { msg: "state reset requires --server <hostname> --taskserv <name>" }
|
||
}
|
||
state-node-reset $workspace_path $server $taskserv
|
||
_print $"($server)/($taskserv) reset to pending"
|
||
},
|
||
|
||
"migrate" | "m" => {
|
||
state-migrate-from-json $workspace_path
|
||
},
|
||
|
||
"sync" => {
|
||
let curr_settings = (find_get_settings --infra $infra)
|
||
|
||
# 1. Drift detection + reconcile against servers.ncl
|
||
let drift_rows = (state-drift $workspace_path $curr_settings --server $server)
|
||
let has_drift = ($drift_rows | where drift != "ok" | is-not-empty)
|
||
if $has_drift {
|
||
_print "── drift ──"
|
||
print ($drift_rows | where drift != "ok" | table)
|
||
let result = (state-reconcile $workspace_path $curr_settings --server $server)
|
||
if ($result.removed | is-not-empty) {
|
||
_print $"🗑 Removed ($result.removed | length) orphaned"
|
||
}
|
||
if ($result.added | is-not-empty) {
|
||
_print $"➕ Added ($result.added | length) pending"
|
||
}
|
||
} else {
|
||
_print "✅ No drift against servers.ncl"
|
||
}
|
||
|
||
# 2. External API sync (Hetzner, K8s, SSH)
|
||
let skip_ssh = ($flags | get -o skip_ssh | default false)
|
||
state-sync $workspace_path $curr_settings --kubeconfig $kubeconfig --skip-ssh=$skip_ssh
|
||
},
|
||
|
||
"drift" | "d" => {
|
||
let curr_settings = (find_get_settings --infra $infra)
|
||
let rows = (state-drift $workspace_path $curr_settings --server $server)
|
||
let has_drift = ($rows | where drift != "ok" | is-not-empty)
|
||
if ($rows | is-empty) {
|
||
_print "(no state entries to compare)"
|
||
} else {
|
||
print ($rows | table)
|
||
if $has_drift {
|
||
_print $"\n⚠ Drift detected. Run (_ansi yellow_bold)provisioning state reconcile(_ansi reset) to fix."
|
||
} else {
|
||
_print "\n✅ No drift — state matches servers.ncl"
|
||
}
|
||
}
|
||
},
|
||
|
||
"reconcile" | "rec" => {
|
||
let curr_settings = (find_get_settings --infra $infra)
|
||
let dry_run = ($flags | get -o dry_run | default false)
|
||
|
||
# Always show drift first
|
||
let drift_rows = (state-drift $workspace_path $curr_settings --server $server)
|
||
let has_drift = ($drift_rows | where drift != "ok" | is-not-empty)
|
||
if not $has_drift {
|
||
_print "✅ No drift — nothing to reconcile"
|
||
return
|
||
}
|
||
print ($drift_rows | where drift != "ok" | table)
|
||
|
||
if $dry_run {
|
||
_print "\n(dry-run: no changes applied)"
|
||
return
|
||
}
|
||
|
||
let result = (state-reconcile $workspace_path $curr_settings --server $server)
|
||
if ($result.removed | is-not-empty) {
|
||
_print $"\n🗑 Removed ($result.removed | length) orphaned entries:"
|
||
for r in $result.removed { _print $" ($r.server)/($r.taskserv)" }
|
||
}
|
||
if ($result.added | is-not-empty) {
|
||
_print $"\n➕ Added ($result.added | length) pending entries:"
|
||
for a in $result.added { _print $" ($a.server)/($a.taskserv)" }
|
||
}
|
||
_print "\n✅ State reconciled with servers.ncl"
|
||
},
|
||
|
||
_ => {
|
||
_print "Usage: provisioning state <subcommand> [--infra <path>]"
|
||
_print ""
|
||
_print " show [--server <hostname>] — display state table"
|
||
_print " init [--infra <path>] — bootstrap state from settings"
|
||
_print " reset --server <hostname> --taskserv <name> — reset node to pending"
|
||
_print " migrate — migrate .json → .ncl"
|
||
_print " sync [--infra <path>] [--kubeconfig <path>] — reconcile from APIs"
|
||
_print " drift [--infra <path>] [--server <hostname>] — detect state vs servers.ncl divergence"
|
||
_print " reconcile [--infra <path>] [--server <hostname>] — fix drift (remove orphaned, add missing)"
|
||
},
|
||
}
|
||
}
|