#!/usr/bin/env nu # Cluster Discovery System # Discovers available cluster definitions with metadata extraction use ../lib_provisioning/config/accessor.nu config-get # Discover all available clusters export def discover-clusters []: nothing -> list { # Get absolute path to extensions directory from config let clusters_path = (config-get "paths.clusters" | path expand) if not ($clusters_path | path exists) { error make { msg: $"Clusters path not found: ($clusters_path)" } } # Find all cluster directories with KCL modules ls $clusters_path | where type == "dir" | each { |dir| let cluster_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_cluster_metadata $cluster_name $kcl_path } } | compact | sort-by name } # Extract metadata from a cluster's KCL module def extract_cluster_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) cluster configuration" } # Extract cluster components from schema let components = extract_cluster_components $main_schema # Determine cluster type based on components let cluster_type = determine_cluster_type $components { name: $name type: "cluster" cluster_type: $cluster_type version: $mod_content.package.version kcl_path: $kcl_path main_schema: $main_schema dependencies: $dependencies components: $components 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 } # Extract cluster components from schema def extract_cluster_components [schema_file: string]: nothing -> list { if not ($schema_file | path exists) { return [] } let content = (open $schema_file) # Look for component patterns in the schema let components = [] # Check for common component mentions let common_components = [ "kubernetes", "k8s", "cilium", "calico", "nginx", "traefik", "prometheus", "grafana", "redis", "postgres", "mysql", "buildkit", "registry", "docker", "containerd" ] $common_components | each { |comp| if ($content | str contains $comp) { $comp } } | compact } # Determine cluster type based on components def determine_cluster_type [components: list]: nothing -> string { if ($components | any { |comp| $comp in ["buildkit", "registry", "docker"] }) { "ci-cd" } else if ($components | any { |comp| $comp in ["prometheus", "grafana"] }) { "monitoring" } else if ($components | any { |comp| $comp in ["nginx", "traefik"] }) { "web" } else if ($components | any { |comp| $comp in ["redis", "postgres", "mysql"] }) { "database" } else if ($components | any { |comp| $comp in ["kubernetes", "k8s"] }) { "orchestration" } else { "application" } } # Search clusters by name, type, or components export def search-clusters [query: string]: nothing -> list { discover-clusters | where ( ($it.name | str contains $query) or ($it.cluster_type | str contains $query) or ($it.description | str contains $query) or ($it.components | any { |comp| $comp | str contains $query }) ) } # Get specific cluster info export def get-cluster-info [name: string]: nothing -> record { let clusters = (discover-clusters) let found = ($clusters | where name == $name | first) if ($found | is-empty) { error make { msg: $"Cluster '($name)' not found" } } $found } # List clusters by type export def list-clusters-by-type [type: string]: nothing -> list { discover-clusters | where cluster_type == $type } # Validate cluster availability export def validate-clusters [names: list]: nothing -> record { let available = (discover-clusters | 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 clusters that use specific components export def find-clusters-with-component [component: string]: nothing -> list { discover-clusters | where ($it.components | any { |comp| $comp == $component }) } # List all available cluster types export def list-cluster-types []: nothing -> list { discover-clusters | get cluster_type | uniq | sort }