143 lines
4.2 KiB
Plaintext
143 lines
4.2 KiB
Plaintext
|
|
#!/usr/bin/env nu
|
||
|
|
|
||
|
|
# Provider Discovery System
|
||
|
|
# Discovers available cloud providers with metadata extraction
|
||
|
|
|
||
|
|
use ../lib_provisioning/config/accessor.nu config-get
|
||
|
|
|
||
|
|
# Discover all available providers
|
||
|
|
export def discover-providers []: nothing -> list<record> {
|
||
|
|
# Get absolute path to extensions directory from config
|
||
|
|
let providers_path = (config-get "paths.providers" | path expand)
|
||
|
|
|
||
|
|
if not ($providers_path | path exists) {
|
||
|
|
error make { msg: $"Providers path not found: ($providers_path)" }
|
||
|
|
}
|
||
|
|
|
||
|
|
# Find all provider directories with KCL modules
|
||
|
|
ls $providers_path
|
||
|
|
| where type == "dir"
|
||
|
|
| each { |dir|
|
||
|
|
let provider_name = ($dir.name | path basename)
|
||
|
|
let kcl_path = ($dir.name | path join "kcl")
|
||
|
|
let kcl_mod_path = ($kcl_path | path join "kcl.mod")
|
||
|
|
|
||
|
|
if ($kcl_mod_path | path exists) {
|
||
|
|
extract_provider_metadata $provider_name $kcl_path
|
||
|
|
}
|
||
|
|
}
|
||
|
|
| compact
|
||
|
|
| sort-by name
|
||
|
|
}
|
||
|
|
|
||
|
|
# Extract metadata from a provider's KCL module
|
||
|
|
def extract_provider_metadata [name: string, kcl_path: string]: nothing -> record {
|
||
|
|
let kcl_mod_path = ($kcl_path | path join "kcl.mod")
|
||
|
|
let mod_content = (open $kcl_mod_path | from toml)
|
||
|
|
|
||
|
|
# Find KCL schema files
|
||
|
|
let schema_files = (glob ($kcl_path | path join "*.k"))
|
||
|
|
let main_schema = ($schema_files | where ($it | str contains $name) | first | default "")
|
||
|
|
|
||
|
|
# Extract dependencies
|
||
|
|
let dependencies = ($mod_content.dependencies? | default {} | columns)
|
||
|
|
|
||
|
|
# Get description from schema file if available
|
||
|
|
let description = if ($main_schema != "") {
|
||
|
|
extract_schema_description $main_schema
|
||
|
|
} else {
|
||
|
|
$"($name | str title-case) cloud provider"
|
||
|
|
}
|
||
|
|
|
||
|
|
# Determine provider type
|
||
|
|
let provider_type = match $name {
|
||
|
|
"aws" => "cloud"
|
||
|
|
"upcloud" => "cloud"
|
||
|
|
"gcp" => "cloud"
|
||
|
|
"azure" => "cloud"
|
||
|
|
"local" => "local"
|
||
|
|
_ => "unknown"
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
name: $name
|
||
|
|
type: "provider"
|
||
|
|
provider_type: $provider_type
|
||
|
|
version: $mod_content.package.version
|
||
|
|
kcl_path: $kcl_path
|
||
|
|
main_schema: $main_schema
|
||
|
|
dependencies: $dependencies
|
||
|
|
description: $description
|
||
|
|
available: true
|
||
|
|
last_updated: (ls $kcl_mod_path | get 0.modified)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Extract description from KCL schema file
|
||
|
|
def extract_schema_description [schema_file: string]: nothing -> string {
|
||
|
|
if not ($schema_file | path exists) {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
# Read first few lines to find description
|
||
|
|
let content = (open $schema_file | lines | take 10)
|
||
|
|
let description_lines = ($content | where ($it | str starts-with "# ") | take 3)
|
||
|
|
|
||
|
|
if ($description_lines | is-empty) {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
$description_lines
|
||
|
|
| str replace "^# " ""
|
||
|
|
| str join " "
|
||
|
|
| str trim
|
||
|
|
}
|
||
|
|
|
||
|
|
# Search providers by name or type
|
||
|
|
export def search-providers [query: string]: nothing -> list<record> {
|
||
|
|
discover-providers
|
||
|
|
| where ($it.name | str contains $query) or ($it.provider_type | str contains $query) or ($it.description | str contains $query)
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get specific provider info
|
||
|
|
export def get-provider-info [name: string]: nothing -> record {
|
||
|
|
let providers = (discover-providers)
|
||
|
|
let found = ($providers | where name == $name | first)
|
||
|
|
|
||
|
|
if ($found | is-empty) {
|
||
|
|
error make { msg: $"Provider '($name)' not found" }
|
||
|
|
}
|
||
|
|
|
||
|
|
$found
|
||
|
|
}
|
||
|
|
|
||
|
|
# List providers by type
|
||
|
|
export def list-providers-by-type [type: string]: nothing -> list<record> {
|
||
|
|
discover-providers
|
||
|
|
| where provider_type == $type
|
||
|
|
}
|
||
|
|
|
||
|
|
# Validate provider availability
|
||
|
|
export def validate-providers [names: list<string>]: nothing -> record {
|
||
|
|
let available = (discover-providers | get name)
|
||
|
|
let missing = ($names | where ($it not-in $available))
|
||
|
|
let found = ($names | where ($it in $available))
|
||
|
|
|
||
|
|
{
|
||
|
|
requested: $names
|
||
|
|
found: $found
|
||
|
|
missing: $missing
|
||
|
|
valid: ($missing | is-empty)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Get default provider (first cloud provider found)
|
||
|
|
export def get-default-provider []: nothing -> string {
|
||
|
|
let cloud_providers = (list-providers-by-type "cloud")
|
||
|
|
|
||
|
|
if ($cloud_providers | is-empty) {
|
||
|
|
"local"
|
||
|
|
} else {
|
||
|
|
$cloud_providers | first | get name
|
||
|
|
}
|
||
|
|
}
|