@@ -154,8 +154,15 @@ async def try_delete(logger, resource, instances, **kwargs):
154
154
return check_required
155
155
156
156
157
- async def purge_openstack_resources (
158
- logger , clouds , cloud_name , cacert , name , include_volumes , include_appcred
157
+ async def purge_openstack_resources ( # noqa: C901
158
+ logger ,
159
+ clouds ,
160
+ cloud_name ,
161
+ cacert ,
162
+ name ,
163
+ include_volumes ,
164
+ include_loadbalancers ,
165
+ include_appcred ,
159
166
):
160
167
"""Cleans up the OpenStack resources created by the OCCM and CSI for a cluster."""
161
168
# Use the credential to delete external resources as required
@@ -180,10 +187,15 @@ async def purge_openstack_resources(
180
187
# Delete any loadbalancers associated with loadbalancer services for the cluster
181
188
lbapi = cloud .api_client ("load-balancer" , "/v2/lbaas/" )
182
189
loadbalancers = lbapi .resource ("loadbalancers" )
183
- check_lbs = await try_delete (
184
- logger , loadbalancers , lbs_for_cluster (loadbalancers , name ), cascade = "true"
185
- )
186
- logger .info ("deleted load balancers for LoadBalancer services" )
190
+ check_lbs = False
191
+ if include_loadbalancers :
192
+ check_lbs = await try_delete (
193
+ logger ,
194
+ loadbalancers ,
195
+ lbs_for_cluster (loadbalancers , name ),
196
+ cascade = "true" ,
197
+ )
198
+ logger .info ("deleted load balancers for LoadBalancer services" )
187
199
188
200
# Delete security groups associated with loadbalancer services for the cluster
189
201
secgroups = networkapi .resource ("security-groups" )
@@ -344,15 +356,15 @@ async def wrapper(**kwargs):
344
356
@kopf .on .event (CAPO_API_GROUP , "openstackclusters" )
345
357
@retry_event
346
358
async def on_openstackcluster_event (
347
- name , namespace , meta , labels , spec , logger , ** kwargs
359
+ name , namespace , meta , labels , spec , status , logger , ** kwargs
348
360
):
349
361
await _on_openstackcluster_event_impl (
350
- name , namespace , meta , labels , spec , logger , ** kwargs
362
+ name , namespace , meta , labels , spec , status , logger , ** kwargs
351
363
)
352
364
353
365
354
366
async def _on_openstackcluster_event_impl (
355
- name , namespace , meta , labels , spec , logger , ** kwargs
367
+ name , namespace , meta , labels , spec , status , logger , ** kwargs
356
368
):
357
369
"""Executes whenever an event occurs for an OpenStack cluster."""
358
370
# Get the resource for manipulating OpenStackClusters at the preferred version
@@ -421,15 +433,29 @@ async def _on_openstackcluster_event_impl(
421
433
)
422
434
remove_appcred = credential_annotation_value == CREDENTIAL_ANNOTATION_DELETE
423
435
436
+ # Handle the case where the API server load balancer is enabled but was
437
+ # never successfully created (possibly due to LB permissions error)
438
+ # meaning that there cannot be any other LBs to remove
439
+ # (since API server was never online due to missing load balancer)
440
+ remove_loadbalancers = (
441
+ # Default to false since this is default CAPO behaviour if
442
+ # ApiServerLoadBalancer field is omitted from OpenStackClusterSpec
443
+ # https://github.com/kubernetes-sigs/cluster-api-provider-openstack/blob/57ae27ee114bda3606d92163397697b640272673/api/v1beta1/openstackcluster_types.go#L99-L101
444
+ spec .get ("apiServerLoadBalancer" , {}).get ("enabled" , False )
445
+ and status .get ("apiServerLoadBalancer" , {}).get ("id" , "" ) != ""
446
+ )
447
+
424
448
await purge_openstack_resources (
425
449
logger ,
426
450
clouds ,
427
451
cloud_name ,
428
452
cacert ,
429
453
clustername ,
430
454
volumes_annotation_value == VOLUMES_ANNOTATION_DELETE ,
455
+ remove_loadbalancers ,
431
456
remove_appcred and len (finalizers ) == 1 ,
432
457
)
458
+
433
459
# If we get to here, OpenStack resources have been successfully deleted
434
460
# So we can remove the appcred secret if we are the last actor
435
461
if remove_appcred and len (finalizers ) == 1 :
0 commit comments