Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Improved twingate_connector_recreate_pod logic #179

Merged
merged 4 commits into from Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 19 additions & 26 deletions app/handlers/handlers_connectors.py
@@ -1,5 +1,3 @@
import time

import kopf
import kubernetes.client
import pendulum
Expand Down Expand Up @@ -85,17 +83,24 @@ def get_connector_secret(
)


def check_pod_exists(namespace: str, name: str) -> bool:
def get_existing_pod(
namespace: str, name: str, kapi: kubernetes.client.CoreV1Api | None = None
) -> kubernetes.client.V1Pod | None:
try:
kapi = kubernetes.client.CoreV1Api()
kapi.read_namespaced_pod(name=name, namespace=namespace)
return True
kapi = kapi or kubernetes.client.CoreV1Api()
return kapi.read_namespaced_pod(name=name, namespace=namespace)
except kubernetes.client.exceptions.ApiException as ex:
if ex.status == 404:
return False
return None
raise


def check_pod_exists(
namespace: str, name: str, kapi: kubernetes.client.CoreV1Api | None = None
) -> bool:
return bool(get_existing_pod(namespace, name, kapi=kapi))


@kopf.on.create("twingateconnector")
def twingate_connector_create(body, memo, logger, namespace, patch, **_):
settings = memo.twingate_settings
Expand Down Expand Up @@ -265,27 +270,13 @@ def is_conflict_already_exists(apiex):
kopf.adopt(pod, owner=body, strict=True, forced=True)
kopf.label(pod, {"twingate.com/connector": crd.metadata.name})

retry_count = 0
kapi = kubernetes.client.CoreV1Api()
while True:
try:
kapi.create_namespaced_pod(namespace=namespace, body=pod)
break
except kubernetes.client.exceptions.ApiException as apiex: # noqa: PERF203
if is_conflict_already_exists(apiex):
# Pod is not deleted yet... retry
logger.info(
"Pod %s not deleted yet. Retrying (%s)...",
pod.metadata.name,
retry_count,
)
retry_count += 1
if retry_count > 3:
raise
time.sleep(2)
else:
raise
if check_pod_exists(namespace, crd.metadata.name, kapi=kapi):
raise kopf.TemporaryError(
f"Pod {crd.metadata.name} not deleted yet. Retrying (%s)...", delay=1
)

kapi.create_namespaced_pod(namespace=namespace, body=pod)
patch.meta["labels"] = {LABEL_CONNECTOR_POD_DELETED: None}


Expand Down Expand Up @@ -338,5 +329,7 @@ def twingate_connector_pod_deleted(body, spec, meta, logger, namespace, memo, **
except kubernetes.client.exceptions.ApiException:
logger.exception("Failed to annotate connector %s", owner["name"])

return success(msg="deleted")


# endregion
7 changes: 6 additions & 1 deletion app/handlers/tests/test_handlers_connector.py
Expand Up @@ -319,8 +319,13 @@ def test_timer_check_image_version_with_imagepolicy_do_nothing_if_check_not_due(
assert run.patch_mock.meta == {}


def test_twingate_connector_recreate_pod(get_connector_and_crd, kopf_handler_runner):
def test_twingate_connector_recreate_pod(
k8s_client_mock, get_connector_and_crd, kopf_handler_runner
):
connector, crd = get_connector_and_crd()

k8s_client_mock.read_namespaced_pod.return_value = None

run = kopf_handler_runner(twingate_connector_recreate_pod, crd, MagicMock())

run.kopf_adopt_mock.assert_called_once_with(
Expand Down
6 changes: 4 additions & 2 deletions tests_integration/test_connector_flows.py
Expand Up @@ -89,7 +89,7 @@ def test_connector_flows(kopf_settings, kopf_runner_args, ci_run_number):
assert runner.exit_code == 0


def test_connector_flowes_image_change(kopf_settings, kopf_runner_args, ci_run_number):
def test_connector_flows_image_change(kopf_settings, kopf_runner_args, ci_run_number):
connector_name = f"test-connector-image-{ci_run_number}"
OBJ = f"""
apiVersion: twingate.com/v1beta
Expand Down Expand Up @@ -151,7 +151,9 @@ def test_connector_flowes_image_change(kopf_settings, kopf_runner_args, ci_run_n
assert runner.exit_code == 0


def test_pod_gone_while_operator_down(kopf_settings, kopf_runner_args, ci_run_number):
def test_connector_flows_pod_gone_while_operator_down(
kopf_settings, kopf_runner_args, ci_run_number
):
connector_name = f"test-connector-gone-{ci_run_number}"
OBJ = f"""
apiVersion: twingate.com/v1beta
Expand Down