test(ariadne): cover Kubernetes exec edges
This commit is contained in:
parent
dc4e76c90d
commit
4fec10d1ee
@ -9,10 +9,7 @@ try:
|
||||
from kubernetes import client, config
|
||||
from kubernetes.stream import stream
|
||||
except Exception as exc: # pragma: no cover - import checked at runtime
|
||||
client = None
|
||||
config = None
|
||||
stream = None
|
||||
_IMPORT_ERROR = exc
|
||||
client, config, stream, _IMPORT_ERROR = None, None, None, exc
|
||||
else:
|
||||
_IMPORT_ERROR = None
|
||||
|
||||
@ -72,13 +69,7 @@ class PodExecutor:
|
||||
self._label_selector = label_selector
|
||||
self._container = container
|
||||
|
||||
def exec(
|
||||
self,
|
||||
command: list[str] | str,
|
||||
env: dict[str, str] | None = None,
|
||||
timeout_sec: float | None = None,
|
||||
check: bool = True,
|
||||
) -> ExecResult:
|
||||
def exec(self, command: list[str] | str, env: dict[str, str] | None = None, timeout_sec: float | None = None, check: bool = True) -> ExecResult:
|
||||
pod = select_pod(self._namespace, self._label_selector)
|
||||
cmd = _build_command(command, env)
|
||||
api = _ensure_client()
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import builtins
|
||||
import importlib.util
|
||||
import sys
|
||||
import types
|
||||
|
||||
import pytest
|
||||
@ -57,11 +60,25 @@ class HangingStream(DummyStream):
|
||||
return False
|
||||
|
||||
|
||||
class ReturnCodeStream(DummyStream):
|
||||
def __init__(self):
|
||||
super().__init__(stdout="fallback", stderr="", exit_code=0)
|
||||
self.returncode = 7
|
||||
|
||||
def is_open(self) -> bool:
|
||||
return False
|
||||
|
||||
def peek_exit_code(self):
|
||||
raise AssertionError("closed streams should not read exit code")
|
||||
|
||||
|
||||
def test_build_command_wraps_env() -> None:
|
||||
cmd = _build_command(["echo", "hello"], {"FOO": "bar"})
|
||||
assert cmd[0] == "/bin/sh"
|
||||
assert "export FOO=bar" in cmd[2]
|
||||
|
||||
assert _build_command("echo hello", None) == ["/bin/sh", "-c", "echo hello"]
|
||||
|
||||
|
||||
def test_exec_returns_output(monkeypatch) -> None:
|
||||
monkeypatch.setattr(exec_module, "select_pod", lambda *_args, **_kwargs: PodRef("pod", "ns"))
|
||||
@ -94,6 +111,17 @@ def test_exec_times_out(monkeypatch) -> None:
|
||||
executor.exec(["sleep", "10"], timeout_sec=0.0, check=False)
|
||||
|
||||
|
||||
def test_exec_uses_returncode_when_stream_has_no_exit_code(monkeypatch) -> None:
|
||||
monkeypatch.setattr(exec_module, "select_pod", lambda *_args, **_kwargs: PodRef("pod", "ns"))
|
||||
monkeypatch.setattr(exec_module, "_ensure_client", lambda: types.SimpleNamespace(connect_get_namespaced_pod_exec=None))
|
||||
monkeypatch.setattr(exec_module, "stream", lambda *args, **kwargs: ReturnCodeStream())
|
||||
|
||||
result = PodExecutor("ns", "app=test", None).exec("echo ok", check=False)
|
||||
|
||||
assert result.exit_code == 7
|
||||
assert result.ok is False
|
||||
|
||||
|
||||
def test_ensure_client_fallback(monkeypatch) -> None:
|
||||
dummy_api = object()
|
||||
monkeypatch.setattr(exec_module, "_CORE_API", None)
|
||||
@ -115,3 +143,39 @@ def test_ensure_client_fallback(monkeypatch) -> None:
|
||||
monkeypatch.setattr(exec_module, "client", types.SimpleNamespace(CoreV1Api=lambda: dummy_api))
|
||||
|
||||
assert exec_module._ensure_client() is dummy_api
|
||||
|
||||
|
||||
def test_ensure_client_cached_and_import_error(monkeypatch) -> None:
|
||||
cached = object()
|
||||
monkeypatch.setattr(exec_module, "_IMPORT_ERROR", None)
|
||||
monkeypatch.setattr(exec_module, "_CORE_API", cached)
|
||||
assert exec_module._ensure_client() is cached
|
||||
|
||||
error = RuntimeError("missing kubernetes")
|
||||
monkeypatch.setattr(exec_module, "_IMPORT_ERROR", error)
|
||||
monkeypatch.setattr(exec_module, "_CORE_API", None)
|
||||
with pytest.raises(RuntimeError, match="kubernetes client missing"):
|
||||
exec_module._ensure_client()
|
||||
|
||||
|
||||
def test_exec_module_import_error_fallback(monkeypatch) -> None:
|
||||
real_import = builtins.__import__
|
||||
|
||||
def fake_import(name, globals=None, locals=None, fromlist=(), level=0):
|
||||
if name == "kubernetes" or name.startswith("kubernetes."):
|
||||
raise RuntimeError("kubernetes unavailable")
|
||||
return real_import(name, globals, locals, fromlist, level)
|
||||
|
||||
module_name = "ariadne.k8s.exec_import_failure_probe"
|
||||
spec = importlib.util.spec_from_file_location(module_name, exec_module.__file__)
|
||||
assert spec and spec.loader
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
monkeypatch.setattr(builtins, "__import__", fake_import)
|
||||
monkeypatch.setitem(sys.modules, module_name, module)
|
||||
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
assert module.client is None
|
||||
assert module.config is None
|
||||
assert module.stream is None
|
||||
assert isinstance(module._IMPORT_ERROR, RuntimeError)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user