# Workspace Configuration Management Commands # Provides commands to view, edit, validate, and manage workspace configurations use platform/user/config.nu [list-workspaces get-active-workspace get-workspace-path get-user-config-dir] use tools/nickel/process.nu [ncl-eval-soft] # Get active workspace context or load by name def get-workspace-context [ workspace_name?: string ] { if ($workspace_name | is-empty) { let active = (get-active-workspace) if ($active | is-empty) { print "❌ No active workspace found. Use 'provisioning workspace activate '" exit 1 } let path = (get-workspace-path $active) { name: $active path: $path } } else { let contexts = (list-workspaces) # First try to match by name let found = ($contexts | where name == $workspace_name | first) if ($found | is-empty) { let input_as_path = if ($workspace_name | path exists) { $workspace_name | path expand } else { let rel_path = ($env.PWD | path join $workspace_name) if ($rel_path | path exists) { $rel_path | path expand } else { $workspace_name | path expand } } let path_exists = ($input_as_path | path exists) if $path_exists { let found_by_path = ($contexts | where (path | path expand) == $input_as_path | first) if ($found_by_path | is-not-empty) { return $found_by_path } let config_file_nickel = ($input_as_path | path join "config" | path join "provisioning.ncl") let config_file_yaml = ($input_as_path | path join "config" | path join "provisioning.yaml") if (($config_file_nickel | path exists) or ($config_file_yaml | path exists)) { return { name: ($input_as_path | path basename) path: $input_as_path } } } let found_by_exact_path = ($contexts | where path == $workspace_name | first) if ($found_by_exact_path | is-not-empty) { return $found_by_exact_path } print $"❌ Workspace '($workspace_name)' not found" exit 1 } $found } } # Show complete workspace configuration export def "workspace-config-show" [ workspace_name?: string --format: string = "yaml" # yaml, json, toml, nickel ] { let workspace = (get-workspace-context $workspace_name) let config_dir = ($workspace.path | path join "config") let decl_file = ($config_dir | path join "provisioning.ncl") let yaml_file = ($config_dir | path join "provisioning.yaml") let config_file = if ($decl_file | path exists) { let ncl_ok = (ncl-eval-soft $decl_file [] null | is-not-empty) if $ncl_ok { $decl_file } else if ($yaml_file | path exists) { $yaml_file } else { $decl_file } } else if ($yaml_file | path exists) { $yaml_file } else { null } if ($config_file | is-empty) { print "❌ No workspace configuration found (neither .ncl nor .yaml)" exit 1 } let config = if ($config_file | str ends-with ".ncl") { let file_dir = ($config_file | path dirname) let file_name = ($config_file | path basename) let decl_mod_exists = (($file_dir | path join "nickel.mod") | path exists) let parsed = if $decl_mod_exists { let res = (do { ^sh -c $"cd '($file_dir)' && nickel export ($file_name) --format json" } | complete) if ($res.stdout | is-not-empty) { $res.stdout | from json } else { null } } else { ncl-eval-soft $config_file [] null } if ($parsed | is-empty) { print "❌ Failed to load Nickel config: empty output" exit 1 } if (($parsed | columns) | any { |col| $col == "workspace_config" }) { $parsed.workspace_config } else { $parsed } } else { open $config_file } let config_type = if ($config_file | str ends-with ".ncl") { "Nickel" } else { "YAML" } match $format { "yaml" => { print $"Configuration ($config_type): ($config_file)" print "" ($config | to yaml) } "json" => { print $"Configuration ($config_type): ($config_file)" print "" ($config | to json) } "toml" => { print $"Configuration ($config_type): ($config_file)" print "" ($config | to toml) } "nickel" => { if ($config_file | str ends-with ".ncl") { open $config_file } else { print "ℹ️ Configuration is stored in YAML format, not Nickel" print " Use --format=yaml to view the config" ($config | to json) } } _ => ($config | to yaml) } } # Validate workspace configuration export def "workspace-config-validate" [ workspace_name?: string ] { let workspace = (get-workspace-context $workspace_name) print $"🔍 Validating workspace: ($workspace.name)" print "" mut all_valid = true let config_dir = ($workspace.path | path join "config") let decl_file = ($config_dir | path join "provisioning.ncl") let yaml_file = ($config_dir | path join "provisioning.yaml") let config_file = if ($decl_file | path exists) { let ncl_ok = (ncl-eval-soft $decl_file [] null | is-not-empty) if $ncl_ok { $decl_file } else if ($yaml_file | path exists) { $yaml_file } else { $decl_file } } else if ($yaml_file | path exists) { $yaml_file } else { null } if ($config_file | is-empty) { print "✓ Main config: (not found)" print " ❌ No Nickel (.ncl) or YAML (.yaml) config file found" $all_valid = false } else { let config_type = if ($config_file | str ends-with ".ncl") { "Nickel" } else { "YAML" } print $"✓ Main config: ($config_file) [($config_type)]" let config = if ($config_file | str ends-with ".ncl") { let file_dir = ($config_file | path dirname) let file_name = ($config_file | path basename) let decl_mod_exists = (($file_dir | path join "nickel.mod") | path exists) let parsed = if $decl_mod_exists { let res = (do { ^sh -c $"cd '($file_dir)' && nickel export ($file_name) --format json" } | complete) if ($res.stdout | is-not-empty) { $res.stdout | from json } else { null } } else { ncl-eval-soft $config_file [] null } if ($parsed | is-empty) { print $" ❌ Nickel compilation failed, but YAML fallback not available" $all_valid = false {} } else { if (($parsed | columns) | any { |col| $col == "workspace_config" }) { $parsed.workspace_config } else { $parsed } } } else { open $config_file } if ($config | is-not-empty) { if ($config_file | str ends-with ".ncl") { print " ✅ Valid Nickel (schema validated)" } else { print " ✅ Valid YAML" } if ($config | get workspace? | default null | is-empty) { print $" ⚠️ Missing 'workspace' section" } if ($config | get paths? | default null | is-empty) { print $" ⚠️ Missing 'paths' section" } } } print "" print "Providers:" let providers_dir = ($workspace.path | path join "config" | path join "providers") if ($providers_dir | path exists) { let provider_files = (glob $"($providers_dir)/*.toml") if ($provider_files | is-empty) { print " ⚠️ No provider configs found" } else { for file in $provider_files { let provider_name = ($file | path basename | str replace ".toml" "") print $" ✓ ($provider_name): ($file)" let _ = (open $file) print $" ✅ Valid TOML" } } } else { print " ⚠️ No providers directory" } print "" print "Platform Services:" let platform_dir = ($workspace.path | path join "config" | path join "platform") if ($platform_dir | path exists) { let platform_files = (glob $"($platform_dir)/*.toml") if ($platform_files | is-empty) { print " ⚠️ No platform service configs found" } else { for file in $platform_files { let service_name = ($file | path basename | str replace ".toml" "") print $" ✓ ($service_name): ($file)" let _ = (open $file) print $" ✅ Valid TOML" } } } else { print " ⚠️ No platform services directory" } print "" print "KMS Configuration:" let kms_file = ($workspace.path | path join "config" | path join "kms.toml") if ($kms_file | path exists) { print $" ✓ KMS config: ($kms_file)" let _ = (open $kms_file) print $" ✅ Valid TOML" } else { print " ⚠️ KMS not configured" } print "" if $all_valid { print "✅ Validation complete - all configs are valid" } else { print "❌ Validation failed - some configs have errors" } $all_valid } # Generate provider config for workspace export def "workspace-config-generate-provider" [ provider_name: string workspace_name?: string ] { let workspace = (get-workspace-context $workspace_name) let provisioning_path = $env.PROVISIONING_PATH? if ($provisioning_path | is-empty) { print "❌ PROVISIONING_PATH environment variable not set" exit 1 } let template_dir = ($provisioning_path | path join "catalog" | path join "providers" | path join $provider_name) let template_file = ($template_dir | path join "config.defaults.toml") if not ($template_file | path exists) { print "❌ Provider template not found: ($provider_name)" exit 1 } let output_dir = ($workspace.path | path join "config" | path join "providers") mkdir $output_dir let output_file = ($output_dir | path join $"($provider_name).toml") let template = (open $template_file) let content = ( $template | str replace --all "{{workspace.path}}" $workspace.path | str replace --all "{{workspace.name}}" $workspace.name ) $content | save $output_file print $"✅ Provider config generated: ($output_file)" print $"💡 Edit the file to customize settings" } # Edit configuration file export def "workspace-config-edit" [ config_type: string # provider, platform, kms, main name?: string # provider/platform name (not needed for kms/main) workspace_name?: string ] { let workspace = (get-workspace-context $workspace_name) let config_file = match $config_type { "main" => ($workspace.path | path join "config" | path join "provisioning.yaml") "provider" => { if ($name | is-empty) { print "❌ Provider name required" exit 1 } ($workspace.path | path join "config" | path join "providers" | path join $"($name).toml") } "platform" => { if ($name | is-empty) { print "❌ Platform service name required" exit 1 } ($workspace.path | path join "config" | path join "platform" | path join $"($name).toml") } "kms" => ($workspace.path | path join "config" | path join "kms.toml") _ => { print "❌ Unknown config type: ($config_type)" exit 1 } } if not ($config_file | path exists) { print "❌ Config file not found: ($config_file)" exit 1 } let editor = ($env.EDITOR? | default "vi") ^$editor $config_file } # Show configuration hierarchy export def "workspace-config-hierarchy" [ workspace_name?: string ] { let workspace = (get-workspace-context $workspace_name) print $"📊 Configuration Hierarchy for: ($workspace.name)" print "==================================================" print "" print "Priority (highest to lowest):" print "" print "5. Environment Variables (highest)" print " PROVISIONING_*" print "" print "4. User Context" let user_config = ((get-user-config-dir) | path join $"ws_($workspace.name).yaml") print $" ($user_config)" if ($user_config | path exists) { print " ✅ Exists" } else { print " ⚠️ Not found" } print "" print "3. Platform Services" let platform_dir = ($workspace.path | path join "config" | path join "platform") print $" ($platform_dir)/" if ($platform_dir | path exists) { let files = (ls $"($platform_dir)/*.toml" | get name) if ($files | is-empty) { print " ⚠️ No platform configs" } else { for file in $files { print $" • ($file | path basename)" } } } else { print " ⚠️ No platform configs" } print "" print "2. Provider Configs" let providers_dir = ($workspace.path | path join "config" | path join "providers") print $" ($providers_dir)/" if ($providers_dir | path exists) { let files = (ls $"($providers_dir)/*.toml" | get name) if ($files | is-empty) { print " ⚠️ No provider configs" } else { for file in $files { print $" • ($file | path basename)" } } } else { print " ⚠️ No provider configs" } print "" print "1. Workspace Config (lowest)" let main_config = ($workspace.path | path join "config" | path join "provisioning.yaml") print $" ($main_config)" if ($main_config | path exists) { print " ✅ Exists" } else { print " ❌ Not found" } } # List all configuration files for workspace export def "workspace-config-list" [ workspace_name?: string --type: string = "all" # all, provider, platform, kms, main ] { let workspace = (get-workspace-context $workspace_name) print $"📋 Configuration Files for: ($workspace.name)" print "==================================================" print "" mut configs = [] if ($type == "all" or $type == "main") { let main_config = ($workspace.path | path join "config" | path join "provisioning.yaml") if ($main_config | path exists) { $configs = ($configs | append { type: "main" name: "provisioning.yaml" path: $main_config exists: true }) } } if ($type == "all" or $type == "provider") { let providers_dir = ($workspace.path | path join "config" | path join "providers") if ($providers_dir | path exists) { let provider_files = (ls $"($providers_dir)/*.toml" | get name) for file in $provider_files { $configs = ($configs | append { type: "provider" name: ($file | path basename | str replace ".toml" "") path: $file exists: true }) } } } if ($type == "all" or $type == "platform") { let platform_dir = ($workspace.path | path join "config" | path join "platform") if ($platform_dir | path exists) { let platform_files = (ls $"($platform_dir)/*.toml" | get name) for file in $platform_files { $configs = ($configs | append { type: "platform" name: ($file | path basename | str replace ".toml" "") path: $file exists: true }) } } } if ($type == "all" or $type == "kms") { let kms_file = ($workspace.path | path join "config" | path join "kms.toml") if ($kms_file | path exists) { $configs = ($configs | append { type: "kms" name: "kms" path: $kms_file exists: true }) } } $configs | table }