#!/usr/bin/env nu # Provider Management CLI # Manages cloud providers for infrastructures with KCL integration # Author: JesusPerezLorenzo # Date: 2025-09-29 use ../nulib/lib_provisioning/kcl_module_loader.nu * # Main providers command def main [] { print_help } # List all available providers export def "main list" [ --kcl # Show KCL module information (always enabled) --format: string = "table" # Output format: table, json, yaml ] { # Always use KCL module loader let providers = (discover-kcl-modules "providers") match $format { "json" => ($providers | to json) "yaml" => ($providers | to yaml) _ => ($providers | table) } } # Show detailed information about a provider export def "main info" [ provider: string # Provider name --kcl # Show KCL schema information ] { print $"📋 Provider Information: ($provider)" print "" let providers = (discover-kcl-modules "providers") let provider_info = ($providers | where name == $provider) if ($provider_info | is-empty) { print $"❌ Provider not found: ($provider)" return } let info = ($provider_info | first) print $" Name: ($info.name)" print $" Type: ($info.type)" print $" Path: ($info.path)" print $" Has KCL: ($info.has_kcl)" if $kcl and $info.has_kcl { print "" print " KCL Module:" print $" Module Name: ($info.kcl_module_name)" print $" KCL Path: ($info.kcl_path)" print $" Version: ($info.version)" print $" Edition: ($info.edition)" # Check for kcl.mod file let kcl_mod = ($info.kcl_path | path join "kcl.mod") if ($kcl_mod | path exists) { print "" print $" kcl.mod content:" open $kcl_mod | lines | each {|line| print $" ($line)"} } } } # Install a provider for an infrastructure export def "main install" [ provider: string, # Provider name (e.g., upcloud, aws, local) infra: string, # Infrastructure name or path --version: string = "0.0.1", # Provider version --manifest: string = "providers.manifest.yaml" # Manifest file name ] { # Resolve infrastructure path let infra_path = resolve-infra-path $infra if ($infra_path | is-empty) { print $"❌ Infrastructure not found: ($infra)" return } # Use library function to install provider install-provider $provider $infra_path --version $version print "" print $"💡 Next steps:" print $" 1. Check the manifest: ($infra_path)/($manifest)" print $" 2. Update server definitions to use ($provider)" print $" 3. Run: kcl run defs/servers.k" } # Remove a provider from an infrastructure export def "main remove" [ provider: string, # Provider name infra: string, # Infrastructure name or path --force # Force removal without confirmation ] { # Resolve infrastructure path let infra_path = resolve-infra-path $infra if ($infra_path | is-empty) { print $"❌ Infrastructure not found: ($infra)" return } # Confirmation unless forced if not $force { print $"⚠️ This will remove provider ($provider) from ($infra)" print " KCL dependencies will be updated." let response = (input "Continue? (y/N): ") if ($response | str downcase) != "y" { print "❌ Cancelled" return } } # Use library function to remove provider remove-provider $provider $infra_path } # List installed providers for an infrastructure export def "main installed" [ infra: string, # Infrastructure name or path --format: string = "table" # Output format ] { # Resolve infrastructure path let infra_path = resolve-infra-path $infra if ($infra_path | is-empty) { print $"❌ Infrastructure not found: ($infra)" return } let manifest_path = ($infra_path | path join "providers.manifest.yaml") if not ($manifest_path | path exists) { print $"❌ No providers.manifest.yaml found in ($infra)" return } let manifest = (open $manifest_path) let providers = if ($manifest | get providers? | is-not-empty) { $manifest | get providers } else if ($manifest | get loaded_providers? | is-not-empty) { $manifest | get loaded_providers } else { [] } print $"📦 Installed providers for ($infra):" print "" match $format { "json" => ($providers | to json) "yaml" => ($providers | to yaml) _ => ($providers | table) } } # Validate provider installation for an infrastructure export def "main validate" [ infra: string # Infrastructure name or path ] { print $"🔍 Validating providers for ($infra)..." print "" # Resolve infrastructure path let infra_path = resolve-infra-path $infra if ($infra_path | is-empty) { print $"❌ Infrastructure not found: ($infra)" return } mut validation_errors = [] # Check manifest exists let manifest_path = ($infra_path | path join "providers.manifest.yaml") if not ($manifest_path | path exists) { $validation_errors = ($validation_errors | append "providers.manifest.yaml not found") } else { # Check each provider in manifest let manifest = (open $manifest_path) let providers = ($manifest | get providers) for provider in $providers { print $" Checking ($provider.name)..." # Check if provider exists let available = (discover-kcl-modules "providers" | where name == $provider.name) if ($available | is-empty) { $validation_errors = ($validation_errors | append $"Provider not found: ($provider.name)") print $" ❌ Not found in extensions" } else { let provider_info = ($available | first) # Check if symlink exists let modules_dir = ($infra_path | path join ".kcl-modules") let link_path = ($modules_dir | path join $provider_info.kcl_module_name) if not ($link_path | path exists) { $validation_errors = ($validation_errors | append $"Symlink missing: ($link_path)") print $" ❌ Symlink not found" } else { print $" ✓ OK" } } } } # Check kcl.mod let kcl_mod_path = ($infra_path | path join "kcl.mod") if not ($kcl_mod_path | path exists) { $validation_errors = ($validation_errors | append "kcl.mod not found") } print "" # Report results if ($validation_errors | is-empty) { print "✅ Validation passed - all providers correctly installed" return true } else { print "❌ Validation failed:" for error in $validation_errors { print $" • ($error)" } return false } } # Helper: Resolve infrastructure path def resolve-infra-path [infra: string]: nothing -> string { if ($infra | path exists) { return $infra } # Try workspace/infra path let workspace_path = $"workspace/infra/($infra)" if ($workspace_path | path exists) { return $workspace_path } # Try absolute workspace path let abs_workspace_path = $"/Users/Akasha/project-provisioning/workspace/infra/($infra)" if ($abs_workspace_path | path exists) { return $abs_workspace_path } return "" } # Helper: Print help def print_help [] { print "Provider Management CLI" print "" print "Usage: providers [options]" print "" print "COMMANDS:" print " list [--kcl] [--format ] - List all available providers" print " info [--kcl] - Show detailed provider information" print " install [--version ] - Install provider for infrastructure" print " remove [--force] - Remove provider from infrastructure" print " installed [--format ] - List installed providers" print " validate - Validate provider installation" print "" print "OPTIONS:" print " --kcl Show KCL module information" print " --format Output format: table, json, yaml" print " --force Skip confirmation prompts" print " --version Specify provider version (default: 0.0.1)" print "" print "EXAMPLES:" print " providers list --kcl" print " providers info upcloud --kcl" print " providers install upcloud wuji" print " providers installed wuji" print " providers validate wuji" print " providers remove aws wuji --force" print "" print "See also: module-loader sync-kcl" }