Skip to content

Commit

Permalink
Handle various microcluster ready endpoints (#142)
Browse files Browse the repository at this point in the history
* Handle various microcluster ready endpoints

* Review comments
  • Loading branch information
addyess authored Aug 12, 2024
1 parent fd1d3b9 commit 113b69c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 4 deletions.
29 changes: 26 additions & 3 deletions charms/worker/k8s/lib/charms/k8s/v0/k8sd_api_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -776,9 +776,32 @@ def is_cluster_ready(self):
return status.metadata and status.metadata.status.ready

def check_k8sd_ready(self):
"""Check if k8sd is ready."""
endpoint = "/cluster/1.0/ready"
self._send_request(endpoint, "GET", EmptyResponse)
"""Check if k8sd is ready using various microcluster endpoints.
Raises:
K8sdConnectionError: If the response is Not Found on all endpoints.
"""
ready_endpoints = ["/core/1.0/ready", "/cluster/1.0/ready"]
for i, endpoint in enumerate(ready_endpoints):
try:
self._send_request(endpoint, "GET", EmptyResponse)
break
except InvalidResponseError as ex:
if ex.code == 404:
logger.warning(
"micro-cluster unavailable @ %s (%s of %s): %s",
endpoint,
i + 1,
len(ready_endpoints),
ex,
)
# Try the next endpoint if the current one is not found
continue
raise
else:
raise K8sdConnectionError(
"Exhausted all endpoints while checking if micro-cluster is ready"
)

def bootstrap_k8s_snap(self, request: CreateClusterRequest) -> None:
"""Bootstrap the k8s cluster.
Expand Down
51 changes: 50 additions & 1 deletion charms/worker/k8s/tests/unit/test_k8sd_api_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import socket
import unittest
from socket import AF_UNIX, SOCK_STREAM
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock, call, patch

from lib.charms.k8s.v0.k8sd_api_manager import (
AuthTokenResponse,
Expand Down Expand Up @@ -143,6 +143,55 @@ def setUp(self):
self.mock_factory = MagicMock()
self.api_manager = K8sdAPIManager(factory=self.mock_factory)

@patch("lib.charms.k8s.v0.k8sd_api_manager.K8sdAPIManager._send_request")
def test_check_k8sd_in_error(self, mock_send_request):
"""Test bootstrap."""
not_found = InvalidResponseError(code=404, msg="Not Found")
in_error = InvalidResponseError(code=504, msg="In Error")
mock_send_request.side_effect = [not_found, in_error]

with self.assertRaises(InvalidResponseError) as ie:
self.api_manager.check_k8sd_ready()
mock_send_request.assert_has_calls(
[
call("/core/1.0/ready", "GET", EmptyResponse),
call("/cluster/1.0/ready", "GET", EmptyResponse),
]
)
assert ie.exception.code == 504

@patch("lib.charms.k8s.v0.k8sd_api_manager.K8sdAPIManager._send_request")
def test_check_k8sd_not_found(self, mock_send_request):
"""Test bootstrap."""
not_found = InvalidResponseError(code=404, msg="Not Found")
mock_send_request.side_effect = [not_found, not_found]

with self.assertRaises(K8sdConnectionError):
self.api_manager.check_k8sd_ready()

mock_send_request.assert_has_calls(
[
call("/core/1.0/ready", "GET", EmptyResponse),
call("/cluster/1.0/ready", "GET", EmptyResponse),
]
)

@patch("lib.charms.k8s.v0.k8sd_api_manager.K8sdAPIManager._send_request")
def test_check_k8sd_ready(self, mock_send_request):
"""Test bootstrap."""
not_found = InvalidResponseError(code=404, msg="Not Found")
success = EmptyResponse(status_code=200, type="test", error_code=0)
mock_send_request.side_effect = [not_found, success]

self.api_manager.check_k8sd_ready()

mock_send_request.assert_has_calls(
[
call("/core/1.0/ready", "GET", EmptyResponse),
call("/cluster/1.0/ready", "GET", EmptyResponse),
]
)

@patch("lib.charms.k8s.v0.k8sd_api_manager.K8sdAPIManager._send_request")
def test_bootstrap_k8s_snap(self, mock_send_request):
"""Test bootstrap."""
Expand Down

0 comments on commit 113b69c

Please sign in to comment.