Skip to content

Commit cb62037

Browse files
authored
Skip load balancer clean up when none were created (#218)
* Skip load balancer clean up when none were created * Update unit tests and fix linter errors
1 parent 2a05362 commit cb62037

File tree

3 files changed

+42
-11
lines changed

3 files changed

+42
-11
lines changed

capi_janitor/openstack/operator.py

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,15 @@ async def try_delete(logger, resource, instances, **kwargs):
154154
return check_required
155155

156156

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,
159166
):
160167
"""Cleans up the OpenStack resources created by the OCCM and CSI for a cluster."""
161168
# Use the credential to delete external resources as required
@@ -180,10 +187,15 @@ async def purge_openstack_resources(
180187
# Delete any loadbalancers associated with loadbalancer services for the cluster
181188
lbapi = cloud.api_client("load-balancer", "/v2/lbaas/")
182189
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")
187199

188200
# Delete security groups associated with loadbalancer services for the cluster
189201
secgroups = networkapi.resource("security-groups")
@@ -344,15 +356,15 @@ async def wrapper(**kwargs):
344356
@kopf.on.event(CAPO_API_GROUP, "openstackclusters")
345357
@retry_event
346358
async def on_openstackcluster_event(
347-
name, namespace, meta, labels, spec, logger, **kwargs
359+
name, namespace, meta, labels, spec, status, logger, **kwargs
348360
):
349361
await _on_openstackcluster_event_impl(
350-
name, namespace, meta, labels, spec, logger, **kwargs
362+
name, namespace, meta, labels, spec, status, logger, **kwargs
351363
)
352364

353365

354366
async def _on_openstackcluster_event_impl(
355-
name, namespace, meta, labels, spec, logger, **kwargs
367+
name, namespace, meta, labels, spec, status, logger, **kwargs
356368
):
357369
"""Executes whenever an event occurs for an OpenStack cluster."""
358370
# Get the resource for manipulating OpenStackClusters at the preferred version
@@ -421,15 +433,29 @@ async def _on_openstackcluster_event_impl(
421433
)
422434
remove_appcred = credential_annotation_value == CREDENTIAL_ANNOTATION_DELETE
423435

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+
424448
await purge_openstack_resources(
425449
logger,
426450
clouds,
427451
cloud_name,
428452
cacert,
429453
clustername,
430454
volumes_annotation_value == VOLUMES_ANNOTATION_DELETE,
455+
remove_loadbalancers,
431456
remove_appcred and len(finalizers) == 1,
432457
)
458+
433459
# If we get to here, OpenStack resources have been successfully deleted
434460
# So we can remove the appcred secret if we are the last actor
435461
if remove_appcred and len(finalizers) == 1:

capi_janitor/tests/openstack/test_operator.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ async def test_on_openstackcluster_event_adds_finalizers(
232232
meta={},
233233
labels={},
234234
spec={},
235+
status={},
235236
logger=logger,
236237
body={},
237238
)
@@ -258,6 +259,7 @@ async def test_on_openstackcluster_event_skip_no_finalizers(
258259
meta={"deletionTimestamp": "2023-10-01T00:00:00Z"},
259260
labels={},
260261
spec={},
262+
status={},
261263
logger=logger,
262264
body={},
263265
)
@@ -319,6 +321,7 @@ async def test_on_openstackcluster_event_calls_purge(
319321
},
320322
labels={},
321323
spec={"identityRef": {"name": "appcred42"}},
324+
status={},
322325
logger=logger,
323326
body={},
324327
)
@@ -330,6 +333,7 @@ async def test_on_openstackcluster_event_calls_purge(
330333
None,
331334
"mycluster",
332335
True,
336+
False,
333337
True,
334338
)
335339
mock_delete_secret.assert_awaited_once_with("appcred42", "namespace1")
@@ -383,6 +387,7 @@ async def test_purge_openstack_resources_raises(self, mock_from_clouds):
383387
None,
384388
"mycluster",
385389
True,
390+
True,
386391
False,
387392
)
388393
self.assertEqual(

tox.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ commands = stestr run {posargs}
2020
[testenv:autofix]
2121
commands =
2222
ruff format {tox_root}
23-
codespell {tox_root} -w
23+
codespell {tox_root} -w --skip venv
2424
ruff check {tox_root} --fix
2525

2626
[testenv:black]
@@ -29,7 +29,7 @@ commands =
2929
commands = black {tox_root} --check
3030

3131
[testenv:codespell]
32-
commands = codespell {posargs}
32+
commands = codespell --skip ./venv {posargs}
3333

3434
[testenv:ruff]
3535
description = Run Ruff checks

0 commit comments

Comments
 (0)