@@ -50,6 +50,9 @@ func NewService(scope *scope.ClusterScope) *Service {
5050// ErrNoLoadBalancerAvailable indicates that no available load balancer could be fond.
5151var ErrNoLoadBalancerAvailable = fmt .Errorf ("no available load balancer" )
5252
53+ // ErrControlPlaneEndpointNotSet indicates that hetznercluster.spec.controlPlaneEndpoint is not set.
54+ var ErrControlPlaneEndpointNotSet = errors .New ("hetznercluster.spec.controlPlaneEndpoint is not set" )
55+
5356// Reconcile implements the life cycle of HCloud load balancers.
5457func (s * Service ) Reconcile (ctx context.Context ) (reconcile.Result , error ) {
5558 // delete the deprecated condition from existing cluster objects
@@ -68,20 +71,37 @@ func (s *Service) Reconcile(ctx context.Context) (reconcile.Result, error) {
6871 }
6972
7073 if lb == nil {
71- // fixed name is set - we expect a load balancer with this name to exist
72-
7374 if s .scope .HetznerCluster .Spec .ControlPlaneLoadBalancer .Name != nil {
75+ // fixed name is set - we expect a load balancer with this name to exist
7476 lb , err = s .ownExistingLoadBalancer (ctx )
75-
76- // if load balancer is not found even though we expect it to exist, wait and reconcile until user creates it
77- if errors .Is (err , ErrNoLoadBalancerAvailable ) {
78- return reconcile.Result {RequeueAfter : 1 * time .Minute }, nil
77+ if err != nil {
78+ // if load balancer is not found even though we expect it to exist, wait and reconcile until user creates it
79+ if errors .Is (err , ErrNoLoadBalancerAvailable ) {
80+ return reconcile.Result {RequeueAfter : 1 * time .Minute }, nil
81+ }
82+ return reconcile.Result {}, fmt .Errorf ("failed to own existing load balancer (name=%s): %w" , * s .scope .HetznerCluster .Spec .ControlPlaneLoadBalancer .Name , err )
7983 }
8084 } else {
8185 lb , err = s .createLoadBalancer (ctx )
82- }
83- if err != nil {
84- return reconcile.Result {}, fmt .Errorf ("failed to own/create load balancer: %w" , err )
86+ if err != nil {
87+ if errors .Is (err , ErrControlPlaneEndpointNotSet ) {
88+ // When an external ControlPlane Provider gets used (Kamaji), it might
89+ // need some time until the endpoint is available.
90+ err = fmt .Errorf ("requeue, waiting for control-plane endpoint to be set: %w" ,
91+ err )
92+ conditions .MarkFalse (
93+ s .scope .HetznerCluster ,
94+ infrav1 .LoadBalancerReadyCondition ,
95+ "MissingControlPlaneEndpoint" ,
96+ clusterv1 .ConditionSeverityWarning ,
97+ "%s" ,
98+ err .Error (),
99+ )
100+ s .scope .Logger .Info (err .Error ())
101+ return reconcile.Result {RequeueAfter : 10 * time .Second }, nil
102+ }
103+ return reconcile.Result {}, fmt .Errorf ("failed to create load balancer: %w" , err )
104+ }
85105 }
86106 }
87107
@@ -287,7 +307,10 @@ func (s *Service) reconcileServices(ctx context.Context, lb *hcloud.LoadBalancer
287307}
288308
289309func (s * Service ) createLoadBalancer (ctx context.Context ) (* hcloud.LoadBalancer , error ) {
290- opts := createOptsFromSpec (s .scope .HetznerCluster )
310+ opts , err := createOptsFromSpec (s .scope .HetznerCluster )
311+ if err != nil {
312+ return nil , err
313+ }
291314 lb , err := s .scope .HCloudClient .CreateLoadBalancer (ctx , opts )
292315 if err != nil {
293316 err = fmt .Errorf ("failed to create load balancer: %w" , err )
@@ -309,7 +332,7 @@ func (s *Service) createLoadBalancer(ctx context.Context) (*hcloud.LoadBalancer,
309332 return lb , nil
310333}
311334
312- func createOptsFromSpec (hc * infrav1.HetznerCluster ) hcloud.LoadBalancerCreateOpts {
335+ func createOptsFromSpec (hc * infrav1.HetznerCluster ) ( hcloud.LoadBalancerCreateOpts , error ) {
313336 // gather algorithm type
314337 algorithmType := hc .Spec .ControlPlaneLoadBalancer .Algorithm .HCloudAlgorithmType ()
315338
@@ -323,6 +346,10 @@ func createOptsFromSpec(hc *infrav1.HetznerCluster) hcloud.LoadBalancerCreateOpt
323346 network = & hcloud.Network {ID : hc .Status .Network .ID }
324347 }
325348
349+ if hc .Spec .ControlPlaneEndpoint == nil {
350+ return hcloud.LoadBalancerCreateOpts {}, ErrControlPlaneEndpointNotSet
351+ }
352+
326353 listenPort := int (hc .Spec .ControlPlaneEndpoint .Port )
327354 publicInterface := true
328355 return hcloud.LoadBalancerCreateOpts {
@@ -341,7 +368,7 @@ func createOptsFromSpec(hc *infrav1.HetznerCluster) hcloud.LoadBalancerCreateOpt
341368 Proxyprotocol : & proxyprotocol ,
342369 },
343370 },
344- }
371+ }, nil
345372}
346373
347374// Delete implements the deletion of HCloud load balancers.
0 commit comments