Files
hse-2026/materials/07-naming-lookup/seminar/consul/client.py
T
2026-10-21 23:03:28 +03:00

68 lines
2.2 KiB
Python

"""Discover instances, save one address, and compare cached/fresh requests."""
import argparse
import json
from pathlib import Path
import sys
import time
from urllib.request import urlopen
BASE = "http://consul:8500"
CACHE = Path("/work/consul-address.json")
def get(url):
with urlopen(url, timeout=2) as response:
return json.load(response)
def discover():
rows = get(BASE + "/v1/health/service/orders?passing=true")
return sorted([{"id": r["Service"]["ID"], "address": r["Service"]["Address"],
"port": r["Service"]["Port"]} for r in rows], key=lambda r: r["id"])
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("action", choices=["list", "save", "cached", "fresh", "wait"])
parser.add_argument("--ids", default="app-a,app-b", help="Expected passing IDs for wait")
args = parser.parse_args()
if args.action == "wait":
expected = sorted(args.ids.split(","))
deadline = time.monotonic() + 30
while time.monotonic() < deadline:
try:
rows = discover()
if [r["id"] for r in rows] == expected:
print(json.dumps(rows, indent=2))
return
except OSError:
pass
time.sleep(0.5)
raise RuntimeError("Passing instances did not reach " + str(expected))
if args.action == "list":
print(json.dumps(discover(), indent=2))
return
if args.action == "cached":
endpoint = json.loads(CACHE.read_text())
else:
rows = discover()
if not rows:
raise RuntimeError("No passing instances")
endpoint = rows[0]
if args.action == "save":
CACHE.parent.mkdir(parents=True, exist_ok=True)
CACHE.write_text(json.dumps(endpoint), encoding="utf-8")
print("SAVED", endpoint)
return
url = f"http://{endpoint['address']}:{endpoint['port']}/"
print(("CACHED" if args.action == "cached" else "FRESH"), endpoint["id"], url, flush=True)
print(json.dumps(get(url), indent=2))
if __name__ == "__main__":
try:
main()
except (OSError, ValueError, RuntimeError) as error:
print("REQUEST FAILED:", error, file=sys.stderr)
sys.exit(1)