mirror of
https://github.com/Katakate/k7.git
synced 2026-09-21 17:43:20 +00:00
d65ea43536
See CHANGELOG.md for what shipped.
248 lines
10 KiB
Python
248 lines
10 KiB
Python
"""Unit tests for the Spec 10d ``k7 api ...`` sub-app + deprecation aliases.
|
|
|
|
Coverage:
|
|
|
|
- ``k7 api status / endpoint / enable / disable`` shell out to the right
|
|
kubectl commands and surface the standard error paths.
|
|
- ``k7 dev api rebuild`` is registered (hidden) and routes through the
|
|
rebuild path.
|
|
- The deprecated top-level commands (``start-api`` / ``stop-api`` /
|
|
``api-status`` / ``get-api-endpoint``) emit a stderr warning and
|
|
forward to the new home.
|
|
- ``k7 install --no-api`` passes ``k7_api_enabled=false`` into the
|
|
Ansible extra_vars (which is what the playbook actually keys off).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
from types import SimpleNamespace
|
|
from unittest.mock import patch
|
|
|
|
from typer.testing import CliRunner
|
|
|
|
from k7.cli.k7 import app
|
|
|
|
runner = CliRunner()
|
|
|
|
|
|
def _make_completed(stdout: str = "", stderr: str = "", returncode: int = 0) -> subprocess.CompletedProcess:
|
|
return subprocess.CompletedProcess(args=[], returncode=returncode, stdout=stdout, stderr=stderr)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# ``k7 api enable / disable``.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestApiEnableDisable:
|
|
def test_enable_calls_kubectl_scale_1(self):
|
|
with patch("k7.cli.k7.subprocess.run", return_value=_make_completed()) as run:
|
|
result = runner.invoke(app, ["api", "enable"])
|
|
assert result.exit_code == 0, result.output
|
|
# Find the scale call.
|
|
scale_calls = [c for c in run.call_args_list if "scale" in (c.args[0] if c.args else [])]
|
|
assert scale_calls, "expected at least one kubectl scale call"
|
|
cmd = scale_calls[0].args[0]
|
|
assert "deployment" in cmd
|
|
assert "k7-api" in cmd
|
|
assert "--replicas=1" in cmd
|
|
assert "enabled" in result.output.lower()
|
|
|
|
def test_disable_calls_kubectl_scale_0(self):
|
|
with patch("k7.cli.k7.subprocess.run", return_value=_make_completed()) as run:
|
|
result = runner.invoke(app, ["api", "disable"])
|
|
assert result.exit_code == 0, result.output
|
|
scale_calls = [c for c in run.call_args_list if "scale" in (c.args[0] if c.args else [])]
|
|
assert scale_calls
|
|
cmd = scale_calls[0].args[0]
|
|
assert "--replicas=0" in cmd
|
|
assert "disabled" in result.output.lower()
|
|
|
|
def test_enable_exits_nonzero_on_kubectl_failure(self):
|
|
with patch(
|
|
"k7.cli.k7.subprocess.run",
|
|
return_value=_make_completed(stderr="not found", returncode=1),
|
|
):
|
|
result = runner.invoke(app, ["api", "enable"])
|
|
assert result.exit_code != 0
|
|
assert "failed" in result.output.lower()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# ``k7 api status``.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestApiStatus:
|
|
def test_reports_running_when_replicas_ready(self):
|
|
# subprocess.run is called three times by api_status_cmd:
|
|
# 1) jsonpath get deployment → "1/1"
|
|
# 2) get pods -l app=k7-api → human-readable line
|
|
# 3) _read_api_endpoint -> get svc / get nodes (two calls inside)
|
|
calls = [
|
|
_make_completed(stdout="1/1"), # deployment readyReplicas/replicas
|
|
_make_completed(stdout="k7-api-abc 1/1 Running 0 1m k7-node-01"), # pods
|
|
_make_completed(stdout="31007"), # service nodePort
|
|
_make_completed(stdout='[{"type":"InternalIP","address":"10.0.0.1"}]'),
|
|
]
|
|
with patch("k7.cli.k7.subprocess.run", side_effect=calls):
|
|
result = runner.invoke(app, ["api", "status"])
|
|
assert result.exit_code == 0, result.output
|
|
assert "running" in result.output.lower()
|
|
assert "1/1" in result.output
|
|
|
|
def test_reports_disabled_when_replicas_zero(self):
|
|
calls = [_make_completed(stdout="0/0")]
|
|
# status_cmd may make more subprocess calls (pods/endpoint); pad with no-ops.
|
|
calls.extend(_make_completed(stdout="") for _ in range(5))
|
|
with patch("k7.cli.k7.subprocess.run", side_effect=calls):
|
|
result = runner.invoke(app, ["api", "status"])
|
|
assert result.exit_code == 0, result.output
|
|
assert "disabled" in result.output.lower() or "scaled to 0" in result.output.lower()
|
|
|
|
def test_reports_missing_when_deployment_absent(self):
|
|
with patch(
|
|
"k7.cli.k7.subprocess.run",
|
|
return_value=_make_completed(stderr="NotFound", returncode=1),
|
|
):
|
|
result = runner.invoke(app, ["api", "status"])
|
|
# status reports the problem but doesn't exit 1 — diagnostic only.
|
|
assert result.exit_code == 0
|
|
assert "not found" in result.output.lower()
|
|
assert "k7 install" in result.output
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# ``k7 api endpoint``.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestApiEndpoint:
|
|
def test_prints_url_when_service_exists(self):
|
|
with patch("k7.cli.k7._read_api_endpoint", return_value="http://10.0.0.1:31007"):
|
|
result = runner.invoke(app, ["api", "endpoint"])
|
|
assert result.exit_code == 0, result.output
|
|
assert result.output.strip() == "http://10.0.0.1:31007"
|
|
|
|
def test_exits_nonzero_when_service_missing(self):
|
|
with patch("k7.cli.k7._read_api_endpoint", return_value=None):
|
|
result = runner.invoke(app, ["api", "endpoint"])
|
|
assert result.exit_code != 0
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Deprecated command aliases.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestDeprecatedAliases:
|
|
def test_api_status_alias_warns_and_forwards(self):
|
|
# Calls subprocess.run several times under the hood; first call returns
|
|
# something that lets api_status_cmd produce output.
|
|
seq = [_make_completed(stdout="1/1")] + [_make_completed(stdout="") for _ in range(5)]
|
|
with patch("k7.cli.k7.subprocess.run", side_effect=seq):
|
|
result = runner.invoke(app, ["api-status"])
|
|
assert result.exit_code == 0
|
|
combined = result.output + (result.stderr or "")
|
|
assert "deprecated" in combined.lower()
|
|
assert "k7 api status" in combined
|
|
|
|
def test_get_api_endpoint_alias_warns_and_forwards(self):
|
|
with patch("k7.cli.k7._read_api_endpoint", return_value="http://x:31007"):
|
|
result = runner.invoke(app, ["get-api-endpoint"])
|
|
assert result.exit_code == 0
|
|
combined = result.output + (result.stderr or "")
|
|
assert "deprecated" in combined.lower()
|
|
assert "k7 api endpoint" in combined
|
|
assert "http://x:31007" in result.output
|
|
|
|
def test_stop_api_alias_warns_and_forwards_to_disable(self):
|
|
with patch("k7.cli.k7.subprocess.run", return_value=_make_completed()) as run:
|
|
result = runner.invoke(app, ["stop-api"])
|
|
assert result.exit_code == 0
|
|
combined = result.output + (result.stderr or "")
|
|
assert "deprecated" in combined.lower()
|
|
assert "k7 api disable" in combined
|
|
# The scale-to-0 call still went through.
|
|
scale_calls = [c for c in run.call_args_list if "--replicas=0" in (c.args[0] if c.args else [])]
|
|
assert scale_calls
|
|
|
|
def test_start_api_alias_warns_and_forwards_to_dev_rebuild(self):
|
|
# Avoid actually building Docker images: stub the build helper.
|
|
with (
|
|
patch("k7.cli.k7._build_and_import_api_image", return_value=False),
|
|
patch("k7.cli.k7.subprocess.run", return_value=_make_completed()),
|
|
):
|
|
result = runner.invoke(app, ["start-api"])
|
|
combined = result.output + (result.stderr or "")
|
|
assert "deprecated" in combined.lower()
|
|
assert "k7 dev api rebuild" in combined
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# ``k7 install --no-api`` passes the right extra var.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestInstallNoApi:
|
|
def test_install_no_api_passes_k7_api_enabled_false(self):
|
|
seen: dict = {}
|
|
|
|
def _capture(*args, **kwargs):
|
|
# ``K7Core.install_node`` is sync (it shells out to ansible-playbook).
|
|
seen["kwargs"] = kwargs
|
|
return SimpleNamespace(success=True, message="ok", error="")
|
|
|
|
with (
|
|
patch("k7.cli.k7.K7Core") as core_cls,
|
|
patch("k7.cli.k7._build_default_inventory", return_value="[k7_servers]\nhost ansible_host=1.2.3.4"),
|
|
):
|
|
core_cls.return_value.install_node = _capture
|
|
result = runner.invoke(app, ["install", "--no-api", "host"])
|
|
assert result.exit_code == 0, result.output
|
|
extra_vars = seen["kwargs"]["extra_vars"]
|
|
assert extra_vars.get("k7_api_enabled") == "false"
|
|
|
|
def test_install_without_flag_passes_k7_api_enabled_true(self):
|
|
seen: dict = {}
|
|
|
|
def _capture(*args, **kwargs):
|
|
seen["kwargs"] = kwargs
|
|
return SimpleNamespace(success=True, message="ok", error="")
|
|
|
|
with (
|
|
patch("k7.cli.k7.K7Core") as core_cls,
|
|
patch("k7.cli.k7._build_default_inventory", return_value="[k7_servers]\nhost ansible_host=1.2.3.4"),
|
|
):
|
|
core_cls.return_value.install_node = _capture
|
|
result = runner.invoke(app, ["install", "host"])
|
|
assert result.exit_code == 0, result.output
|
|
extra_vars = seen["kwargs"]["extra_vars"]
|
|
assert extra_vars.get("k7_api_enabled") == "true"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# ``k7 --help`` no longer lists the deprecated commands.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_top_level_help_hides_deprecated_commands():
|
|
result = runner.invoke(app, ["--help"])
|
|
assert result.exit_code == 0
|
|
for name in ("start-api", "stop-api", "api-status", "get-api-endpoint"):
|
|
assert name not in result.output, f"deprecated command {name!r} still appears in `k7 --help`"
|
|
|
|
|
|
def test_api_subapp_help_lists_new_commands():
|
|
result = runner.invoke(app, ["api", "--help"])
|
|
assert result.exit_code == 0
|
|
for name in ("status", "endpoint", "enable", "disable"):
|
|
assert name in result.output, f"missing `{name}` under `k7 api --help`"
|
|
|
|
|
|
def test_dev_api_subapp_help_lists_rebuild():
|
|
result = runner.invoke(app, ["dev", "api", "--help"])
|
|
assert result.exit_code == 0
|
|
assert "rebuild" in result.output
|