Release v0.1.16
This commit is contained in:
@@ -14,6 +14,7 @@ from urllib.request import Request, urlopen
|
||||
|
||||
JsonObject = dict[str, Any]
|
||||
CommandRunner = Callable[[Sequence[str]], JsonObject]
|
||||
ActionRunner = Callable[[Sequence[str]], None]
|
||||
JsonFetcher = Callable[[str, str], JsonObject]
|
||||
|
||||
|
||||
@@ -26,11 +27,13 @@ def collect_kubernetes_evidence(
|
||||
exercise_api_pod_loss: bool = False,
|
||||
timeout_seconds: float = 180.0,
|
||||
command_runner: CommandRunner | None = None,
|
||||
action_runner: ActionRunner | None = None,
|
||||
json_fetcher: JsonFetcher | None = None,
|
||||
) -> JsonObject:
|
||||
"""Inspect a live cluster and optionally exercise one API pod replacement."""
|
||||
|
||||
run_json = command_runner or _kubectl_json
|
||||
run_action = action_runner or _kubectl_action
|
||||
fetch_json = json_fetcher or _fetch_json
|
||||
nodes = run_json(("get", "nodes", "-o", "json"))
|
||||
pods = run_json(
|
||||
@@ -76,6 +79,7 @@ def collect_kubernetes_evidence(
|
||||
initial_pods=pods,
|
||||
timeout_seconds=timeout_seconds,
|
||||
run_json=run_json,
|
||||
run_action=run_action,
|
||||
fetch_json=fetch_json,
|
||||
)
|
||||
evidence = {
|
||||
@@ -211,6 +215,7 @@ def _exercise_api_pod_loss(
|
||||
initial_pods: Mapping[str, Any],
|
||||
timeout_seconds: float,
|
||||
run_json: CommandRunner,
|
||||
run_action: ActionRunner,
|
||||
fetch_json: JsonFetcher,
|
||||
) -> JsonObject:
|
||||
candidates = [
|
||||
@@ -228,7 +233,7 @@ def _exercise_api_pod_loss(
|
||||
victim = sorted(candidates, key=lambda item: item["name"])[0]
|
||||
initial_uids = {item["uid"] for item in candidates}
|
||||
desired_ready = len(candidates)
|
||||
run_json(
|
||||
run_action(
|
||||
(
|
||||
"-n",
|
||||
namespace,
|
||||
@@ -236,8 +241,6 @@ def _exercise_api_pod_loss(
|
||||
"pod",
|
||||
victim["name"],
|
||||
"--wait=false",
|
||||
"-o",
|
||||
"json",
|
||||
)
|
||||
)
|
||||
deadline = time.monotonic() + timeout_seconds
|
||||
@@ -309,6 +312,22 @@ def _kubectl_json(arguments: Sequence[str]) -> JsonObject:
|
||||
return payload
|
||||
|
||||
|
||||
def _kubectl_action(arguments: Sequence[str]) -> None:
|
||||
kubectl = shutil.which("kubectl")
|
||||
if kubectl is None:
|
||||
raise ValueError("kubectl is required for Kubernetes evidence collection")
|
||||
result = subprocess.run(
|
||||
(kubectl, *arguments),
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=60,
|
||||
)
|
||||
if result.returncode:
|
||||
detail = result.stderr.strip() or result.stdout.strip()
|
||||
raise ValueError(f"kubectl failed: {detail}")
|
||||
|
||||
|
||||
def _fetch_json(url: str, api_key: str) -> JsonObject:
|
||||
request = Request(
|
||||
url,
|
||||
|
||||
Reference in New Issue
Block a user