prvng_core/nulib/main_provisioning/commands/state.nu
Jesús Pérez 316622a78f
merge(refactor/lazy-loading): ADR-025 lazy-loading complete
557 files merged. Conflicts resolved:
  - CHANGELOG.md: took refactor/lazy-loading (session changelog)
  - versions.ncl: took refactor/lazy-loading (adds typedialog entries)
2026-04-17 23:09:56 +01:00

127 lines
5.5 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)"
},
}
}