refactor: full-stack restructure with multi-tenancy, workspace management, and K8s diagnostics
- Add Workspace domain (entity, repository, service, handler, DTO) - Add multi-tenant K8s client with tenant binding and quota management - Add K8s diagnostics client (instance diagnostics) - Add authorization middleware (authz package) - Restructure frontend to feature-based architecture (features/) - Add User Management page in configuration - Add AccessDenied page and route guards - Refactor shared components (form inputs, layout, UI) - Update Tailwind config for new design system - Add comprehensive documentation (docs/, tasks/, plans) - Improve cluster service with better kubeconfig handling - Add tests for crypto, config, helm client, tenant binding
This commit is contained in:
77
test/chart_values_yaml_api_contract.py
Normal file
77
test/chart_values_yaml_api_contract.py
Normal file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
# Covers Harbor Helm chart defaults retrieval: authenticate as admin, locate an
|
||||
# available registry, fetch charts/nginx:22.1.1 values-yaml, and assert the
|
||||
# response is the top-level chart values.yaml rather than a dependency values file.
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from urllib.error import HTTPError, URLError
|
||||
from urllib.parse import quote
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
|
||||
BASE_URL = os.environ.get("BASE_URL", "http://localhost:18081/api/v1").rstrip("/")
|
||||
ADMIN_USER = os.environ.get("ADMIN_USER", os.environ.get("BOOTSTRAP_ADMIN_USER", "admin"))
|
||||
ADMIN_PASS = os.environ.get("ADMIN_PASS", os.environ.get("BOOTSTRAP_ADMIN_PASS", ""))
|
||||
|
||||
|
||||
def request(method: str, path: str, token: str | None = None, payload=None):
|
||||
headers = {"Accept": "application/json"}
|
||||
data = None
|
||||
if payload is not None:
|
||||
headers["Content-Type"] = "application/json"
|
||||
data = json.dumps(payload).encode("utf-8")
|
||||
if token:
|
||||
headers["Authorization"] = f"Bearer {token}"
|
||||
req = Request(BASE_URL + path, data=data, headers=headers, method=method)
|
||||
try:
|
||||
with urlopen(req, timeout=60) as res:
|
||||
body = res.read().decode("utf-8", errors="replace")
|
||||
return res.status, json.loads(body) if body else None, body
|
||||
except HTTPError as exc:
|
||||
body = exc.read().decode("utf-8", errors="replace")
|
||||
try:
|
||||
parsed = json.loads(body) if body else None
|
||||
except json.JSONDecodeError:
|
||||
parsed = None
|
||||
return exc.code, parsed, body
|
||||
except URLError as exc:
|
||||
print(f"FAIL: cannot reach {BASE_URL}: {exc}", file=sys.stderr)
|
||||
return 1, None, str(exc)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if not ADMIN_PASS:
|
||||
print("SKIP: ADMIN_PASS or BOOTSTRAP_ADMIN_PASS is required")
|
||||
return 77
|
||||
status, auth, body = request("POST", "/auth/login", payload={"username": ADMIN_USER, "password": ADMIN_PASS})
|
||||
if status != 200 or not isinstance(auth, dict):
|
||||
print(f"FAIL: admin login failed HTTP {status}: {body[:300]}", file=sys.stderr)
|
||||
return 1
|
||||
token = auth["accessToken"]
|
||||
status, registries, body = request("GET", "/registries", token)
|
||||
if status != 200 or not isinstance(registries, list) or not registries:
|
||||
print(f"SKIP: no registries available for values-yaml contract: HTTP {status}")
|
||||
return 77
|
||||
registry_id = registries[0]["id"]
|
||||
repository = "charts/nginx"
|
||||
reference = "22.1.1"
|
||||
path = f"/registries/{registry_id}/repositories/{quote(repository, safe='')}/artifacts/{quote(reference, safe='')}/values-yaml"
|
||||
status, response, body = request("GET", path, token)
|
||||
if status != 200 or not isinstance(response, dict):
|
||||
print(f"FAIL: values-yaml returned HTTP {status}: {body[:300]}", file=sys.stderr)
|
||||
return 1
|
||||
values_yaml = response.get("valuesYaml", "")
|
||||
if len(values_yaml) < 10_000 or "global:" not in values_yaml or "image:" not in values_yaml or "service:" not in values_yaml:
|
||||
print("FAIL: values-yaml did not look like the top-level nginx chart values.yaml", file=sys.stderr)
|
||||
return 1
|
||||
if "exampleValue: common-chart" in values_yaml[:1000]:
|
||||
print("FAIL: values-yaml returned dependency chart values instead of top-level chart values", file=sys.stderr)
|
||||
return 1
|
||||
print("PASS: chart values-yaml API contract")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user