# 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)" }