137 lines
4.4 KiB
Python
137 lines
4.4 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from ariadne.k8s import pods as pods_module
|
|
|
|
|
|
def test_parse_start_time_handles_missing_and_invalid_values() -> None:
|
|
assert pods_module._parse_start_time(None) == 0.0
|
|
assert pods_module._parse_start_time("not-a-date") == 0.0
|
|
|
|
|
|
def test_parse_start_time_defaults_naive_value_to_utc() -> None:
|
|
assert pods_module._parse_start_time("2026-01-20T00:00:00") > 0
|
|
|
|
|
|
def test_is_ready_handles_missing_conditions_and_non_ready_states() -> None:
|
|
assert pods_module._is_ready({"status": {"phase": "Pending"}}) is False
|
|
assert pods_module._is_ready({"status": {"phase": "Running", "conditions": "bad"}}) is False
|
|
assert pods_module._is_ready({"status": {"phase": "Running", "conditions": ["bad"]}}) is False
|
|
assert (
|
|
pods_module._is_ready(
|
|
{"status": {"phase": "Running", "conditions": [{"type": "Initialized", "status": "True"}]}}
|
|
)
|
|
is False
|
|
)
|
|
|
|
|
|
def test_list_pods_requires_namespace() -> None:
|
|
with pytest.raises(pods_module.PodSelectionError):
|
|
pods_module.list_pods("", "app=test")
|
|
|
|
|
|
def test_list_pods_encodes_selector(monkeypatch) -> None:
|
|
captured = {}
|
|
|
|
def fake_get_json(path: str):
|
|
captured["path"] = path
|
|
return {"items": []}
|
|
|
|
monkeypatch.setattr(pods_module, "get_json", fake_get_json)
|
|
pods_module.list_pods("demo", "app=nextcloud")
|
|
assert "labelSelector=app%3Dnextcloud" in captured["path"]
|
|
|
|
|
|
def test_list_pods_filters_non_dict_items(monkeypatch) -> None:
|
|
monkeypatch.setattr(pods_module, "get_json", lambda *_args, **_kwargs: {"items": [{}, "bad", 1]})
|
|
assert pods_module.list_pods("demo", "app=test") == [{}]
|
|
|
|
|
|
def test_select_pod_picks_ready_latest(monkeypatch) -> None:
|
|
payload = {
|
|
"items": [
|
|
{
|
|
"metadata": {"name": "old-pod"},
|
|
"status": {
|
|
"phase": "Running",
|
|
"startTime": "2026-01-19T00:00:00Z",
|
|
"conditions": [{"type": "Ready", "status": "True"}],
|
|
},
|
|
},
|
|
{
|
|
"metadata": {"name": "new-pod"},
|
|
"status": {
|
|
"phase": "Running",
|
|
"startTime": "2026-01-20T00:00:00Z",
|
|
"conditions": [{"type": "Ready", "status": "True"}],
|
|
},
|
|
},
|
|
]
|
|
}
|
|
|
|
monkeypatch.setattr(pods_module, "get_json", lambda *_args, **_kwargs: payload)
|
|
pod = pods_module.select_pod("demo", "app=test")
|
|
assert pod.name == "new-pod"
|
|
|
|
|
|
def test_select_pod_ignores_non_ready(monkeypatch) -> None:
|
|
payload = {
|
|
"items": [
|
|
{
|
|
"metadata": {"name": "pending"},
|
|
"status": {"phase": "Pending"},
|
|
},
|
|
]
|
|
}
|
|
monkeypatch.setattr(pods_module, "get_json", lambda *_args, **_kwargs: payload)
|
|
|
|
with pytest.raises(pods_module.PodSelectionError):
|
|
pods_module.select_pod("demo", "app=test")
|
|
|
|
|
|
def test_select_pod_skips_deleted_and_invalid_entries(monkeypatch) -> None:
|
|
payload = {
|
|
"items": [
|
|
{
|
|
"metadata": {"name": "deleting", "deletionTimestamp": "2026-01-20T00:00:00Z"},
|
|
"status": {
|
|
"phase": "Running",
|
|
"conditions": [{"type": "Ready", "status": "True"}],
|
|
},
|
|
},
|
|
{
|
|
"metadata": {"name": "chosen"},
|
|
"status": {
|
|
"phase": "Running",
|
|
"nodeName": "titan-24",
|
|
"startTime": "2026-01-20T00:00:00Z",
|
|
"conditions": [{"type": "Ready", "status": "True"}],
|
|
},
|
|
},
|
|
]
|
|
}
|
|
monkeypatch.setattr(pods_module, "get_json", lambda *_args, **_kwargs: payload)
|
|
|
|
pod = pods_module.select_pod("demo", "app=test")
|
|
assert pod.name == "chosen"
|
|
assert pod.node == "titan-24"
|
|
|
|
|
|
def test_select_pod_skips_blank_names(monkeypatch) -> None:
|
|
payload = {
|
|
"items": [
|
|
{
|
|
"metadata": {"name": " "},
|
|
"status": {
|
|
"phase": "Running",
|
|
"conditions": [{"type": "Ready", "status": "True"}],
|
|
},
|
|
}
|
|
]
|
|
}
|
|
monkeypatch.setattr(pods_module, "get_json", lambda *_args, **_kwargs: payload)
|
|
|
|
with pytest.raises(pods_module.PodSelectionError):
|
|
pods_module.select_pod("demo", "app=test")
|