import argparse
import json
import sys
from pathlib import Path
from urllib import request, error
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("--config", required=True, help="Path to smoke test config JSON")
return parser.parse_args()
def load_config(config_path: Path):
with config_path.open("r", encoding="utf-8") as handle:
return json.load(handle)
def check_url(url: str, timeout: int):
req = request.Request(url, method="GET")
try:
with request.urlopen(req, timeout=timeout) as response:
return response.status, None
except error.HTTPError as exc:
return exc.code, str(exc)
except Exception as exc: # noqa: BLE001
return None, str(exc)
def main():
args = parse_args()
config_path = Path(args.config)
if not config_path.exists():
raise SystemExit(f"Config file not found: {config_path}")
config = load_config(config_path)
timeout = int(config.get("timeout_seconds", 10))
checks = config.get("checks", [])
if not checks:
print("No checks configured.")
return
failures = []
print("Smoke Test Results")
print("==================")
for check in checks:
name = check["name"]
url = check["url"]
status, err = check_url(url, timeout)
if status and 200 <= status < 400:
print(f"[PASS] {name}: {url} -> {status}")
else:
print(f"[FAIL] {name}: {url} -> {status or 'error'}")
if err:
print(f" {err}")
failures.append(name)
print()
print(f"Total checks: {len(checks)}")
print(f"Failures: {len(failures)}")
if failures:
sys.exit(1)
if __name__ == "__main__":
main()