package harvester import ( "context" "fmt" "vanderlande.com/ittp/appstack/rig-operator/api/v1alpha1" template "vanderlande.com/ittp/appstack/rig-operator/internal/templates/harvester" ) // harvesterNodePool matches the exact JSON structure required by the Helm Chart type harvesterNodePool struct { Name string `json:"name"` DisplayName string `json:"displayName"` Quantity int `json:"quantity"` Etcd bool `json:"etcd"` ControlPlane bool `json:"controlplane"` Worker bool `json:"worker"` Paused bool `json:"paused"` // Harvester Specific Fields CpuCount int `json:"cpuCount"` MemorySize int `json:"memorySize"` // GB DiskSize int `json:"diskSize"` // GB ImageName string `json:"imageName"` NetworkName string `json:"networkName"` SshUser string `json:"sshUser"` VmNamespace string `json:"vmNamespace"` UserData string `json:"userData"` } type Strategy struct { blueprint *v1alpha1.HarvesterBlueprint userData string rancherURL string defaults template.Defaults } // NewStrategy initializes the strategy with defaults and optional overrides func NewStrategy(hbp *v1alpha1.HarvesterBlueprint, infraUserData string, infraRancherURL string, defaults template.Defaults) *Strategy { // 1. Determine UserData priority: Infra (IBP) > Template Default finalUserData := infraUserData if finalUserData == "" { finalUserData = defaults.UserData } return &Strategy{ blueprint: hbp, userData: finalUserData, rancherURL: infraRancherURL, defaults: defaults, } } // GenerateNodePools implements provider.Strategy func (s *Strategy) GenerateNodePools(ctx context.Context, cbp *v1alpha1.ClusterBlueprint) (interface{}, error) { var pools []interface{} // Helper to map generic req -> harvester specific struct mapPool := func(name string, qty, cpu, memGB, diskGB int, isEtcd, isCp, isWk bool) harvesterNodePool { return harvesterNodePool{ Name: name, DisplayName: name, Quantity: qty, Etcd: isEtcd, ControlPlane: isCp, Worker: isWk, Paused: false, // Mapping: Generic (GB) -> Harvester (GB) [No conversion needed] CpuCount: cpu, MemorySize: memGB, DiskSize: diskGB, // Harvester Specifics from HBP ImageName: s.blueprint.Spec.ImageName, NetworkName: s.blueprint.Spec.NetworkName, SshUser: s.blueprint.Spec.SshUser, VmNamespace: s.blueprint.Spec.VmNamespace, UserData: s.userData, } } // 1. Control Plane Pool cpQty := 1 if cbp.Spec.ControlPlaneHA { cpQty = 3 } // Use Defaults from YAML for CP sizing pools = append(pools, mapPool( "cp-pool", cpQty, s.defaults.CP_CPU, s.defaults.CP_Mem, s.defaults.CP_Disk, true, true, false, )) // 2. Worker Pools for _, wp := range cbp.Spec.WorkerPools { pools = append(pools, mapPool( wp.Name, wp.Quantity, wp.CpuCores, wp.MemoryGB, wp.DiskGB, false, false, true, )) } return pools, nil } // GetGlobalOverrides implements provider.Strategy func (s *Strategy) GetGlobalOverrides(ctx context.Context, cbp *v1alpha1.ClusterBlueprint, credentialSecretName string) (map[string]interface{}, error) { // secret://: secretURI := fmt.Sprintf("secret://%s:%s", cbp.Namespace, credentialSecretName) overrides := map[string]interface{}{ "cloud_provider_name": "harvester", "cloud_provider_config": secretURI, // Inject Rancher URL "rancher": map[string]interface{}{ "cattle": map[string]interface{}{ "url": s.rancherURL, }, }, "chartValues": map[string]interface{}{ "harvester-cloud-provider": map[string]interface{}{ "global": map[string]interface{}{ "cattle": map[string]interface{}{ "clusterName": cbp.Name, }, }, }, }, } return overrides, nil }