diff --git a/pykube/http.py b/pykube/http.py index 7acbb7f..bd14aaf 100644 --- a/pykube/http.py +++ b/pykube/http.py @@ -5,7 +5,6 @@ import datetime import json import posixpath -import re import shlex import subprocess @@ -23,10 +22,11 @@ from .exceptions import HTTPError from .utils import jsonpath_installed, jsonpath_parse +from .config import KubeConfig from . import __version__ -_ipv4_re = re.compile(r"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$") +DEFAULT_HTTP_TIMEOUT = 10 # seconds class KubernetesHTTPAdapter(requests.adapters.HTTPAdapter): @@ -35,7 +35,7 @@ class KubernetesHTTPAdapter(requests.adapters.HTTPAdapter): # it can be overwritten in unit tests to mock the actual HTTP calls _do_send = requests.adapters.HTTPAdapter.send - def __init__(self, kube_config, **kwargs): + def __init__(self, kube_config: KubeConfig, **kwargs): self.kube_config = kube_config super().__init__(**kwargs) @@ -150,7 +150,7 @@ class HTTPClient(object): Client for interfacing with the Kubernetes API. """ - def __init__(self, config): + def __init__(self, config: KubeConfig, timeout: float = DEFAULT_HTTP_TIMEOUT): """ Creates a new instance of the HTTPClient. @@ -158,6 +158,7 @@ def __init__(self, config): - `config`: The configuration instance """ self.config = config + self.timeout = timeout self.url = self.config.cluster["server"] session = requests.Session() @@ -193,7 +194,7 @@ def resource_list(self, api_version): setattr(self, cached_attr, r.json()) return getattr(self, cached_attr) - def get_kwargs(self, **kwargs): + def get_kwargs(self, **kwargs) -> dict: """ Creates a full URL to request based on arguments. @@ -228,6 +229,9 @@ def get_kwargs(self, **kwargs): url = url[1:] bits.append(url) kwargs["url"] = self.url + posixpath.join(*bits) + if 'timeout' not in kwargs: + # apply default HTTP timeout + kwargs['timeout'] = self.timeout return kwargs def raise_for_status(self, resp): diff --git a/tests/test_http.py b/tests/test_http.py index 88163af..5101192 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -8,7 +8,7 @@ from unittest.mock import MagicMock from pykube import __version__ -from pykube.http import HTTPClient +from pykube.http import HTTPClient, DEFAULT_HTTP_TIMEOUT from pykube.config import KubeConfig GOOD_CONFIG_FILE_PATH = os.path.sep.join(["tests", "test_config_with_context.yaml"]) @@ -16,15 +16,17 @@ def test_http(monkeypatch): cfg = KubeConfig.from_file(GOOD_CONFIG_FILE_PATH) - session = HTTPClient(cfg).session + api = HTTPClient(cfg) mock_send = MagicMock() mock_send.side_effect = Exception('MOCK HTTP') monkeypatch.setattr('pykube.http.KubernetesHTTPAdapter._do_send', mock_send) with pytest.raises(Exception): - session.get('http://localhost:9090/test') + api.get(url='test') mock_send.assert_called_once() assert mock_send.call_args[0][0].headers['Authorization'] == 'Basic YWRtOnNvbWVwYXNzd29yZA==' assert mock_send.call_args[0][0].headers['User-Agent'] == f'pykube-ng/{__version__}' + # check that the default HTTP timeout was set + assert mock_send.call_args[1]['timeout'] == DEFAULT_HTTP_TIMEOUT