2026-01-19 19:01:32 -03:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2026-01-20 18:11:02 -03:00
|
|
|
import base64
|
2026-01-19 19:01:32 -03:00
|
|
|
import types
|
|
|
|
|
|
2026-01-20 18:11:02 -03:00
|
|
|
import pytest
|
|
|
|
|
|
2026-01-19 19:01:32 -03:00
|
|
|
import ariadne.k8s.client as k8s_client
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DummyResponse:
|
|
|
|
|
def __init__(self, payload):
|
|
|
|
|
self._payload = payload
|
|
|
|
|
|
|
|
|
|
def raise_for_status(self):
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def json(self):
|
|
|
|
|
return self._payload
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DummyClient:
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
self.calls = []
|
2026-01-20 18:11:02 -03:00
|
|
|
self.payload = {"ok": True}
|
2026-01-19 19:01:32 -03:00
|
|
|
|
|
|
|
|
def request(self, method, url, json=None):
|
|
|
|
|
self.calls.append((method, url, json))
|
2026-01-20 18:11:02 -03:00
|
|
|
return DummyResponse(self.payload)
|
2026-01-19 19:01:32 -03:00
|
|
|
|
|
|
|
|
def __enter__(self):
|
|
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
def __exit__(self, exc_type, exc, tb):
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_json_builds_url(monkeypatch) -> None:
|
|
|
|
|
dummy_settings = types.SimpleNamespace(k8s_api_timeout_sec=5.0)
|
|
|
|
|
monkeypatch.setattr(k8s_client, "settings", dummy_settings)
|
|
|
|
|
monkeypatch.setattr(k8s_client, "_read_service_account", lambda: ("token", "/tmp/ca"))
|
2026-01-20 18:11:02 -03:00
|
|
|
client = DummyClient()
|
|
|
|
|
monkeypatch.setattr(k8s_client.httpx, "Client", lambda *args, **kwargs: client)
|
2026-01-19 19:01:32 -03:00
|
|
|
|
|
|
|
|
result = k8s_client.get_json("/api/test")
|
|
|
|
|
assert result == {"ok": True}
|
2026-01-20 18:11:02 -03:00
|
|
|
assert client.calls[0][1].endswith("/api/test")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_post_json_rejects_non_dict(monkeypatch) -> None:
|
|
|
|
|
dummy_settings = types.SimpleNamespace(k8s_api_timeout_sec=5.0)
|
|
|
|
|
monkeypatch.setattr(k8s_client, "settings", dummy_settings)
|
|
|
|
|
monkeypatch.setattr(k8s_client, "_read_service_account", lambda: ("token", "/tmp/ca"))
|
|
|
|
|
client = DummyClient()
|
|
|
|
|
client.payload = ["bad"]
|
|
|
|
|
monkeypatch.setattr(k8s_client.httpx, "Client", lambda *args, **kwargs: client)
|
|
|
|
|
|
|
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
|
k8s_client.post_json("/api/test", {"payload": "ok"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_post_json_success(monkeypatch) -> None:
|
|
|
|
|
dummy_settings = types.SimpleNamespace(k8s_api_timeout_sec=5.0)
|
|
|
|
|
monkeypatch.setattr(k8s_client, "settings", dummy_settings)
|
|
|
|
|
monkeypatch.setattr(k8s_client, "_read_service_account", lambda: ("token", "/tmp/ca"))
|
|
|
|
|
client = DummyClient()
|
|
|
|
|
monkeypatch.setattr(k8s_client.httpx, "Client", lambda *args, **kwargs: client)
|
|
|
|
|
|
|
|
|
|
result = k8s_client.post_json("/api/test", {"payload": "ok"})
|
|
|
|
|
assert result == {"ok": True}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_json_rejects_non_dict(monkeypatch) -> None:
|
|
|
|
|
dummy_settings = types.SimpleNamespace(k8s_api_timeout_sec=5.0)
|
|
|
|
|
monkeypatch.setattr(k8s_client, "settings", dummy_settings)
|
|
|
|
|
monkeypatch.setattr(k8s_client, "_read_service_account", lambda: ("token", "/tmp/ca"))
|
|
|
|
|
client = DummyClient()
|
|
|
|
|
client.payload = ["bad"]
|
|
|
|
|
monkeypatch.setattr(k8s_client.httpx, "Client", lambda *args, **kwargs: client)
|
|
|
|
|
|
|
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
|
k8s_client.get_json("/api/test")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_read_service_account(monkeypatch, tmp_path) -> None:
|
|
|
|
|
sa_dir = tmp_path / "sa"
|
|
|
|
|
sa_dir.mkdir()
|
|
|
|
|
(sa_dir / "token").write_text("token123")
|
|
|
|
|
(sa_dir / "ca.crt").write_text("ca")
|
|
|
|
|
monkeypatch.setattr(k8s_client, "_SA_PATH", sa_dir)
|
|
|
|
|
|
|
|
|
|
token, ca_path = k8s_client._read_service_account()
|
|
|
|
|
assert token == "token123"
|
|
|
|
|
assert ca_path.endswith("ca.crt")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_read_service_account_missing_files(monkeypatch, tmp_path) -> None:
|
|
|
|
|
sa_dir = tmp_path / "sa"
|
|
|
|
|
sa_dir.mkdir()
|
|
|
|
|
monkeypatch.setattr(k8s_client, "_SA_PATH", sa_dir)
|
|
|
|
|
|
|
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
|
k8s_client._read_service_account()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_read_service_account_empty_token(monkeypatch, tmp_path) -> None:
|
|
|
|
|
sa_dir = tmp_path / "sa"
|
|
|
|
|
sa_dir.mkdir()
|
|
|
|
|
(sa_dir / "token").write_text("")
|
|
|
|
|
(sa_dir / "ca.crt").write_text("ca")
|
|
|
|
|
monkeypatch.setattr(k8s_client, "_SA_PATH", sa_dir)
|
|
|
|
|
|
|
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
|
k8s_client._read_service_account()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_secret_value_decodes(monkeypatch) -> None:
|
|
|
|
|
secret = base64.b64encode(b"secret").decode()
|
|
|
|
|
monkeypatch.setattr(k8s_client, "get_json", lambda *args, **kwargs: {"data": {"key": secret}})
|
|
|
|
|
|
|
|
|
|
assert k8s_client.get_secret_value("ns", "name", "key") == "secret"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_secret_value_missing(monkeypatch) -> None:
|
|
|
|
|
monkeypatch.setattr(k8s_client, "get_json", lambda *args, **kwargs: {"data": {}})
|
|
|
|
|
|
|
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
|
k8s_client.get_secret_value("ns", "name", "key")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_secret_value_decode_error(monkeypatch) -> None:
|
|
|
|
|
monkeypatch.setattr(k8s_client, "get_json", lambda *args, **kwargs: {"data": {"key": "bad"}})
|
|
|
|
|
monkeypatch.setattr(k8s_client.base64, "b64decode", lambda *_args, **_kwargs: (_ for _ in ()).throw(ValueError("bad")))
|
|
|
|
|
|
|
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
|
k8s_client.get_secret_value("ns", "name", "key")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_secret_value_empty_decoded(monkeypatch) -> None:
|
|
|
|
|
raw = base64.b64encode(b" ").decode()
|
|
|
|
|
monkeypatch.setattr(k8s_client, "get_json", lambda *args, **kwargs: {"data": {"key": raw}})
|
|
|
|
|
|
|
|
|
|
with pytest.raises(RuntimeError):
|
|
|
|
|
k8s_client.get_secret_value("ns", "name", "key")
|