feat: add config module and agent setup for migration
- Add config module from backup (loader, accessor, migration) - Add agent reference cards for token-efficient migration - Add migration knowledge base and instructions - Ready to start systematic config-driven migration
This commit is contained in:
parent
a509868257
commit
0a837aed54
37
.migration/knowledge/AGENT_INSTRUCTIONS.md
Normal file
37
.migration/knowledge/AGENT_INSTRUCTIONS.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Agent Instructions Template (Token-Efficient)
|
||||||
|
|
||||||
|
## Syntax Fixer Agent
|
||||||
|
```markdown
|
||||||
|
TASK: Fix syntax errors in FILE_PATH
|
||||||
|
PATTERNS: See SYNTAX_FIX_CARD.md
|
||||||
|
OUTPUT: {"status": "fixed", "changes": N, "test_passed": bool}
|
||||||
|
TEST: nu --ide-check FILE_PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
## ENV Migrator Agent
|
||||||
|
```markdown
|
||||||
|
TASK: Replace ENV vars in FILE_PATH
|
||||||
|
MAPPING: See ENV_MAPPING_CARD.md
|
||||||
|
KEEP: PROVISIONING_ARGS, PROVISIONING_OUT, NOW, CURRENT_*
|
||||||
|
OUTPUT: {"status": "migrated", "replacements": N}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validator Agent
|
||||||
|
```markdown
|
||||||
|
TASK: Test FILE_PATH works
|
||||||
|
COMMANDS: nu --ide-check FILE_PATH
|
||||||
|
OUTPUT: {"syntax_valid": bool, "errors": []}
|
||||||
|
```
|
||||||
|
|
||||||
|
## File Analyzer Agent
|
||||||
|
```markdown
|
||||||
|
TASK: Find issues in FILE_PATH
|
||||||
|
FIND: syntax errors, env refs, hardcoded paths
|
||||||
|
OUTPUT: {"syntax_errors": [], "env_refs": [], "paths": []}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Token Budget
|
||||||
|
- Single file: ~500-1000 tokens
|
||||||
|
- Pattern reference: ~200 tokens
|
||||||
|
- Instructions: ~300 tokens
|
||||||
|
- Total per agent: ~1000-1500 tokens
|
35
.migration/knowledge/ENV_MAPPING_CARD.md
Normal file
35
.migration/knowledge/ENV_MAPPING_CARD.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# ENV → Accessor Mapping (Token-Efficient Reference)
|
||||||
|
|
||||||
|
## Critical Mappings
|
||||||
|
|
||||||
|
### Core Variables
|
||||||
|
```nushell
|
||||||
|
$env.PROVISIONING → (get-base-path)
|
||||||
|
$env.PROVISIONING_DEBUG → (is-debug-enabled)
|
||||||
|
$env.PROVISIONING_OUT → (get-provisioning-out)
|
||||||
|
$env.PROVISIONING_ARGS → (get-provisioning-args)
|
||||||
|
$env.PROVISIONING_MODULE → (get-provisioning-module)
|
||||||
|
$env.PROVISIONING_NAME → (get-provisioning-name)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Path Variables
|
||||||
|
```nushell
|
||||||
|
$env.PROVISIONING_PROVIDERS_PATH → (get-providers-path)
|
||||||
|
$env.PROVISIONING_TASKSERVS_PATH → (get-taskservs-path)
|
||||||
|
$env.PROVISIONING_TOOLS_PATH → (get-tools-path)
|
||||||
|
$env.PROVISIONING_TEMPLATES_PATH → (get-templates-path)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Runtime Variables (Keep as ENV)
|
||||||
|
```nushell
|
||||||
|
$env.PROVISIONING_ARGS # Command arguments - KEEP
|
||||||
|
$env.PROVISIONING_OUT # Output redirection - KEEP
|
||||||
|
$env.NOW # Timestamps - KEEP
|
||||||
|
$env.CURRENT_* # Context variables - KEEP
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage Pattern
|
||||||
|
```nushell
|
||||||
|
# Always wrap in parentheses
|
||||||
|
let value = ((get-function-name) | default "fallback")
|
||||||
|
```
|
38
.migration/knowledge/SYNTAX_FIX_CARD.md
Normal file
38
.migration/knowledge/SYNTAX_FIX_CARD.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Syntax Fix Patterns (Token-Efficient Reference)
|
||||||
|
|
||||||
|
## Critical Patterns to Fix
|
||||||
|
|
||||||
|
### 1. Function Call Parentheses
|
||||||
|
```nushell
|
||||||
|
# BROKEN
|
||||||
|
$"(get-provisioning-args)? | default "") "
|
||||||
|
|
||||||
|
# FIXED
|
||||||
|
((get-provisioning-args) | default "")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Command Parentheses
|
||||||
|
```nushell
|
||||||
|
# BROKEN
|
||||||
|
^$"(get-provisioning-name))" -mod server
|
||||||
|
|
||||||
|
# FIXED
|
||||||
|
^(get-provisioning-name) -mod server
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Missing Function Calls
|
||||||
|
```nushell
|
||||||
|
# BROKEN
|
||||||
|
let ops = $"(get-provisioning-args)? | default "") "
|
||||||
|
|
||||||
|
# FIXED
|
||||||
|
let ops = ((get-provisioning-args) | default "")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Command
|
||||||
|
```bash
|
||||||
|
nu --ide-check FILE_PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
## Success Pattern
|
||||||
|
All function calls must be wrapped in parentheses when used in expressions.
|
715
core/nulib/lib_provisioning/config/accessor.nu
Normal file
715
core/nulib/lib_provisioning/config/accessor.nu
Normal file
@ -0,0 +1,715 @@
|
|||||||
|
# Configuration Accessor - Provides easy access to configuration values
|
||||||
|
# This module provides helper functions to access configuration safely
|
||||||
|
|
||||||
|
use std log
|
||||||
|
|
||||||
|
# Configuration cache (note: Nushell doesn't have persistent global state)
|
||||||
|
# This is a placeholder for documentation purposes
|
||||||
|
|
||||||
|
# Get the global configuration (loads and caches on first access)
|
||||||
|
export def get-config [
|
||||||
|
--reload = false # Force reload configuration
|
||||||
|
--debug = false # Enable debug logging
|
||||||
|
--environment: string # Override environment
|
||||||
|
] {
|
||||||
|
# Always reload since Nushell doesn't have persistent global state
|
||||||
|
use loader.nu load-provisioning-config
|
||||||
|
load-provisioning-config --debug=$debug --environment=$environment
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get a configuration value using dot notation (e.g., "paths.base")
|
||||||
|
export def config-get [
|
||||||
|
path: string # Configuration path (e.g., "paths.base")
|
||||||
|
default_value: any = null # Default value if path not found
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
let config_data = if ($config | is-empty) {
|
||||||
|
get-config
|
||||||
|
} else {
|
||||||
|
$config
|
||||||
|
}
|
||||||
|
|
||||||
|
use loader.nu get-config-value
|
||||||
|
get-config-value $config_data $path $default_value
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if a configuration path exists
|
||||||
|
export def config-has [
|
||||||
|
path: string # Configuration path to check
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
let config_data = if ($config | is-empty) {
|
||||||
|
get-config
|
||||||
|
} else {
|
||||||
|
$config
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = (config-get $path null --config $config_data)
|
||||||
|
($value | is-not-empty)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get all paths configuration as a convenient record
|
||||||
|
export def get-paths [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths" {} --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get debug configuration
|
||||||
|
export def get-debug [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "debug" {} --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get SOPS configuration
|
||||||
|
export def get-sops [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "sops" {} --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get validation configuration
|
||||||
|
export def get-validation [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "validation" {} --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get output configuration
|
||||||
|
export def get-output [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "output" {} --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if debug is enabled
|
||||||
|
export def is-debug-enabled [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "debug.enabled" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the base provisioning path
|
||||||
|
export def get-base-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.base" "/usr/local/provisioning" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the kloud path
|
||||||
|
export def get-kloud-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.kloud" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get SOPS key search paths
|
||||||
|
export def get-sops-key-paths [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "sops.key_search_paths" [] --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find the first existing SOPS key file
|
||||||
|
export def find-sops-key [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
let key_paths = (get-sops-key-paths --config $config)
|
||||||
|
|
||||||
|
for path in $key_paths {
|
||||||
|
if ($path | path exists) {
|
||||||
|
return $path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up environment variables for backward compatibility
|
||||||
|
export def setup-env-compat [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
let config_data = if ($config | is-empty) {
|
||||||
|
get-config
|
||||||
|
} else {
|
||||||
|
$config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up key environment variables for backward compatibility
|
||||||
|
$env.PROVISIONING = (config-get "paths.base" "/usr/local/provisioning" --config $config_data)
|
||||||
|
$env.PROVISIONING_KLOUD_PATH = (config-get "paths.kloud" "" --config $config_data)
|
||||||
|
$env.PROVISIONING_DEBUG = (config-get "debug.enabled" false --config $config_data | into string)
|
||||||
|
$env.PROVISIONING_USE_SOPS = (config-get "sops.use_sops" "age" --config $config_data)
|
||||||
|
|
||||||
|
# Set SOPS key if found
|
||||||
|
let sops_key = (find-sops-key --config $config_data)
|
||||||
|
if ($sops_key | is-not-empty) {
|
||||||
|
$env.SOPS_AGE_KEY_FILE = $sops_key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show current configuration (useful for debugging)
|
||||||
|
export def show-config [
|
||||||
|
--section: string # Show only a specific section
|
||||||
|
--format: string = "yaml" # Output format (yaml, json, table)
|
||||||
|
] {
|
||||||
|
let config_data = (get-config)
|
||||||
|
|
||||||
|
let output_data = if ($section | is-not-empty) {
|
||||||
|
config-get $section {} --config $config_data
|
||||||
|
} else {
|
||||||
|
$config_data
|
||||||
|
}
|
||||||
|
|
||||||
|
match $format {
|
||||||
|
"json" => { $output_data | to json --indent 2 | print }
|
||||||
|
"table" => { $output_data | print }
|
||||||
|
_ => { $output_data | to yaml | print }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate current configuration and show any issues
|
||||||
|
export def validate-current-config [] {
|
||||||
|
let config_data = (get-config --debug=true)
|
||||||
|
print "✅ Configuration is valid"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Helper functions to replace common (get-provisioning-* patterns
|
||||||
|
|
||||||
|
# Get provisioning name
|
||||||
|
export def get-provisioning-name [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "core.name" "provisioning" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning args
|
||||||
|
export def get-provisioning-args [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
$env.PROVISIONING_ARGS? | default ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning output path
|
||||||
|
export def get-provisioning-out [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
$env.PROVISIONING_OUT? | default ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if no-terminal mode is enabled
|
||||||
|
export def is-no-terminal [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "debug.no_terminal" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get work format (yaml/json)
|
||||||
|
export def get-work-format [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "output.format" "yaml" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get providers path
|
||||||
|
export def get-providers-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.providers" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get taskservs path
|
||||||
|
export def get-taskservs-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.taskservs" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get current timestamp
|
||||||
|
export def get-now [] {
|
||||||
|
$env.NOW? | default (date now | format date "%Y_%m_%d_%H_%M_%S")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if metadata is enabled
|
||||||
|
export def is-metadata-enabled [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "debug.metadata" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if debug check is enabled
|
||||||
|
export def is-debug-check-enabled [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "debug.check" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Helper functions for non-PROVISIONING environment variables
|
||||||
|
|
||||||
|
# Get SSH options
|
||||||
|
export def get-ssh-options [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "ssh.options" [] --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get current infrastructure path
|
||||||
|
export def get-current-infra-path [] {
|
||||||
|
$env.CURRENT_INFRA_PATH? | default ($env.PWD? | default "")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get current kloud path
|
||||||
|
export def get-current-kloud-path [] {
|
||||||
|
$env.CURRENT_KLOUD_PATH? | default ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get SOPS age key file path
|
||||||
|
export def get-sops-age-key-file [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
let sops_key = (find-sops-key --config $config)
|
||||||
|
if ($sops_key | is-not-empty) { $sops_key } else { "" }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get SOPS age recipients
|
||||||
|
export def get-sops-age-recipients [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
$env.SOPS_AGE_RECIPIENTS? | default ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get KCL module path
|
||||||
|
export def get-kcl-mod-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
let config_data = if ($config | is-empty) { get-config } else { $config }
|
||||||
|
let base_path = (config-get "paths.base" "" --config $config_data)
|
||||||
|
let providers_path = (config-get "paths.providers" "" --config $config_data)
|
||||||
|
|
||||||
|
[
|
||||||
|
($base_path | path join "kcl")
|
||||||
|
$providers_path
|
||||||
|
($env.PWD? | default "")
|
||||||
|
] | uniq | str join ":"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get work variable for current context
|
||||||
|
export def get-wk-cnprov [] {
|
||||||
|
$env.WK_CNPROV? | default ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Setter functions for backward compatibility
|
||||||
|
|
||||||
|
# Set debug enabled state
|
||||||
|
export def set-debug-enabled [value: bool] {
|
||||||
|
$env.PROVISIONING_DEBUG = $value
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set provisioning output path
|
||||||
|
export def set-provisioning-out [path: string] {
|
||||||
|
$env.PROVISIONING_OUT = $path
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set no-terminal mode
|
||||||
|
export def set-provisioning-no-terminal [value: bool] {
|
||||||
|
$env.PROVISIONING_NO_TERMINAL = $value
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set work context path
|
||||||
|
export def set-wk-cnprov [path: string] {
|
||||||
|
$env.WK_CNPROV = $path
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set metadata enabled state
|
||||||
|
export def set-metadata-enabled [value: bool] {
|
||||||
|
$env.PROVISIONING_METADATA = $value
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning work format
|
||||||
|
export def get-provisioning-wk-format [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "output.format" "yaml" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning version
|
||||||
|
export def get-provisioning-vers [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "core.version" "2.0.0" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning no terminal
|
||||||
|
export def get-provisioning-no-terminal [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "debug.no_terminal" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning generate directory path
|
||||||
|
export def get-provisioning-generate-dirpath [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.generate" "generate" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning generate defs file
|
||||||
|
export def get-provisioning-generate-defsfile [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.files.defs" "defs.nu" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning required versions file path
|
||||||
|
export def get-provisioning-req-versions [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.files.req_versions" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Additional accessor functions for remaining variables
|
||||||
|
|
||||||
|
# Get provisioning vars path
|
||||||
|
export def get-provisioning-vars [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.files.vars" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning work environment path
|
||||||
|
export def get-provisioning-wk-env-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
$env.PROVISIONING_WK_ENV_PATH? | default ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning resources path
|
||||||
|
export def get-provisioning-resources [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.resources" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning settings source path
|
||||||
|
export def get-provisioning-settings-src-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
$env.PROVISIONING_SETTINGS_SRC_PATH? | default ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning infra path
|
||||||
|
export def get-provisioning-infra-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
$env.PROVISIONING_KLOUD_PATH? | default (config-get "paths.infra" "" --config $config)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get clusters path
|
||||||
|
export def get-clusters-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.clusters" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get templates path
|
||||||
|
export def get-templates-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.templates" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get tools path
|
||||||
|
export def get-tools-path [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.tools" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get file viewer
|
||||||
|
export def get-file-viewer [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "output.file_viewer" "bat" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get notify icon path
|
||||||
|
export def get-notify-icon [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.files.notify_icon" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get default settings file
|
||||||
|
export def get-default-settings [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "paths.files.settings" "settings.k" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get match date format
|
||||||
|
export def get-match-date [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
config-get "output.match_date" "%Y_%m_%d" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning module
|
||||||
|
export def get-provisioning-module [
|
||||||
|
--config: record # Optional pre-loaded config
|
||||||
|
] {
|
||||||
|
$env.PROVISIONING_MODULE? | default ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set provisioning module
|
||||||
|
export def set-provisioning-module [value: string] {
|
||||||
|
$env.PROVISIONING_MODULE = $value
|
||||||
|
}
|
||||||
|
|
||||||
|
# Additional accessor functions for complete migration
|
||||||
|
|
||||||
|
# Get provisioning log level
|
||||||
|
export def get-provisioning-log-level [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "debug.log_level" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if debug remote is enabled
|
||||||
|
export def is-debug-remote-enabled [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "debug.remote" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning URL
|
||||||
|
export def get-provisioning-url [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "core.url" "https://provisioning.systems" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning use SOPS
|
||||||
|
export def get-provisioning-use-sops [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "sops.use_sops" "age" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning use KMS
|
||||||
|
export def get-provisioning-use-kms [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "sops.use_kms" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get secret provider
|
||||||
|
export def get-secret-provider [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "sops.secret_provider" "sops" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get AI enabled
|
||||||
|
export def get-ai-enabled [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "ai.enabled" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get AI provider
|
||||||
|
export def get-ai-provider [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "ai.provider" "openai" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get last error
|
||||||
|
export def get-last-error [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
$env.PROVISIONING_LAST_ERROR? | default ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get run taskservs path
|
||||||
|
export def get-run-taskservs-path [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "paths.run_taskservs" "taskservs" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get run clusters path
|
||||||
|
export def get-run-clusters-path [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "paths.run_clusters" "clusters" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get keys path
|
||||||
|
export def get-keys-path [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "paths.files.keys" ".keys.k" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get use KCL
|
||||||
|
export def get-use-kcl [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "tools.use_kcl" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get use KCL plugin
|
||||||
|
export def get-use-kcl-plugin [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "tools.use_kcl_plugin" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get use TERA plugin
|
||||||
|
export def get-use-tera-plugin [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "tools.use_tera_plugin" false --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get extensions path
|
||||||
|
export def get-extensions-path [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "paths.extensions" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get extension mode
|
||||||
|
export def get-extension-mode [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "extensions.mode" "full" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning profile
|
||||||
|
export def get-provisioning-profile [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "extensions.profile" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get allowed extensions
|
||||||
|
export def get-allowed-extensions [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "extensions.allowed" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get blocked extensions
|
||||||
|
export def get-blocked-extensions [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "extensions.blocked" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get custom providers
|
||||||
|
export def get-custom-providers [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "paths.custom_providers" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get custom taskservs
|
||||||
|
export def get-custom-taskservs [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "paths.custom_taskservs" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get core nulib path
|
||||||
|
export def get-core-nulib-path [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
let base = (get-base-path --config $config)
|
||||||
|
$base | path join "core" "nulib"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get prov lib path
|
||||||
|
export def get-prov-lib-path [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
let providers = (get-providers-path --config $config)
|
||||||
|
$providers | path join "prov_lib"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get provisioning core path
|
||||||
|
export def get-provisioning-core [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
let base = (get-base-path --config $config)
|
||||||
|
$base | path join "core"
|
||||||
|
}
|
||||||
|
|
||||||
|
# KMS (Key Management Service) accessor functions
|
||||||
|
export def get-kms-server [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.server" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
export def get-kms-auth-method [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.auth_method" "certificate" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
export def get-kms-client-cert [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.client_cert" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
export def get-kms-client-key [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.client_key" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
export def get-kms-ca-cert [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.ca_cert" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
export def get-kms-api-token [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.api_token" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
export def get-kms-username [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.username" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
export def get-kms-password [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.password" "" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
export def get-kms-timeout [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.timeout" "30" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
export def get-kms-verify-ssl [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "kms.verify_ssl" "true" --config $config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if SSH debug mode is enabled
|
||||||
|
export def is-ssh-debug-enabled [
|
||||||
|
--config: record
|
||||||
|
] {
|
||||||
|
config-get "debug.ssh" false --config $config
|
||||||
|
}
|
263
core/nulib/lib_provisioning/config/loader.nu
Normal file
263
core/nulib/lib_provisioning/config/loader.nu
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
# Configuration Loader for Provisioning System
|
||||||
|
# Implements hierarchical configuration loading with variable interpolation
|
||||||
|
|
||||||
|
use std log
|
||||||
|
|
||||||
|
# Main configuration loader - loads and merges all config sources
|
||||||
|
export def load-provisioning-config [
|
||||||
|
--debug = false # Enable debug logging
|
||||||
|
--validate = true # Validate configuration
|
||||||
|
--environment: string # Override environment (dev/prod/test)
|
||||||
|
] {
|
||||||
|
if $debug {
|
||||||
|
# log debug "Loading provisioning configuration..."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Define configuration sources in precedence order (lowest to highest)
|
||||||
|
let config_sources = [
|
||||||
|
# 1. System defaults (lowest precedence)
|
||||||
|
{
|
||||||
|
name: "defaults"
|
||||||
|
path: "/Users/Akasha/repo-cnz/src/provisioning/config.defaults.toml"
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
# 2. User configuration
|
||||||
|
{
|
||||||
|
name: "user"
|
||||||
|
path: ($env.HOME | path join ".config" | path join "provisioning" | path join "config.toml")
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
# 3. Project configuration
|
||||||
|
{
|
||||||
|
name: "project"
|
||||||
|
path: ($env.PWD | path join "provisioning.toml")
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
# 4. Infrastructure-specific configuration (highest precedence)
|
||||||
|
{
|
||||||
|
name: "infra"
|
||||||
|
path: ($env.PWD | path join ".provisioning.toml")
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
mut final_config = {}
|
||||||
|
|
||||||
|
# Load and merge configurations
|
||||||
|
for source in $config_sources {
|
||||||
|
let config_data = (load-config-file $source.path $source.required $debug)
|
||||||
|
if ($config_data | is-not-empty) {
|
||||||
|
if $debug {
|
||||||
|
# log debug $"Loaded ($source.name) config from ($source.path)"
|
||||||
|
}
|
||||||
|
$final_config = (deep-merge $final_config $config_data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Apply environment-specific overrides if specified
|
||||||
|
if ($environment | is-not-empty) {
|
||||||
|
let env_config = ($final_config | get -o $"environments.($environment)" | default {})
|
||||||
|
if ($env_config | is-not-empty) {
|
||||||
|
if $debug {
|
||||||
|
# log debug $"Applying environment overrides for: ($environment)"
|
||||||
|
}
|
||||||
|
$final_config = (deep-merge $final_config $env_config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Interpolate variables in the final configuration
|
||||||
|
$final_config = (interpolate-config $final_config)
|
||||||
|
|
||||||
|
# Validate configuration if requested
|
||||||
|
if $validate {
|
||||||
|
validate-config $final_config
|
||||||
|
}
|
||||||
|
|
||||||
|
if $debug {
|
||||||
|
# log debug "Configuration loading completed"
|
||||||
|
}
|
||||||
|
|
||||||
|
$final_config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load a single configuration file
|
||||||
|
export def load-config-file [
|
||||||
|
file_path: string
|
||||||
|
required = false
|
||||||
|
debug = false
|
||||||
|
] {
|
||||||
|
if not ($file_path | path exists) {
|
||||||
|
if $required {
|
||||||
|
error make {
|
||||||
|
msg: $"Required configuration file not found: ($file_path)"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if $debug {
|
||||||
|
# log debug $"Optional config file not found: ($file_path)"
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if $debug {
|
||||||
|
# log debug $"Loading config file: ($file_path)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load the file - use error handling without complex try-catch
|
||||||
|
if ($file_path | path exists) {
|
||||||
|
open $file_path
|
||||||
|
} else {
|
||||||
|
if $required {
|
||||||
|
error make {
|
||||||
|
msg: $"Configuration file not found: ($file_path)"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deep merge two configuration records (right takes precedence)
|
||||||
|
export def deep-merge [
|
||||||
|
base: record
|
||||||
|
override: record
|
||||||
|
] {
|
||||||
|
mut result = $base
|
||||||
|
|
||||||
|
for key in ($override | columns) {
|
||||||
|
let override_value = ($override | get $key)
|
||||||
|
let base_value = ($base | get -o $key)
|
||||||
|
|
||||||
|
if ($base_value | is-empty) {
|
||||||
|
# Key doesn't exist in base, add it
|
||||||
|
$result = ($result | insert $key $override_value)
|
||||||
|
} else if (($base_value | describe) == "record") and (($override_value | describe) == "record") {
|
||||||
|
# Both are records, merge recursively
|
||||||
|
$result = ($result | upsert $key (deep-merge $base_value $override_value))
|
||||||
|
} else {
|
||||||
|
# Override the value
|
||||||
|
$result = ($result | upsert $key $override_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result
|
||||||
|
}
|
||||||
|
|
||||||
|
# Interpolate variables in configuration values
|
||||||
|
export def interpolate-config [
|
||||||
|
config: record
|
||||||
|
] {
|
||||||
|
mut result = $config
|
||||||
|
|
||||||
|
# First pass: resolve simple base values
|
||||||
|
if ($config | get -o paths.base | is-not-empty) {
|
||||||
|
let base_path = ($config | get paths.base)
|
||||||
|
$result = ($result | update paths (
|
||||||
|
$result | get paths |
|
||||||
|
transpose key value |
|
||||||
|
each {|item|
|
||||||
|
if ($item.value | describe) == "string" and ($item.value | str contains "${paths.base}") {
|
||||||
|
{key: $item.key, value: ($item.value | str replace --all "${paths.base}" $base_path)}
|
||||||
|
} else {
|
||||||
|
$item
|
||||||
|
}
|
||||||
|
} |
|
||||||
|
transpose -r |
|
||||||
|
into record
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
$result
|
||||||
|
}
|
||||||
|
|
||||||
|
# Interpolate variables in a string using ${path.to.value} syntax
|
||||||
|
export def interpolate-string [
|
||||||
|
text: string
|
||||||
|
config: record
|
||||||
|
] {
|
||||||
|
mut result = $text
|
||||||
|
|
||||||
|
# Simple interpolation for ${paths.base} pattern
|
||||||
|
if ($result | str contains "${paths.base}") {
|
||||||
|
let base_path = (get-config-value $config "paths.base" "")
|
||||||
|
$result = ($result | str replace --all "${paths.base}" $base_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add more interpolation patterns as needed
|
||||||
|
# This is a basic implementation - a full template engine would be more robust
|
||||||
|
$result
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get a nested configuration value using dot notation
|
||||||
|
export def get-config-value [
|
||||||
|
config: record
|
||||||
|
path: string
|
||||||
|
default_value: any = null
|
||||||
|
] {
|
||||||
|
let path_parts = ($path | split row ".")
|
||||||
|
mut current = $config
|
||||||
|
|
||||||
|
for part in $path_parts {
|
||||||
|
let next_value = ($current | get -o $part)
|
||||||
|
if ($next_value | is-empty) {
|
||||||
|
return $default_value
|
||||||
|
}
|
||||||
|
$current = $next_value
|
||||||
|
}
|
||||||
|
|
||||||
|
$current
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate the final configuration
|
||||||
|
export def validate-config [
|
||||||
|
config: record
|
||||||
|
] {
|
||||||
|
# Check required top-level sections
|
||||||
|
let required_sections = ["core", "paths", "debug"]
|
||||||
|
|
||||||
|
for section in $required_sections {
|
||||||
|
if ($config | get -o $section | is-empty) {
|
||||||
|
error make {
|
||||||
|
msg: $"Missing required configuration section: ($section)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate core section
|
||||||
|
let core = ($config | get core)
|
||||||
|
if ($core | get -o version | is-empty) {
|
||||||
|
error make {
|
||||||
|
msg: "Missing required core.version in configuration"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate paths section
|
||||||
|
let paths = ($config | get paths)
|
||||||
|
if ($paths | get -o base | is-empty) {
|
||||||
|
error make {
|
||||||
|
msg: "Missing required paths.base in configuration"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Additional validation can be added here
|
||||||
|
}
|
||||||
|
|
||||||
|
# Helper function to create directory structure for user config
|
||||||
|
export def init-user-config [] {
|
||||||
|
let config_dir = ($env.HOME | path join ".config" | path join "provisioning")
|
||||||
|
|
||||||
|
if not ($config_dir | path exists) {
|
||||||
|
mkdir $config_dir
|
||||||
|
print $"Created user config directory: ($config_dir)"
|
||||||
|
}
|
||||||
|
|
||||||
|
let user_config_path = ($config_dir | path join "config.toml")
|
||||||
|
if not ($user_config_path | path exists) {
|
||||||
|
let example_path = ($env.FILE_PWD | path join ".." | path join ".." | path join ".." | path join ".." | path join "config.user.toml.example")
|
||||||
|
if ($example_path | path exists) {
|
||||||
|
cp $example_path $user_config_path
|
||||||
|
print $"Created user config file: ($user_config_path)"
|
||||||
|
print "Edit this file to customize your provisioning settings"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
262
core/nulib/lib_provisioning/config/migration.nu
Normal file
262
core/nulib/lib_provisioning/config/migration.nu
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
# Configuration Migration Tool
|
||||||
|
# Helps migrate from environment variable based configuration to the new config system
|
||||||
|
|
||||||
|
use std log
|
||||||
|
|
||||||
|
# Mapping of old environment variables to new config paths
|
||||||
|
export def get-env-mapping [] {
|
||||||
|
[
|
||||||
|
{ env_var: "PROVISIONING", config_path: "paths.base", description: "Base provisioning path" }
|
||||||
|
{ env_var: "PROVISIONING_KLOUD_PATH", config_path: "paths.kloud", description: "Infrastructure kloud path" }
|
||||||
|
{ env_var: "PROVISIONING_PROVIDERS_PATH", config_path: "paths.providers", description: "Providers path" }
|
||||||
|
{ env_var: "PROVISIONING_TASKSERVS_PATH", config_path: "paths.taskservs", description: "Task services path" }
|
||||||
|
{ env_var: "PROVISIONING_CLUSTERS_PATH", config_path: "paths.clusters", description: "Clusters path" }
|
||||||
|
{ env_var: "PROVISIONING_RESOURCES", config_path: "paths.resources", description: "Resources path" }
|
||||||
|
{ env_var: "PROVISIONING_TEMPLATES_PATH", config_path: "paths.templates", description: "Templates path" }
|
||||||
|
{ env_var: "PROVISIONING_TOOLS_PATH", config_path: "paths.tools", description: "Tools path" }
|
||||||
|
{ env_var: "PROVISIONING_CORE", config_path: "paths.core", description: "Core path" }
|
||||||
|
|
||||||
|
{ env_var: "PROVISIONING_DEBUG", config_path: "debug.enabled", description: "Debug mode" }
|
||||||
|
{ env_var: "PROVISIONING_METADATA", config_path: "debug.metadata", description: "Metadata debug" }
|
||||||
|
{ env_var: "PROVISIONING_DEBUG_CHECK", config_path: "debug.check", description: "Debug check mode" }
|
||||||
|
{ env_var: "PROVISIONING_DEBUG_REMOTE", config_path: "debug.remote", description: "Remote debug mode" }
|
||||||
|
{ env_var: "PROVISIONING_LOG_LEVEL", config_path: "debug.log_level", description: "Log level" }
|
||||||
|
{ env_var: "PROVISIONING_NO_TERMINAL", config_path: "debug.no_terminal", description: "No terminal mode" }
|
||||||
|
|
||||||
|
{ env_var: "PROVISIONING_FILEVIEWER", config_path: "output.file_viewer", description: "File viewer command" }
|
||||||
|
{ env_var: "PROVISIONING_WK_FORMAT", config_path: "output.format", description: "Working format" }
|
||||||
|
|
||||||
|
{ env_var: "PROVISIONING_USE_SOPS", config_path: "sops.use_sops", description: "SOPS encryption type" }
|
||||||
|
{ env_var: "PROVISIONING_KAGE", config_path: "sops.key_search_paths.0", description: "Primary SOPS key path" }
|
||||||
|
{ env_var: "PROVISIONING_SOPS", config_path: "sops.config_path", description: "SOPS config path" }
|
||||||
|
|
||||||
|
{ env_var: "PROVISIONING_DFLT_SET", config_path: "paths.files.settings", description: "Default settings file" }
|
||||||
|
{ env_var: "PROVISIONING_KEYS_PATH", config_path: "paths.files.keys", description: "Keys file path" }
|
||||||
|
{ env_var: "PROVISIONING_REQ_VERSIONS", config_path: "paths.files.requirements", description: "Requirements file" }
|
||||||
|
{ env_var: "PROVISIONING_NOTIFY_ICON", config_path: "paths.files.notify_icon", description: "Notification icon" }
|
||||||
|
|
||||||
|
{ env_var: "PROVISIONING_RUN_TASKSERVS_PATH", config_path: "taskservs.run_path", description: "Task services run path" }
|
||||||
|
{ env_var: "PROVISIONING_RUN_CLUSTERS_PATH", config_path: "clusters.run_path", description: "Clusters run path" }
|
||||||
|
{ env_var: "PROVISIONING_GENERATE_DIRPATH", config_path: "generation.dir_path", description: "Generation directory" }
|
||||||
|
{ env_var: "PROVISIONING_GENERATE_DEFSFILE", config_path: "generation.defs_file", description: "Generation definitions file" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Analyze current environment variables and suggest migration
|
||||||
|
export def analyze-current-env [] {
|
||||||
|
let mapping = (get-env-mapping)
|
||||||
|
mut analysis = []
|
||||||
|
|
||||||
|
for entry in $mapping {
|
||||||
|
let env_value = ($env | get -o $entry.env_var)
|
||||||
|
if ($env_value | is-not-empty) {
|
||||||
|
$analysis = ($analysis | append {
|
||||||
|
env_var: $entry.env_var
|
||||||
|
current_value: $env_value
|
||||||
|
config_path: $entry.config_path
|
||||||
|
description: $entry.description
|
||||||
|
action: "migrate"
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
$analysis = ($analysis | append {
|
||||||
|
env_var: $entry.env_var
|
||||||
|
current_value: "not set"
|
||||||
|
config_path: $entry.config_path
|
||||||
|
description: $entry.description
|
||||||
|
action: "default"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$analysis
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate user configuration based on current environment variables
|
||||||
|
export def generate-user-config [
|
||||||
|
--output: string = "" # Output file (default: ~/.config/provisioning/config.toml)
|
||||||
|
--dry-run = false # Show what would be generated without writing
|
||||||
|
] {
|
||||||
|
let analysis = (analyze-current-env)
|
||||||
|
let active_vars = ($analysis | where action == "migrate")
|
||||||
|
|
||||||
|
if ($active_vars | is-empty) {
|
||||||
|
print "No environment variables found to migrate"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build configuration structure
|
||||||
|
mut config = {
|
||||||
|
core: {
|
||||||
|
name: "provisioning"
|
||||||
|
}
|
||||||
|
paths: {}
|
||||||
|
debug: {}
|
||||||
|
output: {}
|
||||||
|
sops: {
|
||||||
|
key_search_paths: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert environment variables to config structure
|
||||||
|
for var in $active_vars {
|
||||||
|
$config = (set-config-value $config $var.config_path $var.current_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert to TOML
|
||||||
|
let config_toml = ($config | to toml)
|
||||||
|
|
||||||
|
let output_path = if ($output | is-empty) {
|
||||||
|
($env.HOME | path join ".config" | path join "provisioning" | path join "config.toml")
|
||||||
|
} else {
|
||||||
|
$output
|
||||||
|
}
|
||||||
|
|
||||||
|
if $dry_run {
|
||||||
|
print "Generated configuration (dry run):"
|
||||||
|
print "=====================================\n"
|
||||||
|
print $config_toml
|
||||||
|
print $"\nWould be written to: ($output_path)"
|
||||||
|
} else {
|
||||||
|
# Ensure directory exists
|
||||||
|
let config_dir = ($output_path | path dirname)
|
||||||
|
if not ($config_dir | path exists) {
|
||||||
|
mkdir $config_dir
|
||||||
|
print $"Created directory: ($config_dir)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Write configuration
|
||||||
|
$config_toml | save $output_path
|
||||||
|
print $"Generated user configuration: ($output_path)"
|
||||||
|
print "Review and edit this file as needed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set a nested configuration value using dot notation
|
||||||
|
def set-config-value [
|
||||||
|
config: record
|
||||||
|
path: string
|
||||||
|
value: any
|
||||||
|
] {
|
||||||
|
let path_parts = ($path | split row ".")
|
||||||
|
|
||||||
|
if ($path_parts | length) == 1 {
|
||||||
|
# Simple top-level assignment
|
||||||
|
return ($config | upsert ($path_parts | first) $value)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Handle nested paths
|
||||||
|
let first_part = ($path_parts | first)
|
||||||
|
let remaining_path = ($path_parts | skip 1 | str join ".")
|
||||||
|
|
||||||
|
let existing_section = ($config | get -o $first_part | default {})
|
||||||
|
let updated_section = (set-config-value $existing_section $remaining_path $value)
|
||||||
|
|
||||||
|
$config | upsert $first_part $updated_section
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for potential issues in the migration
|
||||||
|
export def check-migration-issues [] {
|
||||||
|
let analysis = (analyze-current-env)
|
||||||
|
mut issues = []
|
||||||
|
|
||||||
|
# Check for conflicting paths
|
||||||
|
let base_path = ($env | get -o PROVISIONING)
|
||||||
|
if ($base_path | is-not-empty) and not ($base_path | path exists) {
|
||||||
|
$issues = ($issues | append {
|
||||||
|
type: "missing_path"
|
||||||
|
item: "PROVISIONING"
|
||||||
|
value: $base_path
|
||||||
|
issue: "Base path does not exist"
|
||||||
|
severity: "error"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for SOPS configuration
|
||||||
|
let sops_key = ($env | get -o PROVISIONING_KAGE)
|
||||||
|
if ($sops_key | is-not-empty) and not ($sops_key | path exists) {
|
||||||
|
$issues = ($issues | append {
|
||||||
|
type: "missing_file"
|
||||||
|
item: "PROVISIONING_KAGE"
|
||||||
|
value: $sops_key
|
||||||
|
issue: "SOPS key file does not exist"
|
||||||
|
severity: "warning"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for deprecated variables that should be removed
|
||||||
|
let deprecated_vars = [
|
||||||
|
"PROVISIONING_ARGS"
|
||||||
|
"PROVISIONING_MODULE"
|
||||||
|
"PROVISIONING_NAME"
|
||||||
|
"PROVISIONING_OUT"
|
||||||
|
"PROVISIONING_LAST_ERROR"
|
||||||
|
]
|
||||||
|
|
||||||
|
for var in $deprecated_vars {
|
||||||
|
let value = ($env | get -o $var)
|
||||||
|
if ($value | is-not-empty) {
|
||||||
|
$issues = ($issues | append {
|
||||||
|
type: "deprecated"
|
||||||
|
item: $var
|
||||||
|
value: $value
|
||||||
|
issue: "This variable is deprecated and should be removed"
|
||||||
|
severity: "info"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$issues
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show migration status and recommendations
|
||||||
|
export def show-migration-status [] {
|
||||||
|
print "🔄 Environment Variable Migration Analysis"
|
||||||
|
print "==========================================\n"
|
||||||
|
|
||||||
|
let analysis = (analyze-current-env)
|
||||||
|
let to_migrate = ($analysis | where action == "migrate")
|
||||||
|
let using_defaults = ($analysis | where action == "default")
|
||||||
|
|
||||||
|
print $"📊 Summary:"
|
||||||
|
print $" • Variables to migrate: ($to_migrate | length)"
|
||||||
|
print $" • Using system defaults: ($using_defaults | length)"
|
||||||
|
print ""
|
||||||
|
|
||||||
|
if ($to_migrate | length) > 0 {
|
||||||
|
print "🔧 Variables that will be migrated:"
|
||||||
|
$to_migrate | select env_var current_value config_path | table --index false
|
||||||
|
print ""
|
||||||
|
}
|
||||||
|
|
||||||
|
let issues = (check-migration-issues)
|
||||||
|
if ($issues | length) > 0 {
|
||||||
|
print "⚠️ Potential issues found:"
|
||||||
|
$issues | table --index false
|
||||||
|
print ""
|
||||||
|
}
|
||||||
|
|
||||||
|
print "💡 Next steps:"
|
||||||
|
print " 1. Run 'migration generate-user-config --dry-run' to preview"
|
||||||
|
print " 2. Run 'migration generate-user-config' to create config file"
|
||||||
|
print " 3. Test the new configuration system"
|
||||||
|
print " 4. Remove old environment variables from your shell profile"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a backup of current environment variables
|
||||||
|
export def backup-current-env [
|
||||||
|
output: string = "provisioning-env-backup.nu"
|
||||||
|
] {
|
||||||
|
let mapping = (get-env-mapping)
|
||||||
|
mut backup_content = "# Backup of provisioning environment variables\n"
|
||||||
|
$backup_content = ($backup_content + "# Generated on " + (date now | format date "%Y-%m-%d %H:%M:%S") + "\n\n")
|
||||||
|
|
||||||
|
for entry in $mapping {
|
||||||
|
let env_value = ($env | get -o $entry.env_var)
|
||||||
|
if ($env_value | is-not-empty) {
|
||||||
|
$backup_content = ($backup_content + $"$env.($entry.env_var) = \"($env_value)\"\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$backup_content | save $output
|
||||||
|
print $"Environment variables backed up to: ($output)"
|
||||||
|
}
|
52
core/nulib/lib_provisioning/config/mod.nu
Normal file
52
core/nulib/lib_provisioning/config/mod.nu
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Configuration System Module Index
|
||||||
|
# Central import point for the new configuration system
|
||||||
|
|
||||||
|
# Core configuration functionality
|
||||||
|
export use loader.nu *
|
||||||
|
export use accessor.nu *
|
||||||
|
export use migration.nu *
|
||||||
|
|
||||||
|
# Convenience function to get the complete configuration
|
||||||
|
export def config [] {
|
||||||
|
get-config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Quick access to common configuration sections
|
||||||
|
export def paths [] {
|
||||||
|
get-paths
|
||||||
|
}
|
||||||
|
|
||||||
|
export def debug [] {
|
||||||
|
get-debug
|
||||||
|
}
|
||||||
|
|
||||||
|
export def sops [] {
|
||||||
|
get-sops
|
||||||
|
}
|
||||||
|
|
||||||
|
export def validation [] {
|
||||||
|
get-validation
|
||||||
|
}
|
||||||
|
|
||||||
|
# Migration helpers
|
||||||
|
export def migrate [] {
|
||||||
|
use migration.nu show-migration-status
|
||||||
|
show-migration-status
|
||||||
|
}
|
||||||
|
|
||||||
|
export def migrate-now [
|
||||||
|
--dry-run = false
|
||||||
|
] {
|
||||||
|
use migration.nu generate-user-config
|
||||||
|
generate-user-config --dry-run $dry_run
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configuration validation
|
||||||
|
export def validate [] {
|
||||||
|
validate-current-config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Initialize user configuration
|
||||||
|
export def init [] {
|
||||||
|
init-user-config
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user