package clusters import ( "fmt" "sync" "time" ) // ClusterInfo represents a Kubernetes cluster type ClusterInfo struct { Name string APIServer string Healthy bool LastCheck time.Time Capacity int // Max concurrent tasks Usage int // Current task count } // ClusterManager manages multiple K8s clusters type ClusterManager struct { mu sync.RWMutex clusters map[string]*ClusterInfo } // NewClusterManager creates a new cluster manager func NewClusterManager() *ClusterManager { return &ClusterManager{ clusters: make(map[string]*ClusterInfo), } } // RegisterCluster registers a new cluster func (cm *ClusterManager) RegisterCluster(name, apiServer string, capacity int) error { if name == "" || apiServer == "" { return fmt.Errorf("cluster name and API server required") } cm.mu.Lock() defer cm.mu.Unlock() if _, exists := cm.clusters[name]; exists { return fmt.Errorf("cluster already registered: %s", name) } cm.clusters[name] = &ClusterInfo{ Name: name, APIServer: apiServer, Healthy: true, LastCheck: time.Now(), Capacity: capacity, Usage: 0, } return nil } // UnregisterCluster removes a cluster func (cm *ClusterManager) UnregisterCluster(name string) error { cm.mu.Lock() defer cm.mu.Unlock() if _, exists := cm.clusters[name]; !exists { return fmt.Errorf("cluster not found: %s", name) } delete(cm.clusters, name) return nil } // GetCluster retrieves cluster info func (cm *ClusterManager) GetCluster(name string) (*ClusterInfo, bool) { cm.mu.RLock() defer cm.mu.RUnlock() cluster, exists := cm.clusters[name] return cluster, exists } // ListClusters returns all registered clusters func (cm *ClusterManager) ListClusters() map[string]*ClusterInfo { cm.mu.RLock() defer cm.mu.RUnlock() result := make(map[string]*ClusterInfo) for name, cluster := range cm.clusters { result[name] = cluster } return result } // HealthCheck checks cluster health func (cm *ClusterManager) HealthCheck(name string) error { cm.mu.Lock() defer cm.mu.Unlock() cluster, exists := cm.clusters[name] if !exists { return fmt.Errorf("cluster not found: %s", name) } // Simulate health check (in production, query API server) cluster.Healthy = true cluster.LastCheck = time.Now() return nil } // MarkUnhealthy marks a cluster as unhealthy func (cm *ClusterManager) MarkUnhealthy(name string) error { cm.mu.Lock() defer cm.mu.Unlock() cluster, exists := cm.clusters[name] if !exists { return fmt.Errorf("cluster not found: %s", name) } cluster.Healthy = false return nil } // AllocateTask allocates a task to a cluster func (cm *ClusterManager) AllocateTask(name string) error { cm.mu.Lock() defer cm.mu.Unlock() cluster, exists := cm.clusters[name] if !exists { return fmt.Errorf("cluster not found: %s", name) } if !cluster.Healthy { return fmt.Errorf("cluster not healthy: %s", name) } if cluster.Usage >= cluster.Capacity { return fmt.Errorf("cluster at capacity: %s", name) } cluster.Usage++ return nil } // ReleaseTask releases a task from a cluster func (cm *ClusterManager) ReleaseTask(name string) error { cm.mu.Lock() defer cm.mu.Unlock() cluster, exists := cm.clusters[name] if !exists { return fmt.Errorf("cluster not found: %s", name) } if cluster.Usage > 0 { cluster.Usage-- } return nil } // FindBestCluster finds the cluster with most available capacity func (cm *ClusterManager) FindBestCluster() (string, error) { cm.mu.RLock() defer cm.mu.RUnlock() var bestCluster string maxCapacity := 0 for name, cluster := range cm.clusters { if cluster.Healthy { available := cluster.Capacity - cluster.Usage if available > maxCapacity { bestCluster = name maxCapacity = available } } } if bestCluster == "" { return "", fmt.Errorf("no healthy clusters available") } return bestCluster, nil } // GetCapacitySummary returns capacity summary func (cm *ClusterManager) GetCapacitySummary() map[string]interface{} { cm.mu.RLock() defer cm.mu.RUnlock() totalCapacity := 0 totalUsage := 0 healthyCount := 0 for _, cluster := range cm.clusters { totalCapacity += cluster.Capacity totalUsage += cluster.Usage if cluster.Healthy { healthyCount++ } } return map[string]interface{}{ "total_capacity": totalCapacity, "total_usage": totalUsage, "healthy_clusters": healthyCount, "total_clusters": len(cm.clusters), } } // GetHealthStatus returns health status for all clusters func (cm *ClusterManager) GetHealthStatus() map[string]bool { cm.mu.RLock() defer cm.mu.RUnlock() result := make(map[string]bool) for name, cluster := range cm.clusters { result[name] = cluster.Healthy } return result }