@@ -40,13 +40,16 @@ import (
4040 dpuprovisioningv1alpha1 "github.com/nvidia/doca-platform/api/provisioning/v1alpha1"
4141 hyperv1 "github.com/openshift/hypershift/api/hypershift/v1beta1"
4242 provisioningv1alpha1 "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/api/v1alpha1"
43+ "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/internal/common"
4344 "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/internal/controller"
4445 "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/internal/controller/bluefield"
4546 "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/internal/controller/dpucluster"
4647 "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/internal/controller/finalizer"
4748 "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/internal/controller/hostedcluster"
4849 "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/internal/controller/kubeconfiginjection"
50+ "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/internal/controller/metallb"
4951 "github.com/rh-ecosystem-edge/dpf-hcp-provisioner-operator/internal/controller/secrets"
52+ metallbv1beta1 "go.universe.tf/metallb/api/v1beta1"
5053 // +kubebuilder:scaffold:imports
5154)
5255
@@ -61,6 +64,7 @@ func init() {
6164 utilruntime .Must (provisioningv1alpha1 .AddToScheme (scheme ))
6265 utilruntime .Must (dpuprovisioningv1alpha1 .AddToScheme (scheme ))
6366 utilruntime .Must (hyperv1 .AddToScheme (scheme ))
67+ utilruntime .Must (metallbv1beta1 .AddToScheme (scheme ))
6468 // +kubebuilder:scaffold:scheme
6569}
6670
@@ -212,48 +216,60 @@ func main() {
212216 os .Exit (1 )
213217 }
214218
219+ client := mgr .GetClient ()
220+ recorder := mgr .GetEventRecorderFor (common .ControllerName )
221+ scheme := mgr .GetScheme ()
222+
215223 // Initialize BlueField Image Resolver
216- imageResolver := bluefield .NewImageResolver (mgr . GetClient (), mgr . GetEventRecorderFor ( "dpfhcpprovisioner-controller" ) )
224+ imageResolver := bluefield .NewImageResolver (client , recorder )
217225
218226 // Initialize DPUCluster Validator
219- dpuClusterValidator := dpucluster .NewValidator (mgr . GetClient (), mgr . GetEventRecorderFor ( "dpfhcpprovisioner-controller" ) )
227+ dpuClusterValidator := dpucluster .NewValidator (client , recorder )
220228
221229 // Initialize Secrets Validator
222- secretsValidator := secrets .NewValidator (mgr . GetClient (), mgr . GetEventRecorderFor ( "dpfhcpprovisioner-controller" ) )
230+ secretsValidator := secrets .NewValidator (client , recorder )
223231
224232 // Initialize Secret Manager for HostedCluster lifecycle
225- secretManager := hostedcluster .NewSecretManager (mgr . GetClient (), mgr . GetScheme () )
233+ secretManager := hostedcluster .NewSecretManager (client , scheme )
226234
227235 // Initialize HostedCluster Manager
228- hostedClusterManager := hostedcluster .NewHostedClusterManager (mgr . GetClient (), mgr . GetScheme () )
236+ hostedClusterManager := hostedcluster .NewHostedClusterManager (client , scheme )
229237
230238 // Initialize NodePool Manager
231- nodePoolManager := hostedcluster .NewNodePoolManager (mgr . GetClient (), mgr . GetScheme () )
239+ nodePoolManager := hostedcluster .NewNodePoolManager (client , scheme )
232240
233241 // Initialize Kubeconfig Injector
234- kubeconfigInjector := kubeconfiginjection .NewKubeconfigInjector (mgr .GetClient (), mgr .GetEventRecorderFor ("dpfhcpprovisioner-controller" ))
242+ kubeconfigInjector := kubeconfiginjection .NewKubeconfigInjector (client , recorder )
243+
244+ // Initialize MetalLB Manager
245+ metalLBManager := metallb .NewMetalLBManager (client , recorder )
235246
236247 // Initialize Finalizer Manager with pluggable cleanup handlers
237248 // Handlers are executed in registration order
238- finalizerManager := finalizer .NewManager (mgr . GetClient (), mgr . GetEventRecorderFor ( "dpfhcpprovisioner-controller" ) )
249+ finalizerManager := finalizer .NewManager (client , recorder )
239250
240- // Register cleanup handlers in order (dependent resources first)
251+ // Register cleanup handlers in order (dependent resources first, dependencies last )
241252 // 1. Kubeconfig injection cleanup (removes kubeconfig from DPUCluster namespace)
242- finalizerManager .RegisterHandler (kubeconfiginjection .NewCleanupHandler (mgr .GetClient (), mgr .GetEventRecorderFor ("dpfhcpprovisioner-controller" )))
243- // 2. HostedCluster cleanup (removes HostedCluster, NodePool, and secrets)
244- finalizerManager .RegisterHandler (hostedcluster .NewCleanupHandler (mgr .GetClient (), mgr .GetEventRecorderFor ("dpfhcpprovisioner-controller" )))
253+ finalizerManager .RegisterHandler (kubeconfiginjection .NewCleanupHandler (client , recorder ))
254+ // 2. HostedCluster cleanup (removes HostedCluster, NodePool, services, and secrets)
255+ // Must run before MetalLB cleanup because LoadBalancer services depend on IPAddressPool
256+ finalizerManager .RegisterHandler (hostedcluster .NewCleanupHandler (client , recorder ))
257+ // 3. MetalLB cleanup (removes IPAddressPool and L2Advertisement)
258+ // Must run after HostedCluster cleanup to avoid deleting IPs while services still exist
259+ finalizerManager .RegisterHandler (metallb .NewCleanupHandler (client , recorder ))
245260
246261 // Initialize Status Syncer for HostedCluster status mirroring
247- statusSyncer := hostedcluster .NewStatusSyncer (mgr . GetClient () )
262+ statusSyncer := hostedcluster .NewStatusSyncer (client )
248263
249264 if err := (& controller.DPFHCPProvisionerReconciler {
250- Client : mgr . GetClient () ,
251- Scheme : mgr . GetScheme () ,
252- Recorder : mgr . GetEventRecorderFor ( "dpfhcpprovisioner-controller" ) ,
265+ Client : client ,
266+ Scheme : scheme ,
267+ Recorder : recorder ,
253268 ImageResolver : imageResolver ,
254269 DPUClusterValidator : dpuClusterValidator ,
255270 SecretsValidator : secretsValidator ,
256271 SecretManager : secretManager ,
272+ MetalLBManager : metalLBManager ,
257273 HostedClusterManager : hostedClusterManager ,
258274 NodePoolManager : nodePoolManager ,
259275 FinalizerManager : finalizerManager ,
0 commit comments