#!/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 [options]" print "" print "Subcommands:" print " list List cluster-mode components in active workspace (alias: ls, l)" print " show 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 ] [-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 [-o json|yaml] Simulate a (re)deploy: projected req%/ws% (alias: p, sim)" print " per eligible node + fit recommendation" print " capacity [--add-worker] [--resize ] Per-node load by category (movable/pinned/ (alias: cap)" print " infra) + horizontal-vs-vertical what-if" print " deploy [options] Deploy a cluster (layer: platform|apps) (alias: d)" print "" print "Flags for deploy:" print " --workspace (-w) Workspace name (defaults to active)" print " --dry-run (-n) Print execution plan without running scripts" print " --kubeconfig (-k) Override KUBECONFIG path" print " --secrets-file (-s) 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 " 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 [-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 [--workspace ]" 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 } } }