Skip to content

Commit

Permalink
Merge pull request #214 from lsst-sqre/tickets/DM-41630
Browse files Browse the repository at this point in the history
DM-41630: Add propagation_policy to Kubernetes mock deletes
  • Loading branch information
rra authored Nov 10, 2023
2 parents 45c61d5 + 5b9cb08 commit c38b613
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 14 deletions.
3 changes: 3 additions & 0 deletions changelog.d/20231110_124506_rra_DM_41630.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### New features

- Add validated but ignored optional `propagation_policy` arguments to every delete method of the Kubernetes mock for better compatibility with the actual Kubernetes API. Previously, this argument was only accepted by `delete_namespaced_job`.
54 changes: 40 additions & 14 deletions src/safir/testing/kubernetes.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ async def delete_namespaced_custom_object(
name: str,
*,
grace_period_seconds: int | None = None,
propagation_policy: str = "Foreground",
body: V1DeleteOptions | None = None,
) -> Any:
"""Delete a custom namespaced object.
Expand All @@ -552,6 +553,8 @@ async def delete_namespaced_custom_object(
Custom object to delete.
grace_period_seconds
Grace period for object deletion (currently ignored).
propagation_policy
Propagation policy for deletion. Has no effect on the mock.
body
Delete options (currently ignored).
Expand All @@ -570,7 +573,7 @@ async def delete_namespaced_custom_object(
obj = self._get_object(namespace, key, name)
stream = self._event_streams[namespace][key]
stream.add_custom_event("DELETED", obj)
return self._delete_object(namespace, key, name)
return self._delete_object(namespace, key, name, propagation_policy)

async def get_namespaced_custom_object(
self,
Expand Down Expand Up @@ -872,6 +875,7 @@ async def delete_namespaced_config_map(
namespace: str,
*,
grace_period_seconds: int | None = None,
propagation_policy: str = "Foreground",
body: V1DeleteOptions | None = None,
) -> V1Status:
"""Delete a ``ConfigMap`` object.
Expand All @@ -884,6 +888,8 @@ async def delete_namespaced_config_map(
Namespace of object.
grace_period_seconds
Grace period for object deletion (currently ignored).
propagation_policy
Propagation policy for deletion. Has no effect on the mock.
body
Delete options (currently ignored).
Expand All @@ -898,7 +904,9 @@ async def delete_namespaced_config_map(
Raised with 404 status if the object does not exist.
"""
self._maybe_error("delete_namespaced_config_map", name, namespace)
return self._delete_object(namespace, "ConfigMap", name)
return self._delete_object(
namespace, "ConfigMap", name, propagation_policy
)

async def read_namespaced_config_map(
self, name: str, namespace: str
Expand Down Expand Up @@ -1048,6 +1056,7 @@ async def delete_namespaced_ingress(
namespace: str,
*,
grace_period_seconds: int | None = None,
propagation_policy: str = "Foreground",
body: V1DeleteOptions | None = None,
) -> V1Status:
"""Delete an ingress object.
Expand All @@ -1060,6 +1069,8 @@ async def delete_namespaced_ingress(
Namespace of ingress to delete.
grace_period_seconds
Grace period for object deletion (currently ignored).
propagation_policy
Propagation policy for deletion. Has no effect on the mock.
body
Delete options (currently ignored).
Expand All @@ -1077,7 +1088,9 @@ async def delete_namespaced_ingress(
ingress = self._get_object(namespace, "Ingress", name)
stream = self._event_streams[namespace]["Ingress"]
stream.add_event("DELETED", ingress)
return self._delete_object(namespace, "Ingress", name)
return self._delete_object(
namespace, "Ingress", name, propagation_policy
)

async def list_namespaced_ingress(
self,
Expand Down Expand Up @@ -1291,8 +1304,7 @@ async def delete_namespaced_job(
grace_period_seconds
Grace period for object deletion (currently ignored).
propagation_policy
Propagation policy for deletion. Must be ``Foreground`` if
specified, and has no effect on the behavior of the mock.
Propagation policy for deletion. Has no effect on the mock.
body
Delete options (currently ignored).
Expand All @@ -1303,14 +1315,9 @@ async def delete_namespaced_job(
Raises
------
AssertionError
Raised if the propagation policy is not ``Foreground``.
kubernetes_asyncio.client.ApiException
Raised with 404 status if the job was not found.
"""
if propagation_policy not in ("Foreground", "Background", "Orphan"):
msg = f"Invalid propagation_policy {propagation_policy}"
raise AssertionError(msg)
self._maybe_error("delete_namespaced_job", name, namespace)

# This simulates a foreground deletion, where the Job is blocked
Expand All @@ -1327,7 +1334,7 @@ async def delete_namespaced_job(
job = self._get_object(namespace, "Job", name)
stream = self._event_streams[namespace]["Job"]
stream.add_event("DELETED", job)
return self._delete_object(namespace, "Job", name)
return self._delete_object(namespace, "Job", name, propagation_policy)

async def list_namespaced_job(
self,
Expand Down Expand Up @@ -1461,6 +1468,7 @@ async def delete_namespace(
name: str,
*,
grace_period_seconds: int | None = None,
propagation_policy: str = "Foreground",
body: V1DeleteOptions | None = None,
) -> None:
"""Delete a namespace.
Expand All @@ -1473,6 +1481,8 @@ async def delete_namespace(
Namespace to delete.
grace_period_seconds
Grace period for object deletion (currently ignored).
propagation_policy
Propagation policy for deletion. Has no effect on the mock.
body
Delete options (currently ignored).
Expand Down Expand Up @@ -1781,6 +1791,7 @@ async def delete_namespaced_pod(
namespace: str,
*,
grace_period_seconds: int | None = None,
propagation_policy: str = "Foreground",
body: V1DeleteOptions | None = None,
) -> V1Status:
"""Delete a pod object.
Expand All @@ -1793,6 +1804,8 @@ async def delete_namespaced_pod(
Namespace of pod to delete.
grace_period_seconds
Grace period for object deletion (currently ignored).
propagation_policy
Propagation policy for deletion. Has no effect on the mock.
body
Delete options (currently ignored).
Expand All @@ -1810,7 +1823,7 @@ async def delete_namespaced_pod(
pod = self._get_object(namespace, "Pod", name)
stream = self._event_streams[namespace]["Pod"]
stream.add_event("DELETED", pod)
return self._delete_object(namespace, "Pod", name)
return self._delete_object(namespace, "Pod", name, propagation_policy)

async def list_namespaced_pod(
self,
Expand Down Expand Up @@ -2168,6 +2181,7 @@ async def delete_namespaced_service(
namespace: str,
*,
grace_period_seconds: int | None = None,
propagation_policy: str = "Foreground",
body: V1DeleteOptions | None = None,
) -> V1Status:
"""Delete a service object.
Expand All @@ -2180,6 +2194,8 @@ async def delete_namespaced_service(
Namespace of service to delete.
grace_period_seconds
Grace period for object deletion (currently ignored).
propagation_policy
Propagation policy for deletion. Has no effect on the mock.
body
Delete options (currently ignored).
Expand All @@ -2197,7 +2213,9 @@ async def delete_namespaced_service(
service = self._get_object(namespace, "Service", name)
stream = self._event_streams[namespace]["Service"]
stream.add_event("DELETED", service)
return self._delete_object(namespace, "Service", name)
return self._delete_object(
namespace, "Service", name, propagation_policy
)

async def list_namespaced_service(
self,
Expand Down Expand Up @@ -2301,7 +2319,9 @@ async def read_namespaced_service(

# Internal helper functions.

def _delete_object(self, namespace: str, key: str, name: str) -> V1Status:
def _delete_object(
self, namespace: str, key: str, name: str, propagation_policy: str
) -> V1Status:
"""Delete an object from internal data structures.
Parameters
Expand All @@ -2312,6 +2332,8 @@ def _delete_object(self, namespace: str, key: str, name: str) -> V1Status:
Key under which the object is stored (usually the kind).
name
Name of the object.
propagation_policy
Propagation policy for deletion. Has no effect on the mock.
Returns
-------
Expand All @@ -2323,6 +2345,10 @@ def _delete_object(self, namespace: str, key: str, name: str) -> V1Status:
kubernetes_asyncio.client.ApiException
Raised with a 404 status if the object is not found.
"""
if propagation_policy not in ("Foreground", "Background", "Orphan"):
msg = f"Invalid propagation_policy {propagation_policy}"
raise AssertionError(msg)

# Called for the side effect of raising an exception if the object is
# not found.
self._get_object(namespace, key, name)
Expand Down

0 comments on commit c38b613

Please sign in to comment.