- 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.
224 lines
6.8 KiB
Text
224 lines
6.8 KiB
Text
# Extensions Management Commands
|
|
|
|
use ../lib_provisioning/extensions *
|
|
use ../lib_provisioning/config/accessor.nu *
|
|
use ../lib_provisioning/utils/nickel_processor.nu [ncl-eval-soft, default-ncl-paths]
|
|
|
|
# Resolve the taskservs directory: PROVISIONING_TASKSERVS_PATH → config → $PROVISIONING/extensions/taskservs.
|
|
def resolve-taskservs-dir [] : nothing -> string {
|
|
let from_env = ($env.PROVISIONING_TASKSERVS_PATH? | default "")
|
|
if ($from_env | is-not-empty) { return $from_env }
|
|
let from_config = (get-taskservs-path)
|
|
if ($from_config | is-not-empty) { return $from_config }
|
|
($env.PROVISIONING? | default "/usr/local/provisioning") | path join "extensions" "taskservs"
|
|
}
|
|
|
|
# Load metadata.ncl for each taskserv via nickel export and aggregate provides/requires/conflicts_with.
|
|
def load-taskserv-capabilities [] : nothing -> list<record> {
|
|
let ts_dir = (resolve-taskservs-dir)
|
|
if not ($ts_dir | path exists) { return [] }
|
|
|
|
glob ($ts_dir | path join "*")
|
|
| where ($it | path type) == "dir"
|
|
| each { |ts_path|
|
|
let meta_path = ($ts_path | path join "metadata.ncl")
|
|
if not ($meta_path | path exists) {
|
|
null
|
|
} else {
|
|
let prov = ($env.PROVISIONING? | default "/usr/local/provisioning")
|
|
let m = (ncl-eval-soft $meta_path (default-ncl-paths "") null)
|
|
if ($m | is-not-empty) {
|
|
{
|
|
name: $m.name,
|
|
version: $m.version,
|
|
description: $m.description,
|
|
provides: ($m.provides? | default []),
|
|
requires: ($m.requires? | default []),
|
|
conflicts_with: ($m.conflicts_with? | default []),
|
|
}
|
|
} else { null }
|
|
}
|
|
}
|
|
| where ($it != null)
|
|
}
|
|
|
|
# List available extensions
|
|
export def "main extensions list" [
|
|
--type: string = "" # Filter by type: provider, taskserv, or all
|
|
--helpinfo (-h) # Show help
|
|
] {
|
|
if $helpinfo {
|
|
print "List available extensions"
|
|
return
|
|
}
|
|
|
|
match $type {
|
|
"provider" => {
|
|
print "Available Provider Extensions:"
|
|
list-providers
|
|
}
|
|
"taskserv" => {
|
|
print "Available TaskServ Extensions:"
|
|
list-taskservs
|
|
}
|
|
_ => {
|
|
print "Available Extensions:"
|
|
print "\nProviders:"
|
|
list-providers
|
|
|
|
print "\nTaskServs:"
|
|
list-taskservs
|
|
}
|
|
}
|
|
}
|
|
|
|
# Show extension details
|
|
export def "main extensions show" [
|
|
name: string # Extension name
|
|
--helpinfo (-h) # Show help
|
|
] {
|
|
if $helpinfo {
|
|
print "Show details for a specific extension"
|
|
return
|
|
}
|
|
|
|
let provider = (get-provider $name)
|
|
let taskserv = (get-taskserv $name)
|
|
|
|
if ($provider | is-not-empty) {
|
|
print $"Provider Extension: ($name)"
|
|
$provider
|
|
} else if ($taskserv | is-not-empty) {
|
|
print $"TaskServ Extension: ($name)"
|
|
$taskserv
|
|
} else {
|
|
print $"Extension '($name)' not found"
|
|
}
|
|
}
|
|
|
|
# Initialize extensions
|
|
export def "main extensions init" [
|
|
--helpinfo (-h) # Show help
|
|
] {
|
|
if $helpinfo {
|
|
print "Initialize extension registry"
|
|
return
|
|
}
|
|
|
|
init-registry
|
|
print "Extension registry initialized"
|
|
}
|
|
|
|
# Show current profile
|
|
export def "main profile show" [
|
|
--helpinfo (-h) # Show help
|
|
] {
|
|
if $helpinfo {
|
|
print "Show current access profile"
|
|
return
|
|
}
|
|
|
|
show-profile | table
|
|
}
|
|
|
|
# Create example profiles
|
|
export def "main profile create-examples" [
|
|
--helpinfo (-h) # Show help
|
|
] {
|
|
if $helpinfo {
|
|
print "Create example profile files"
|
|
return
|
|
}
|
|
|
|
create-example-profiles
|
|
}
|
|
|
|
# List capability declarations across all taskservs (provides + requires).
|
|
export def "main extensions capabilities" [
|
|
--type (-t): string = "all" # Filter: "provides", "requires", or "all"
|
|
--helpinfo (-h) # Show help
|
|
] : nothing -> any {
|
|
if $helpinfo {
|
|
print "List capability declarations across all taskservs"
|
|
print " --type: provides | requires | all (default: all)"
|
|
return
|
|
}
|
|
|
|
let caps = (load-taskserv-capabilities)
|
|
if ($caps | is-empty) {
|
|
print "No taskservs found or metadata.ncl missing."
|
|
return
|
|
}
|
|
|
|
match $type {
|
|
"provides" => {
|
|
$caps | each { |ts|
|
|
$ts.provides | each { |p| { taskserv: $ts.name, provides_id: $p.id, version: $p.version, interface: $p.interface } }
|
|
} | flatten | table
|
|
}
|
|
"requires" => {
|
|
$caps | each { |ts|
|
|
$ts.requires | each { |r| { taskserv: $ts.name, capability: $r.capability, kind: $r.kind } }
|
|
} | flatten | table
|
|
}
|
|
_ => {
|
|
$caps | each { |ts|
|
|
{
|
|
taskserv: $ts.name,
|
|
provides: ($ts.provides | each { |p| $p.id } | str join ", "),
|
|
requires: ($ts.requires | each { |r| $"($r.capability)[($r.kind)]" } | str join ", "),
|
|
conflicts_with: ($ts.conflicts_with | str join ", "),
|
|
}
|
|
} | table
|
|
}
|
|
}
|
|
}
|
|
|
|
# Show inter-extension dependency graph derived from provides/requires metadata.
|
|
export def "main extensions graph" [
|
|
--format (-f): string = "table" # Output format: table, dot
|
|
--helpinfo (-h) # Show help
|
|
] : nothing -> any {
|
|
if $helpinfo {
|
|
print "Show inter-extension dependency graph from provides/requires metadata"
|
|
print " --format: table | dot (default: table)"
|
|
return
|
|
}
|
|
|
|
let caps = (load-taskserv-capabilities)
|
|
if ($caps | is-empty) {
|
|
print "No taskservs found."
|
|
return
|
|
}
|
|
|
|
# Build provides index: capability_id -> taskserv name
|
|
let provides_index = ($caps | each { |ts|
|
|
$ts.provides | each { |p| { cap: $p.id, provider: $ts.name } }
|
|
} | flatten)
|
|
|
|
# Build edges: (requirer, capability, provider, kind)
|
|
let edges = ($caps | each { |ts|
|
|
$ts.requires | each { |r|
|
|
let provider = ($provides_index | where cap == $r.capability | get provider?.0 | default "unresolved")
|
|
{ from: $ts.name, capability: $r.capability, to: $provider, kind: $r.kind }
|
|
}
|
|
} | flatten)
|
|
|
|
match $format {
|
|
"table" => {
|
|
$edges | table
|
|
}
|
|
"dot" => {
|
|
print "digraph extensions {"
|
|
print " rankdir=LR;"
|
|
for edge in $edges {
|
|
let style = if $edge.kind == "Required" { "" } else { " style=dashed" }
|
|
print $" \"($edge.from)\" -> \"($edge.to)\" [label=\"($edge.capability)\"($style)];"
|
|
}
|
|
print "}"
|
|
}
|
|
_ => {
|
|
error make { msg: $"Unknown format '($format)'. Valid: table, dot" }
|
|
}
|
|
}
|
|
}
|