provisioning-core/nulib/cli/cluster.nu

166 lines
7.6 KiB
Text

#!/usr/bin/env nu
# Thin entry for cluster commands.
# Loads only cluster-deploy.nu + discover + workspace (~140ms vs ~49s for the full entry).
export-env {
let lib_dirs_raw = ($env.NU_LIB_DIRS? | default "")
let current_lib_dirs = if ($lib_dirs_raw | type) == "string" {
if ($lib_dirs_raw | is-empty) { [] } else { ($lib_dirs_raw | split row ":") }
} else {
$lib_dirs_raw
}
let dynamic = ($env.PROVISIONING? | default "" | path join "core" "nulib")
$env.NU_LIB_DIRS = ([
"/opt/provisioning/core/nulib"
"/usr/local/provisioning/core/nulib"
] | append $current_lib_dirs | append (if ($dynamic | is-not-empty) { [$dynamic] } else { [] }))
}
use domain/workspace/mod.nu *
use platform/user/config.nu [get-workspace-path, get-active-workspace-details]
use platform/config/accessor.nu [config-get]
use orchestration/cluster_deploy.nu *
use orchestration/clusters/discover.nu [discover-clusters, get-cluster-info]
use cli/components.nu ["main component list", "main cluster top", "main cluster label-nodes", "main cluster plan", "main cluster capacity", "main cluster services"]
def main [
...args: string
--workspace (-w): string = ""
--dry-run (-n)
--kubeconfig (-k): string = ""
--secrets-file (-s): string = ""
--out (-o): string = ""
--debug (-x)
--notitles
]: nothing -> nothing {
if $debug { $env.PROVISIONING_DEBUG = true }
let rest = if (($args | length) > 0) and (($args | first) in ["cluster", "cl"]) {
$args | skip 1
} else {
$args
}
let sub = ($rest | get 0? | default "")
let arg1 = ($rest | get 1? | default "")
let arg2 = ($rest | get 2? | default "")
let help_text = {
print "Cluster Management"
print "=================="
print ""
print "Usage: prvng cluster <subcommand> [options]"
print ""
print "Subcommands:"
print " list List cluster-mode components in active workspace (alias: ls, l)"
print " show <name> Show a cluster-mode component's full config (alias: sh, info)"
print " top [pods] [-o json|yaml] Live node usage via kubectl top; (alias: t)"
print " 'top pods' appends heaviest pods by memory"
print " '-o json|yaml' emits structured output + legend on req%/lim%/no-req"
print " services [-n <ns>] [-o json|yaml] List all Kubernetes services in the cluster (alias: svc, svcs)"
print " label-nodes [--apply] Reconcile declared node labels/node_class (alias: labels, ln)"
print " onto live nodes (dry-run unless --apply)"
print " plan <service> [-o json|yaml] Simulate a (re)deploy: projected req%/ws% (alias: p, sim)"
print " per eligible node + fit recommendation"
print " capacity [--add-worker] [--resize <n>] Per-node load by category (movable/pinned/ (alias: cap)"
print " infra) + horizontal-vs-vertical what-if"
print " deploy <layer> <cluster> [options] Deploy a cluster (layer: platform|apps) (alias: d)"
print ""
print "Flags for deploy:"
print " --workspace (-w) <name> Workspace name (defaults to active)"
print " --dry-run (-n) Print execution plan without running scripts"
print " --kubeconfig (-k) <path> Override KUBECONFIG path"
print " --secrets-file (-s) <path> SOPS-encrypted dotenv with install secrets"
print ""
print "Examples:"
print " prvng cl l"
print " prvng cluster show sgoyol"
print " prvng cl deploy platform sgoyol --dry-run"
print " prvng cluster deploy apps wuji -w libre-daoshi"
}
match $sub {
"" | "help" | "h" | "-h" | "--help" => { do $help_text }
"list" | "ls" | "l" => {
let rows = if ($workspace | is-not-empty) {
main component list --workspace $workspace --mode "cluster"
} else {
main component list --mode "cluster"
}
if ($rows | is-empty) {
print "No cluster-mode components declared in the active workspace."
return
}
$rows | reject pod_selector
}
"show" | "info" | "sh" => {
if ($arg1 | is-empty) {
print "Error: cluster show requires a name"
print "Usage: prvng cluster show <name>"
return
}
let rows = if ($workspace | is-not-empty) {
main component list --workspace $workspace --mode "cluster"
} else {
main component list --mode "cluster"
}
let found = ($rows | where name == $arg1 | get 0?)
if ($found | is-empty) {
print $"Error: cluster component '($arg1)' not found in active workspace"
print $"Available: ($rows | get name | str join ', ')"
return
}
$found | reject pod_selector live_check
}
"services" | "svc" | "svcs" => {
let ns_arg = if ($arg1 | is-not-empty) and ($arg1 | str starts-with "-") == false { $arg1 } else { "" }
let out_val = if ($arg1 == "-o") { $arg2 } else if ($arg2 == "-o") { "" } else { $out }
let ws_flag = if ($workspace | is-not-empty) { [$workspace] } else { [] }
if ($ns_arg | is-not-empty) {
main cluster services --workspace ($ws_flag | get 0? | default "") --namespace $ns_arg --out $out_val
} else {
main cluster services --workspace ($ws_flag | get 0? | default "") --out $out_val
}
}
"top" | "t" => {
main cluster top $arg1 --workspace $workspace --out $out
}
"label-nodes" | "labels" | "ln" => {
let apply = ($arg1 in ["apply", "--apply", "-a"])
if $apply {
main cluster label-nodes --workspace $workspace --apply
} else {
main cluster label-nodes --workspace $workspace
}
}
"plan" | "p" | "sim" => {
if ($arg1 | is-empty) {
print "Usage: prvng cluster plan <service> [-o json|yaml]"
return
}
main cluster plan $arg1 --workspace $workspace --out $out
}
"capacity" | "cap" => {
main cluster capacity --workspace $workspace --out $out
}
"deploy" | "d" => {
let layer = $arg1
let cluster = $arg2
if ($layer | is-empty) or ($cluster | is-empty) {
print "Usage: prvng cluster deploy <layer> <cluster> [--workspace <name>]"
print " layer: platform | apps"
print " cluster: sgoyol | wuji | ..."
exit 1
}
if ($workspace | is-not-empty) {
main cluster deploy $layer $cluster --workspace $workspace --dry-run=$dry_run --kubeconfig $kubeconfig --secrets-file $secrets_file
} else {
main cluster deploy $layer $cluster --dry-run=$dry_run --kubeconfig $kubeconfig --secrets-file $secrets_file
}
}
_ => {
print $"Unknown cluster subcommand: ($sub)"
print ""
do $help_text
}
}
}