Final large batch of single-star conversions.
Orchestrator facades (Layer 3, expanded to explicit symbol lists):
config/accessor.nu 18 symbols (bridges accessor/mod)
config/accessor_generated.nu 18 symbols (consumer of accessor)
utils/version.nu 35 symbols (bridges version/mod)
dependencies/mod.nu 7 symbols from resolver.nu
oci_registry/mod.nu 12 multi-word "oci-registry X" subcommands
oci/commands.nu 12 symbols from oci/client.nu
Selective imports (Layer 2):
platform/discovery.nu target.nu [5 symbols]
platform/health.nu target.nu [2 symbols]
platform/connection.nu user/config [get-active-workspace]
vm/preparer.nu vm/detector [check-vm-capability]
vm/backend_libvirt.nu result.nu [7 symbols]
extensions/tests/test_versions.nu versions [5 symbols]
utils/version/loader.nu utils/nickel_processor [ncl-eval ncl-eval-soft]
Dead imports dropped:
platform/credentials.nu user/config
platform/activation.nu target
config/cache/core.nu cache/metadata
config/interpolation/core.nu helpers/environment
utils/version/loader.nu version/core (kept nickel_processor)
Validation: all 17 files match pre-existing baselines (or 0 errors for clean
ones). Pre-existing noise in vm/, dependencies/, oci_registry/, oci/commands
is known transitive — unrelated to this work.
MILESTONE: 94% of star-imports eliminated (370 → 21).
Remaining 21 star-lines in 6 files are intentional exceptions:
- integrations/mod.nu (2 stars, re-exports already-selective children;
acceptable bounded scope)
- cmd/environment.nu (3 stars, contains ~7 undefined function calls —
needs Blocker-1 style cleanup in follow-up commit)
- providers/loader.nu (1 dynamic `use ($entry_point) *` — runtime dispatch)
- vm/cleanup_scheduler.nu (1 in string template — not a real import)
- lib_provisioning/mod.nu (13 stars — root facade; empties in ADR-025 Phase 4)
Refs: ADR-025
740 lines
27 KiB
Text
740 lines
27 KiB
Text
# NOTE: Nickel plugin is loaded for direct access to nickel-export command
|
|
#export-env {
|
|
# if ((version).installed_plugins | str contains "nickel") {
|
|
# plugin use nickel
|
|
# }
|
|
#}
|
|
|
|
#plugin rm "~/.local/bin/nu_plugin_nickel"
|
|
#plugin add "~/.local/bin/nu_plugin_nickel"
|
|
|
|
# Selective imports — absolute paths from nulib/ root (ADR-025 Phase 3 pilot).
|
|
# Former star-imports (8) replaced with named-symbol imports to stop the root
|
|
# lib_provisioning/mod.nu chain from propagating the full export graph.
|
|
use lib_provisioning/config/accessor/core.nu [config-get]
|
|
use lib_provisioning/context.nu [setup_user_context]
|
|
use lib_provisioning/sops/lib.nu [is_sops_file decode_sops_file on_sops]
|
|
use lib_provisioning/user/config.nu [get-workspace-default-infra get-workspace-path]
|
|
use lib_provisioning/utils/error.nu [throw-error]
|
|
use lib_provisioning/utils/init.nu [get-provisioning-infra-path get-provisioning-name get-provisioning-resources get-work-format]
|
|
use lib_provisioning/utils/interface.nu [_ansi _print]
|
|
use lib_provisioning/utils/logging.nu [is-debug-enabled]
|
|
use lib_provisioning/utils/nickel_processor.nu [ncl-eval ncl-eval-soft process_nickel_export_raw]
|
|
use lib_provisioning/workspace/detection.nu [detect-infra-from-pwd get-effective-workspace infer-workspace-from-pwd]
|
|
# Cross-tree import (target is outside nulib/): extensions/ is the public API
|
|
# consumed by workspaces. Relative path is unavoidable here.
|
|
use ../../../../extensions/providers/prov_lib/middleware.nu [mw_create_cache mw_ip_from_cache]
|
|
|
|
# Get default settings filename (Nickel format post-migration)
|
|
def get-default-settings [] : nothing -> string {
|
|
"settings.ncl"
|
|
}
|
|
|
|
|
|
# No-op function for backward compatibility
|
|
# This function was used to set workspace context but is now handled by config system
|
|
export def set-wk-cnprov [
|
|
wk_path: string
|
|
] {
|
|
# Config system now handles workspace context automatically
|
|
# This function remains for backward compatibility
|
|
}
|
|
|
|
export def find_get_settings [
|
|
--infra (-i): string # Infra directory
|
|
--settings (-s): string # Settings path
|
|
include_notuse: bool = false
|
|
no_error: bool = false
|
|
] {
|
|
#use utils/settings.nu [ load_settings ]
|
|
if $infra != null {
|
|
if $settings != null {
|
|
(load_settings --infra $infra --settings $settings $include_notuse $no_error)
|
|
} else {
|
|
(load_settings --infra $infra $include_notuse $no_error)
|
|
}
|
|
} else {
|
|
if $settings != null {
|
|
(load_settings --settings $settings $include_notuse $no_error)
|
|
} else {
|
|
(load_settings $include_notuse $no_error)
|
|
}
|
|
}
|
|
}
|
|
export def check_env [
|
|
] {
|
|
# TuDO
|
|
true
|
|
}
|
|
export def get_context_infra_path [
|
|
] {
|
|
let context = (setup_user_context)
|
|
if $context == null or $context.infra == null { return "" }
|
|
if $context.infra_path? != null and ($context.infra_path | path join $context.infra | path exists) {
|
|
return ($context.infra_path| path join $context.infra)
|
|
}
|
|
if ((get-provisioning-infra-path) | path join $context.infra | path exists) {
|
|
return ((get-provisioning-infra-path) | path join $context.infra)
|
|
}
|
|
""
|
|
}
|
|
export def get_infra [
|
|
infra?: string
|
|
--workspace: string = ""
|
|
] {
|
|
# Priority 1: Explicit --infra flag (highest)
|
|
if ($infra | is-not-empty) {
|
|
# Resolve infra names to real infra dirs before accepting arbitrary existing paths.
|
|
let effective_ws = if ($workspace | is-not-empty) {
|
|
$workspace
|
|
} else {
|
|
do -i { get-effective-workspace } | default ""
|
|
}
|
|
let ws_path = if ($effective_ws | is-not-empty) {
|
|
do -i { get-workspace-path $effective_ws } | default ""
|
|
} else { "" }
|
|
let ws_infra_path = if ($ws_path | is-not-empty) {
|
|
[$ws_path "infra" $infra] | path join
|
|
} else { "" }
|
|
let pwd_candidate = ($env.PWD | path join "infra" $infra)
|
|
let workspace_root_candidate = if ($infra | path exists) and (($infra | path type) == "dir") {
|
|
let workspace_config = ($infra | path join "config" "provisioning.ncl")
|
|
let nested_infra = ($infra | path join "infra" $infra)
|
|
if ($workspace_config | path exists) and ((($nested_infra | path join (get-default-settings)) | path exists) or (($nested_infra | path join "main.ncl") | path exists)) {
|
|
$nested_infra
|
|
} else {
|
|
""
|
|
}
|
|
} else { "" }
|
|
let direct_settings = ($infra | path join (get-default-settings))
|
|
let direct_main = ($infra | path join "main.ncl")
|
|
|
|
if ($infra | path exists) and (($infra | path type) == "dir") and (($direct_settings | path exists) or ($direct_main | path exists)) {
|
|
$infra
|
|
} else if ($workspace_root_candidate | is-not-empty) {
|
|
$workspace_root_candidate
|
|
} else if ($direct_settings | path exists) or ($direct_main | path exists) {
|
|
$infra
|
|
} else if ($ws_infra_path | is-not-empty) and (($ws_infra_path | path join (get-default-settings) | path exists) or (($ws_infra_path | path join "main.ncl") | path exists)) {
|
|
$ws_infra_path
|
|
} else if (($pwd_candidate | path join (get-default-settings)) | path exists) or (($pwd_candidate | path join "main.ncl") | path exists) {
|
|
$pwd_candidate
|
|
} else if ((get-provisioning-infra-path) | path join $infra | path join (get-default-settings) | path exists) {
|
|
(get-provisioning-infra-path) | path join $infra
|
|
} else {
|
|
let text = $"($infra) on ((get-provisioning-infra-path) | path join $infra)"
|
|
(throw-error "🛑 Path not found " $text "get_infra" --span (metadata $infra).span)
|
|
}
|
|
} else {
|
|
# Priority 2: PWD detection
|
|
if ($env.PWD | path join (get-default-settings) | path exists) {
|
|
return $env.PWD
|
|
}
|
|
|
|
let pwd_infra = (detect-infra-from-pwd)
|
|
if ($pwd_infra | is-not-empty) {
|
|
let effective_ws = if ($workspace | is-not-empty) {
|
|
$workspace
|
|
} else {
|
|
(get-effective-workspace)
|
|
}
|
|
let ws_path = (get-workspace-path $effective_ws)
|
|
let infra_path = ([$ws_path "infra" $pwd_infra] | path join)
|
|
if ($infra_path | path join (get-default-settings) | path exists) {
|
|
return $infra_path
|
|
}
|
|
}
|
|
|
|
# Priority 2.5: workspace root config/provisioning.ncl in PWD (no registration needed)
|
|
let ws_config_file = ($env.PWD | path join "config" "provisioning.ncl")
|
|
if ($ws_config_file | path exists) {
|
|
let current_infra = (ncl-eval-soft $ws_config_file [] null | get -o current_infra | default "")
|
|
if ($current_infra | is-not-empty) {
|
|
let infra_path = ($env.PWD | path join "infra" $current_infra)
|
|
if ($infra_path | path join (get-default-settings) | path exists) {
|
|
return $infra_path
|
|
}
|
|
}
|
|
}
|
|
|
|
# Priority 2.6: convention — workspace dir name = infra name (zero-config fallback)
|
|
let convention_path = ($env.PWD | path join "infra" ($env.PWD | path basename))
|
|
if ($convention_path | path join (get-default-settings) | path exists) {
|
|
return $convention_path
|
|
}
|
|
|
|
# Priority 3: Default infra from workspace config
|
|
# Try PWD-inferred workspace first so CWD takes precedence over the active workspace
|
|
let effective_ws = if ($workspace | is-not-empty) {
|
|
$workspace
|
|
} else {
|
|
let inferred = do -i { infer-workspace-from-pwd } | default ""
|
|
if ($inferred | is-not-empty) { $inferred } else {
|
|
do -i { get-effective-workspace } | default ""
|
|
}
|
|
}
|
|
|
|
let default_infra = (get-workspace-default-infra $effective_ws)
|
|
if ($default_infra | is-not-empty) {
|
|
let ws_path = (get-workspace-path $effective_ws)
|
|
let infra_path = ([$ws_path "infra" $default_infra] | path join)
|
|
if ($infra_path | path join (get-default-settings) | path exists) {
|
|
return $infra_path
|
|
}
|
|
}
|
|
|
|
# Priority 4: session config — infra.current (consulted only after all PWD checks fail)
|
|
let session_infra = (do -i { config-get "infra.current" "" } | default "")
|
|
if ($session_infra | is-not-empty) {
|
|
let effective_ws2 = if ($workspace | is-not-empty) { $workspace } else {
|
|
do -i { get-effective-workspace } | default ""
|
|
}
|
|
let ws_path2 = if ($effective_ws2 | is-not-empty) {
|
|
do -i { get-workspace-path $effective_ws2 } | default ""
|
|
} else { "" }
|
|
let session_infra_path = if ($ws_path2 | is-not-empty) {
|
|
[$ws_path2 "infra" $session_infra] | path join
|
|
} else { "" }
|
|
if ($session_infra_path | is-not-empty) and ($session_infra_path | path join (get-default-settings) | path exists) {
|
|
return $session_infra_path
|
|
}
|
|
}
|
|
|
|
# Fallback: Context-based resolution
|
|
if ((get-provisioning-infra-path) | path join ($env.PWD | path basename) |
|
|
path join (get-default-settings) | path exists) {
|
|
return ((get-provisioning-infra-path) | path join ($env.PWD | path basename))
|
|
}
|
|
|
|
let context_path = get_context_infra_path
|
|
if $context_path != "" { return $context_path }
|
|
|
|
# Last resort: return workspace root
|
|
let effective_ws = if ($workspace | is-not-empty) {
|
|
$workspace
|
|
} else {
|
|
(get-effective-workspace)
|
|
}
|
|
(get-workspace-path $effective_ws)
|
|
}
|
|
}
|
|
export def parse_nickel_file [
|
|
src: string
|
|
target: string
|
|
append: bool
|
|
msg: string
|
|
err_exit?: bool = false
|
|
] {
|
|
# Guard: Check source file exists
|
|
if not ($src | path exists) {
|
|
let text = $"nickel source not found: ($src)"
|
|
(throw-error $msg $text "parse_nickel_file" --span (metadata $src).span)
|
|
if $err_exit { exit 1 }
|
|
return false
|
|
}
|
|
|
|
# Process Nickel file
|
|
let format = if (get-work-format) == "json" { "json" } else { "yaml" }
|
|
let raw_out = (process_nickel_export_raw $src $format)
|
|
let result = (^nu -c $"'($raw_out)' | from json")
|
|
|
|
if ($result | is-empty) {
|
|
let text = $"nickel ($src) compilation failed - check Nickel syntax"
|
|
(throw-error $msg $text "parse_nickel_file" --span (metadata $src).span)
|
|
if $err_exit { exit 1 }
|
|
return false
|
|
}
|
|
|
|
if $append {
|
|
$result | save --append $target
|
|
} else {
|
|
$result | save -f $target
|
|
}
|
|
true
|
|
}
|
|
export def load_from_wk_format [
|
|
src: string
|
|
] {
|
|
if not ( $src | path exists) { return {} }
|
|
let data_raw = (open -r $src)
|
|
if (get-work-format) == "json" {
|
|
$data_raw | from json | default {}
|
|
} else {
|
|
$data_raw | from yaml | default {}
|
|
}
|
|
}
|
|
export def load_defaults [
|
|
src_path: string
|
|
item_path: string
|
|
target_path: string
|
|
] {
|
|
if ($target_path | path exists) {
|
|
if (is_sops_file $target_path) { decode_sops_file $src_path $target_path true }
|
|
retrurn
|
|
}
|
|
let full_path = if ($item_path | path exists) {
|
|
($item_path)
|
|
} else if ($"($item_path).ncl" | path exists) {
|
|
$"($item_path).ncl"
|
|
} else if ($src_path | path dirname | path join $"($item_path).ncl" | path exists) {
|
|
$src_path | path dirname | path join $"($item_path).ncl"
|
|
} else {
|
|
""
|
|
}
|
|
if $full_path == "" { return true }
|
|
if (is_sops_file $full_path) {
|
|
decode_sops_file $full_path $target_path true
|
|
(parse_nickel_file $target_path $target_path false $"🛑 load default settings failed ($target_path) ")
|
|
} else {
|
|
(parse_nickel_file $full_path $target_path false $"🛑 load default settings failed ($full_path)")
|
|
}
|
|
}
|
|
export def get_provider_env [
|
|
settings: record
|
|
server: record
|
|
] {
|
|
let prov_env_path = if ($server.prov_settings | path exists ) {
|
|
$server.prov_settings
|
|
} else {
|
|
let file_path = ($settings.src_path | path join $server.prov_settings)
|
|
if ($file_path | str ends-with '.ncl' ) { $file_path } else { $"($file_path).ncl" }
|
|
}
|
|
if not ($prov_env_path| path exists ) {
|
|
if (is-debug-enabled) { _print $"🛑 load (_ansi cyan_bold)provider_env(_ansi reset) from ($server.prov_settings) failed at ($prov_env_path)" }
|
|
return {}
|
|
}
|
|
let str_created_taskservs_dirpath = ($settings.data.created_taskservs_dirpath | default "/tmp" |
|
|
str replace "\~" $env.HOME | str replace "NOW" $env.NOW | str replace "./" $"($settings.src_path)/")
|
|
let created_taskservs_dirpath = if ($str_created_taskservs_dirpath | str starts-with "/" ) { $str_created_taskservs_dirpath } else { $settings.src_path | path join $str_created_taskservs_dirpath }
|
|
if not ( $created_taskservs_dirpath | path exists) { ^mkdir -p $created_taskservs_dirpath }
|
|
let source_settings_path = ($created_taskservs_dirpath | path join $"($prov_env_path | path basename)")
|
|
let target_settings_path = ($created_taskservs_dirpath| path join $"($prov_env_path | path basename | str replace '.ncl' '').((get-work-format))")
|
|
let res = if (is_sops_file $prov_env_path) {
|
|
decode_sops_file $prov_env_path $source_settings_path true
|
|
(parse_nickel_file $source_settings_path $target_settings_path false $"🛑 load prov settings failed ($target_settings_path)")
|
|
} else {
|
|
cp $prov_env_path $source_settings_path
|
|
(parse_nickel_file $source_settings_path $target_settings_path false $"🛑 load prov settings failed ($prov_env_path)")
|
|
}
|
|
if not (is-debug-enabled) { rm -f $source_settings_path }
|
|
if $res and ($target_settings_path | path exists) {
|
|
let data = (open $target_settings_path)
|
|
if not (is-debug-enabled) { rm -f $target_settings_path }
|
|
$data
|
|
} else {
|
|
{}
|
|
}
|
|
}
|
|
export def get_file_format [
|
|
filename: string
|
|
] {
|
|
if ($filename | str ends-with ".json") {
|
|
"json"
|
|
} else if ($filename | str ends-with ".yaml") {
|
|
"yaml"
|
|
} else {
|
|
(get-work-format)
|
|
}
|
|
}
|
|
export def save_provider_env [
|
|
data: record
|
|
settings: record
|
|
provider_path: string
|
|
] {
|
|
if ($provider_path | is-empty) or not ($provider_path | path dirname |path exists) {
|
|
_print $"❗ Can not save provider env for (_ansi blue)($provider_path | path dirname)(_ansi reset) in (_ansi red)($provider_path)(_ansi reset )"
|
|
return
|
|
}
|
|
if (get_file_format $provider_path) == "json" {
|
|
$"data: ($data | to json | encode base64)" | save --force $provider_path
|
|
} else {
|
|
$"data: ($data | to yaml | encode base64)" | save --force $provider_path
|
|
}
|
|
let result = (on_sops "encrypt" $provider_path --quiet)
|
|
if ($result | is-not-empty) {
|
|
($result | save --force $provider_path)
|
|
}
|
|
}
|
|
export def get_provider_data_path [
|
|
settings: record
|
|
server: record
|
|
] {
|
|
# Get prov_data_dirpath with fallbacks for different settings structures
|
|
let prov_data_dir = (
|
|
$settings.data.prov_data_dirpath?
|
|
| default ($settings.prov_data_dirpath? | default "./data")
|
|
)
|
|
|
|
let data_path = if ($prov_data_dir | str starts-with "." ) {
|
|
let base = ($settings.src_path? | default ($settings.infra_path? | default "."))
|
|
($base | path join $prov_data_dir)
|
|
} else {
|
|
$prov_data_dir
|
|
}
|
|
if not ($data_path | path exists) { ^mkdir -p $data_path }
|
|
($data_path | path join $"($server.provider)_cache.((get-work-format))")
|
|
}
|
|
export def load_provider_env [
|
|
settings: record
|
|
server: record
|
|
provider_path: string = ""
|
|
] {
|
|
let data = if ($provider_path | is-not-empty) and ($provider_path |path exists) {
|
|
let file_data = if (is_sops_file $provider_path) {
|
|
on_sops "decrypt" $provider_path --quiet
|
|
let result = (on_sops "decrypt" $provider_path --quiet)
|
|
# --character-set binhex
|
|
if (get_file_format $provider_path) == "json" {
|
|
($result | from json | get data? | default "" | decode base64 | decode | from json)
|
|
} else {
|
|
($result | from yaml | get data? | default "" | decode base64 | decode | from yaml)
|
|
}
|
|
} else {
|
|
open $provider_path
|
|
}
|
|
if ($file_data | is-empty) or ($file_data | get main?.vpc? | default null) == "?" {
|
|
# (throw-error $"load provider ($server.provider) settings failed" $"($provider_path) no main data"
|
|
# "load_provider_env" --span (metadata $data).span)
|
|
if (is-debug-enabled) { _print $"load provider ($server.provider) settings failed ($provider_path) no main data in load_provider_env" }
|
|
{}
|
|
} else {
|
|
$file_data
|
|
}
|
|
} else {
|
|
{}
|
|
}
|
|
if ($data | is-empty) {
|
|
let new_data = (get_provider_env $settings $server)
|
|
if ($new_data | is-not-empty) and ($provider_path | is-not-empty) { save_provider_env $new_data $settings $provider_path }
|
|
$new_data
|
|
} else {
|
|
$data
|
|
}
|
|
}
|
|
export def load_provider_settings [
|
|
settings: record
|
|
server: record
|
|
] {
|
|
let data_path = if ($settings.data.settings.prov_data_dirpath | str starts-with "." ) {
|
|
($settings.src_path | path join $settings.data.settings.prov_data_dirpath)
|
|
} else { $settings.data.settings.prov_data_dirpath }
|
|
if ($data_path | is-empty) {
|
|
(throw-error $"load provider ($server.provider) settings failed" $"($settings.data.settings.prov_data_dirpath)"
|
|
"load_provider_settings" --span (metadata $data_path).span)
|
|
}
|
|
if not ($data_path | path exists) { ^mkdir -p $data_path }
|
|
let provider_path = ($data_path | path join $"($server.provider)_cache.((get-work-format))")
|
|
let data = (load_provider_env $settings $server $provider_path)
|
|
if ($data | is-empty) or ($data | get main?.vpc? | default null) == "?" {
|
|
mw_create_cache $settings $server false
|
|
(load_provider_env $settings $server $provider_path)
|
|
} else {
|
|
$data
|
|
}
|
|
}
|
|
|
|
# Helper function: Load servers from definition files
|
|
def load-servers-from-definitions [
|
|
servers_paths: list
|
|
src_path: string
|
|
wk_settings_path: string
|
|
no_error: bool
|
|
] {
|
|
mut loaded_servers = []
|
|
|
|
for it in $servers_paths {
|
|
let file_path = if ($it | str ends-with ".ncl") {
|
|
$it
|
|
} else {
|
|
$"($it).ncl"
|
|
}
|
|
let server_path = if ($file_path | str starts-with "/") {
|
|
$file_path
|
|
} else {
|
|
($src_path | path dirname | path join $file_path)
|
|
}
|
|
if not ($server_path | path exists) {
|
|
if $no_error {
|
|
"" | save $server_path
|
|
} else {
|
|
(throw-error "🛑 server path not found " ($server_path) "load-servers-from-definitions" --span (metadata $servers_paths).span)
|
|
}
|
|
continue
|
|
}
|
|
|
|
let target_settings_path = $"($wk_settings_path)/($it | str replace --all "/" "_").((get-work-format))"
|
|
if not (parse_nickel_file ($server_path) $target_settings_path false "🛑 load settings failed ") {
|
|
continue
|
|
}
|
|
if not ($target_settings_path | path exists) {
|
|
continue
|
|
}
|
|
|
|
let servers_defs = (open $target_settings_path | default {})
|
|
let servers = ($servers_defs | get servers? | default [])
|
|
$loaded_servers = ($loaded_servers | append $servers)
|
|
}
|
|
|
|
$loaded_servers
|
|
}
|
|
|
|
# Helper function: Process individual server with defaults and provider data
|
|
def process-server [
|
|
server: record
|
|
settings_data: record
|
|
src_path: string
|
|
src_dir: string
|
|
wk_settings_path: string
|
|
data_fullpath: string
|
|
infra_path: string
|
|
include_notuse: bool
|
|
providers_settings: list
|
|
] {
|
|
# Filter out servers with not_use=True when include_notuse is false
|
|
if not $include_notuse and ($server | get not_use? | default false) {
|
|
return {
|
|
server: null
|
|
providers_settings: $providers_settings
|
|
}
|
|
}
|
|
|
|
let provider = $server.provider
|
|
|
|
# Load provider defaults if not already loaded
|
|
if not ($"($wk_settings_path)/($provider)($settings_data.settings.defaults_provs_suffix).((get-work-format))" | path exists) {
|
|
let dflt_item = ($settings_data.settings.defaults_provs_dirpath | path join $"($provider)($settings_data.settings.defaults_provs_suffix)")
|
|
let dflt_item_fullpath = if ($dflt_item | str starts-with ".") {
|
|
($src_dir | path join $dflt_item)
|
|
} else {
|
|
$dflt_item
|
|
}
|
|
load_defaults $src_path $dflt_item_fullpath ($wk_settings_path | path join $"($provider)($settings_data.settings.defaults_provs_suffix).((get-work-format))")
|
|
}
|
|
|
|
# Merge server with provider defaults
|
|
let server_with_dflts = if ($"($wk_settings_path)/($provider)($settings_data.settings.defaults_provs_suffix).((get-work-format))" | path exists) {
|
|
open ($"($wk_settings_path)/($provider)($settings_data.settings.defaults_provs_suffix).((get-work-format))") | merge $server
|
|
} else {
|
|
$server
|
|
}
|
|
|
|
# Load provider-level data settings
|
|
let server_prov_data = if ($data_fullpath | path join $"($provider)($settings_data.settings.prov_data_suffix)" | path exists) {
|
|
(load_defaults $src_dir ($data_fullpath | path join $"($provider)($settings_data.settings.prov_data_suffix)")
|
|
($wk_settings_path | path join $"($provider)($settings_data.settings.prov_data_suffix)")
|
|
)
|
|
if (($wk_settings_path | path join $"($provider)($settings_data.settings.prov_data_suffix)") | path exists) {
|
|
$server_with_dflts | merge (load_from_wk_format ($wk_settings_path | path join $"($provider)($settings_data.settings.prov_data_suffix)"))
|
|
} else {
|
|
$server_with_dflts
|
|
}
|
|
} else {
|
|
$server_with_dflts
|
|
}
|
|
|
|
# Load server-specific data settings
|
|
let server_with_data = if ($data_fullpath | path join $"($server.hostname)_($provider)($settings_data.settings.prov_data_suffix)" | path exists) {
|
|
(load_defaults $src_dir ($data_fullpath | path join $"($server.hostname)_($provider)($settings_data.settings.prov_data_suffix)")
|
|
($wk_settings_path | path join $"($server.hostname)_($provider)($settings_data.settings.prov_data_suffix)")
|
|
)
|
|
if ($wk_settings_path | path join $"($server.hostname)_($provider)($settings_data.settings.prov_data_suffix)" | path exists) {
|
|
$server_prov_data | merge (load_from_wk_format ($wk_settings_path | path join $"($server.hostname)_($provider)($settings_data.settings.prov_data_suffix)"))
|
|
} else {
|
|
$server_prov_data
|
|
}
|
|
} else {
|
|
$server_prov_data
|
|
}
|
|
|
|
# Load provider settings if not already loaded
|
|
mut updated_providers = $providers_settings
|
|
if ($providers_settings | where {|it| $it.provider == $provider} | length) == 0 {
|
|
$updated_providers = ($updated_providers | append {
|
|
provider: $provider,
|
|
settings: (load_provider_settings {
|
|
data: $settings_data,
|
|
providers: $providers_settings,
|
|
src: ($src_path | path basename),
|
|
src_path: ($src_path | path dirname),
|
|
infra: ($infra_path | path basename),
|
|
infra_path: ($infra_path | path dirname),
|
|
wk_path: $wk_settings_path
|
|
}
|
|
$server_with_data)
|
|
})
|
|
}
|
|
|
|
{
|
|
server: $server_with_data
|
|
providers_settings: $updated_providers
|
|
}
|
|
}
|
|
export def load [
|
|
infra?: string
|
|
in_src?: string
|
|
include_notuse?: bool = false
|
|
--no_error
|
|
] {
|
|
let source = if $in_src == null or ($in_src | str ends-with '.ncl' ) { $in_src } else { $"($in_src).ncl" }
|
|
|
|
# Try to determine the source path to load
|
|
let source_path = if $source != null and ($source | path type) == "dir" {
|
|
# If source is a directory, try main.ncl first (new pattern), then settings.ncl (legacy)
|
|
let main_path = $"($source)/main.ncl"
|
|
let settings_path = $"($source)/settings.ncl"
|
|
if ($main_path | path exists) {
|
|
$main_path
|
|
} else if ($settings_path | path exists) {
|
|
$settings_path
|
|
} else {
|
|
$source
|
|
}
|
|
} else {
|
|
$source
|
|
}
|
|
|
|
let src_path = if $source_path != null and ($source_path | path exists) {
|
|
$source_path
|
|
} else if ($infra | is-not-empty) and (($infra | path join "main.ncl") | path exists) {
|
|
$infra | path join "main.ncl"
|
|
} else if ($infra | is-not-empty) and (($infra | path join (get-default-settings)) | path exists) {
|
|
$infra | path join (get-default-settings)
|
|
} else if ($infra | is-not-empty) {
|
|
# Infra specified but files not found
|
|
if $no_error { return {} } else { return }
|
|
} else if ((get-default-settings) | path exists) {
|
|
$"./((get-default-settings))"
|
|
} else {
|
|
# No source found - return empty record gracefully
|
|
if $no_error { return {} } else { return }
|
|
}
|
|
|
|
let src_dir = ($src_path | path dirname)
|
|
let infra_path = if $src_dir == "." {
|
|
$env.PWD
|
|
} else if ($src_dir | is-empty) {
|
|
$env.PWD | path join $infra
|
|
} else if ($src_dir | path exists) and ($src_dir | str starts-with "/") {
|
|
$src_dir
|
|
} else {
|
|
$env.PWD | path join $src_dir
|
|
}
|
|
|
|
# Guard: Check source file exists
|
|
if not ($src_path | path exists) {
|
|
if $no_error { return {} } else { return }
|
|
}
|
|
|
|
# Convert to absolute path (handles both relative and absolute paths)
|
|
let abs_path = ($src_path | path expand)
|
|
# Cache not updated
|
|
# let config = (ncl-eval $abs_path [] | from json)
|
|
# print $config_p.servers.server_type
|
|
let prov_root = ($env.PROVISIONING? | default "/usr/local/provisioning")
|
|
let config = (ncl-eval $abs_path [$prov_root])
|
|
|
|
# Filter servers by include_notuse flag: keep only enabled servers
|
|
let filtered_servers = ($config.servers | where { |s|
|
|
(not ($s.not_use? | default false)) and ($s.enabled? | default true)
|
|
})
|
|
|
|
# Return standardized settings structure (expected by provisioning CLI)
|
|
{
|
|
data: ($config | merge { servers: $filtered_servers })
|
|
providers: ($config.providers? | default [])
|
|
src: ($src_path | path basename)
|
|
src_path: ($src_path | path dirname)
|
|
infra_path: $infra_path
|
|
wk_path: (mktemp -d)
|
|
}
|
|
}
|
|
export def load_settings [
|
|
--infra (-i): string
|
|
--settings (-s): string # Settings path
|
|
include_notuse: bool = false
|
|
no_error: bool = false
|
|
] {
|
|
let kld = get_infra (if $infra == null { "" } else { $infra })
|
|
if $no_error {
|
|
(load $kld $settings $include_notuse --no_error)
|
|
} else {
|
|
(load $kld $settings $include_notuse)
|
|
}
|
|
# let settings = (load $kld $settings $exclude_not_use)
|
|
# if $env.PROVISIONING_USE_SOPS? != "" {
|
|
# use sops/lib.nu check_sops
|
|
# check_sops $settings.src_path
|
|
# }
|
|
# $settings
|
|
}
|
|
export def save_settings_file [
|
|
settings: record
|
|
target_file: string
|
|
match_text: string
|
|
new_text: string
|
|
mark_changes: bool = false
|
|
] {
|
|
let it_path = if ($target_file | path exists) {
|
|
$target_file
|
|
} else if ($settings.src_path | path join $"($target_file).ncl" | path exists) {
|
|
($settings.src_path | path join $"($target_file).ncl")
|
|
} else if ($settings.src_path | path join $"($target_file).((get-work-format))" | path exists) {
|
|
($settings.src_path | path join $"($target_file).((get-work-format))")
|
|
} else {
|
|
_print $"($target_file) not found in ($settings.src_path)"
|
|
return false
|
|
}
|
|
if (is_sops_file $it_path) {
|
|
let result = (on_sops "decrypt" $it_path --quiet)
|
|
if ($result | is-empty) {
|
|
(throw-error $"🛑 saving settings to ($it_path)"
|
|
$"from ($match_text) to ($new_text)"
|
|
$"in ($target_file)" --span (metadata $it_path).span)
|
|
return false
|
|
} else {
|
|
$result | str replace $match_text $new_text| save --force $it_path
|
|
let en_result = (on_sops "encrypt" $it_path --quiet)
|
|
if ($en_result | is-not-empty) {
|
|
($en_result | save --force $it_path)
|
|
}
|
|
}
|
|
} else {
|
|
open $it_path --raw | str replace $match_text $new_text | save --force $it_path
|
|
}
|
|
#if $it_path != "" and (^grep -q $match_text $it_path | complete).exit_code == 0 {
|
|
# if (^sed -i $"s/($match_text)/($match_text)\"($new_text)\"/g" $it_path | complete).exit_code == 0 {
|
|
_print $"($target_file) saved with new value "
|
|
if $mark_changes {
|
|
if ($settings.wk_path | path join "changes" | path exists) == false {
|
|
$"($it_path) has been changed" | save ($settings.wk_path | path join "changes") --append
|
|
}
|
|
} else if ((get-provisioning-module) | is-not-empty) {
|
|
^(get-provisioning-name) "-mod" (get-provisioning-module) $env.PROVISIONING_ARGS
|
|
exit
|
|
}
|
|
# }
|
|
#}
|
|
}
|
|
export def save_servers_settings [
|
|
settings: record
|
|
match_text: string
|
|
new_text: string
|
|
] {
|
|
$settings.data.servers_paths | each { | it |
|
|
save_settings_file $settings $it $match_text $new_text
|
|
}
|
|
}
|
|
export def settings_with_env [
|
|
settings: record
|
|
] {
|
|
mut $servers_with_ips = []
|
|
for srv in ($settings.data.servers) {
|
|
let pub_ip = (mw_ip_from_cache $settings $srv false)
|
|
if ($pub_ip | is-empty) {
|
|
$servers_with_ips = ($servers_with_ips | append ($srv))
|
|
} else {
|
|
$servers_with_ips = ($servers_with_ips | append ($srv | merge { network_public_ip: $pub_ip }))
|
|
}
|
|
}
|
|
($settings | merge { data: ($settings.data | merge { servers: $servers_with_ips}) })
|
|
}
|