pipekit/.archive/pre-rewrite/tui/client.py
Paul Trowbridge 574ada5258 Initial commit: Pipekit rewrite.
Orchestration layer around the jrunner Java JDBC CLI, replacing the
previous shell-based sync system in .archive/pre-rewrite. Includes
the FastAPI + Jinja web frontend, per-driver adapters (DB2, MSSQL,
PG), wizard-driven module creation with editable dest types and
source-sourced table/column descriptions, watermark/hook CRUD,
and the engine that runs modules end-to-end.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 00:38:26 -04:00

101 lines
4.7 KiB
Python

"""HTTP client for Pipekit API."""
import requests
from requests.auth import HTTPBasicAuth
class PipekitClient:
def __init__(self, base_url: str = "http://localhost:8100",
username: str = "admin", password: str = "pipekit"):
self.base_url = base_url.rstrip("/")
self.auth = HTTPBasicAuth(username, password)
def _get(self, path: str, params: dict = None) -> dict | list:
r = requests.get(f"{self.base_url}{path}", auth=self.auth, params=params)
r.raise_for_status()
return r.json()
def _post(self, path: str, json: dict = None) -> dict:
r = requests.post(f"{self.base_url}{path}", auth=self.auth, json=json)
r.raise_for_status()
return r.json()
def _put(self, path: str, json: dict = None) -> dict:
r = requests.put(f"{self.base_url}{path}", auth=self.auth, json=json)
r.raise_for_status()
return r.json()
def _delete(self, path: str) -> dict:
r = requests.delete(f"{self.base_url}{path}", auth=self.auth)
r.raise_for_status()
return r.json()
# Connections
def list_connections(self): return self._get("/connections")
def create_connection(self, data): return self._post("/connections", data)
def get_connection(self, id): return self._get(f"/connections/{id}")
def update_connection(self, id, data): return self._put(f"/connections/{id}", data)
def delete_connection(self, id): return self._delete(f"/connections/{id}")
def test_connection(self, id): return self._post(f"/connections/{id}/test")
# Introspection
def list_tables(self, conn_id, schema=None):
params = {"schema": schema} if schema else None
return self._get(f"/connections/{conn_id}/tables", params)
def list_columns(self, conn_id, schema, table):
return self._get(f"/connections/{conn_id}/tables/{schema}.{table}/columns")
def propose_module(self, conn_id, schema, table, dest_schema=None,
linked_server=None, linked_db=None):
params = {}
if dest_schema: params["dest_schema"] = dest_schema
if linked_server: params["linked_server"] = linked_server
if linked_db: params["linked_db"] = linked_db
return self._get(f"/connections/{conn_id}/tables/{schema}.{table}/propose", params or None)
# Modules
def list_modules(self): return self._get("/modules")
def create_module(self, data): return self._post("/modules", data)
def get_module(self, id): return self._get(f"/modules/{id}")
def update_module(self, id, data): return self._put(f"/modules/{id}", data)
def delete_module(self, id): return self._delete(f"/modules/{id}")
def preview_module(self, id): return self._get(f"/modules/{id}/preview")
def run_module(self, id): return self._post(f"/modules/{id}/run")
def run_module_stream(self, id):
"""Stream sync output. Yields lines, final line starts with __DONE__ or __ERROR__."""
r = requests.post(f"{self.base_url}/modules/{id}/run/stream",
auth=self.auth, stream=True)
r.raise_for_status()
for line in r.iter_lines(decode_unicode=True):
if line.startswith("data: "):
yield line[6:]
def module_history(self, id): return self._get(f"/modules/{id}/history")
# Hooks
def list_hooks(self, module_id): return self._get(f"/modules/{module_id}/hooks")
def create_hook(self, data): return self._post("/hooks", data)
def delete_hook(self, id): return self._delete(f"/hooks/{id}")
# Groups
def list_groups(self): return self._get("/groups")
def create_group(self, data): return self._post("/groups", data)
def get_group(self, id): return self._get(f"/groups/{id}")
def delete_group(self, id): return self._delete(f"/groups/{id}")
def add_group_member(self, group_id, data): return self._post(f"/groups/{group_id}/members", data)
def remove_group_member(self, member_id): return self._delete(f"/groups/members/{member_id}")
def run_group(self, id): return self._post(f"/groups/{id}/run")
# Runs
def list_runs(self, limit=50): return self._get("/runs", {"limit": limit})
def get_run(self, id): return self._get(f"/runs/{id}")
# Schedules
def list_schedules(self): return self._get("/schedules")
def create_schedule(self, data): return self._post("/schedules", data)
def update_schedule(self, id, data): return self._put(f"/schedules/{id}", data)
def delete_schedule(self, id): return self._delete(f"/schedules/{id}")
# Drivers
def list_drivers(self): return self._get("/drivers")
def create_driver(self, data): return self._post("/drivers", data)
def delete_driver(self, id): return self._delete(f"/drivers/{id}")