Skip to content

Commit

Permalink
Add retry for api_request() call (#2240)
Browse files Browse the repository at this point in the history
* Add retry for api_request() call

* add optional retry_params to pass timeout and sleep_time

* updates based on review comments

* updates based on review comments

* fix missing default value

* move default retry params to where they are used

* Add typing
  • Loading branch information
dbasunag authored Jan 5, 2025
1 parent 0d654cd commit 71ccf67
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 14 deletions.
31 changes: 23 additions & 8 deletions ocp_resources/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
TIMEOUT_10SEC,
TIMEOUT_30SEC,
TIMEOUT_5SEC,
TIMEOUT_1SEC,
)
from ocp_resources.event import Event
from timeout_sampler import (
Expand Down Expand Up @@ -1059,27 +1060,41 @@ def wait_for_condition(self, condition: str, status: str, timeout: int = 300) ->
if cond["type"] == condition and cond["status"] == status:
return

def api_request(self, method: str, action: str, url: str, **params: Any) -> dict[str, Any]:
def api_request(
self, method: str, action: str, url: str, retry_params: dict[str, int] | None = None, **params: Any
) -> dict[str, Any]:
"""
Handle API requests to resource.
Args:
method (str): Request method (GET/PUT etc.).
action (str): Action to perform (stop/start/guestosinfo etc.).
url (str): URL of resource.
retry_params (dict): dict of timeout and sleep_time values for retrying the api request call
Returns:
data(dict): response data
"""
client: DynamicClient = self.client
response = client.client.request(
method=method,
url=f"{url}/{action}",
headers=client.client.configuration.api_key,
**params,
)

api_request_params = {
"url": f"{url}/{action}",
"method": method,
"headers": client.client.configuration.api_key,
}
if retry_params:
response = self.retry_cluster_exceptions(
func=client.client.request,
timeout=retry_params.get("timeout", TIMEOUT_10SEC),
sleep_time=retry_params.get("sleep_time", TIMEOUT_1SEC),
**api_request_params,
**params,
)
else:
response = client.client.request(
**api_request_params,
**params,
)
try:
return json.loads(response.data)
except json.decoder.JSONDecodeError:
Expand Down
1 change: 1 addition & 0 deletions ocp_resources/utils/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
PROTOCOL_ERROR_EXCEPTION_DICT: Dict[type[Exception], List[str]] = {ProtocolError: []}
NOT_FOUND_ERROR_EXCEPTION_DICT: Dict[type[Exception], List[str]] = {NotFoundError: []}

TIMEOUT_1SEC: int = 1
TIMEOUT_5SEC: int = 5
TIMEOUT_10SEC: int = 10
TIMEOUT_30SEC: int = 30
Expand Down
18 changes: 15 additions & 3 deletions ocp_resources/virtual_machine.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# -*- coding: utf-8 -*-
from __future__ import annotations
from typing import Any


from ocp_resources.utils.constants import (
DEFAULT_CLUSTER_RETRY_EXCEPTIONS,
PROTOCOL_ERROR_EXCEPTION_DICT,
TIMEOUT_4MINUTES,
TIMEOUT_30SEC,
TIMEOUT_5SEC,
)
from ocp_resources.resource import NamespacedResource
from timeout_sampler import TimeoutSampler
Expand Down Expand Up @@ -70,8 +73,17 @@ def _subresource_api_url(self):
f"namespaces/{self.namespace}/virtualmachines/{self.name}"
)

def api_request(self, method, action, **params):
return super().api_request(method=method, action=action, url=self._subresource_api_url, **params)
def api_request(
self, method: str, action: str, url: str = "", retry_params: dict[str, int] | None = None, **params: Any
) -> dict[str, Any]:
default_vm_api_request_retry_params: dict[str, int] = {"timeout": TIMEOUT_30SEC, "sleep_time": TIMEOUT_5SEC}
return super().api_request(
method=method,
action=action,
url=url or self._subresource_api_url,
retry_params=retry_params or default_vm_api_request_retry_params,
**params,
)

def to_dict(self) -> None:
super().to_dict()
Expand Down
17 changes: 14 additions & 3 deletions ocp_resources/virtual_machine_instance.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from __future__ import annotations
import shlex
from typing import Any

import xmltodict
from kubernetes.dynamic.exceptions import ResourceNotFoundError

from ocp_resources.utils.constants import PROTOCOL_ERROR_EXCEPTION_DICT, TIMEOUT_4MINUTES
from ocp_resources.utils.constants import PROTOCOL_ERROR_EXCEPTION_DICT, TIMEOUT_4MINUTES, TIMEOUT_30SEC, TIMEOUT_5SEC
from ocp_resources.node import Node
from ocp_resources.pod import Pod
from ocp_resources.resource import NamespacedResource
Expand Down Expand Up @@ -47,8 +49,17 @@ def _subresource_api_url(self):
f"namespaces/{self.namespace}/virtualmachineinstances/{self.name}"
)

def api_request(self, method, action, **params):
return super().api_request(method=method, action=action, url=self._subresource_api_url, **params)
def api_request(
self, method: str, action: str, url: str = "", retry_params: dict[str, int] | None = None, **params: Any
) -> dict[str, Any]:
default_vmi_api_request_retry_params: dict[str, int] = {"timeout": TIMEOUT_30SEC, "sleep_time": TIMEOUT_5SEC}
return super().api_request(
method=method,
action=action,
url=url or self._subresource_api_url,
retry_params=retry_params or default_vmi_api_request_retry_params,
**params,
)

def pause(self, timeout=TIMEOUT_4MINUTES, wait=False):
self.api_request(method="PUT", action="pause")
Expand Down

0 comments on commit 71ccf67

Please sign in to comment.