262 lines
10 KiB
Plaintext
262 lines
10 KiB
Plaintext
![]() |
# 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)"
|
||
|
}
|