add fixture-invoicing example, sample-room wrap, kind cluster support
- examples/fixture-invoicing/: FastAPI + Vue + Postgres demo (4-entity invoice fixture)
- cfg/sample/: wraps the fixture (managed.repos points at examples/)
- ctrl/kind-{up,down,status}.sh + per-room k8s render in soleprint/ctrl/k8s/
- build.py: relative repo paths, resilient rmtree, optional k8s render hook
- cfg/.gitignore: stop ignoring sample/ and standalone/ template rooms
Manifests render cleanly but kind cluster has not been run end-to-end yet.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
15
cfg/sample/link/Dockerfile
Normal file
15
cfg/sample/link/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libpq-dev gcc \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE 8000
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
||||
0
cfg/sample/link/adapters/__init__.py
Normal file
0
cfg/sample/link/adapters/__init__.py
Normal file
43
cfg/sample/link/adapters/sqlalchemy_bridge.py
Normal file
43
cfg/sample/link/adapters/sqlalchemy_bridge.py
Normal file
@@ -0,0 +1,43 @@
|
||||
"""SQLAlchemy bridge — read tables via reflection.
|
||||
|
||||
Works against the fixture's postgres. Reflection means the link does not
|
||||
need to import the app's model code — it discovers tables at runtime.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from sqlalchemy import MetaData, create_engine, inspect, select
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
def _db_url() -> str:
|
||||
host = os.getenv("DB_HOST", "db")
|
||||
port = os.getenv("DB_PORT", "5432")
|
||||
name = os.getenv("DB_NAME", "fixture")
|
||||
user = os.getenv("DB_USER", "postgres")
|
||||
password = os.getenv("DB_PASSWORD", "localdev123")
|
||||
return f"postgresql+psycopg2://{user}:{password}@{host}:{port}/{name}"
|
||||
|
||||
|
||||
engine = create_engine(_db_url(), future=True)
|
||||
metadata = MetaData()
|
||||
|
||||
|
||||
@router.get("/tables")
|
||||
def list_tables():
|
||||
insp = inspect(engine)
|
||||
return {"tables": insp.get_table_names()}
|
||||
|
||||
|
||||
@router.get("/tables/{name}")
|
||||
def table_rows(name: str, limit: int = 50):
|
||||
insp = inspect(engine)
|
||||
if name not in insp.get_table_names():
|
||||
raise HTTPException(404, f"table '{name}' not found")
|
||||
metadata.reflect(bind=engine, only=[name])
|
||||
table = metadata.tables[name]
|
||||
with engine.connect() as conn:
|
||||
rows = conn.execute(select(table).limit(limit)).mappings().all()
|
||||
return {"table": name, "rows": [dict(r) for r in rows]}
|
||||
24
cfg/sample/link/docker-compose.yml
Normal file
24
cfg/sample/link/docker-compose.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
# Link — Fixture DB bridge
|
||||
name: ${DEPLOYMENT_NAME}_link
|
||||
|
||||
services:
|
||||
link:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: ${DEPLOYMENT_NAME}_link
|
||||
environment:
|
||||
DB_HOST: db
|
||||
DB_PORT: 5432
|
||||
DB_NAME: ${POSTGRES_DB}
|
||||
DB_USER: ${POSTGRES_USER}
|
||||
DB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
ports:
|
||||
- "${LINK_PORT:-8121}:8000"
|
||||
networks:
|
||||
- default
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: ${NETWORK_NAME}
|
||||
19
cfg/sample/link/main.py
Normal file
19
cfg/sample/link/main.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""Link — DB bridge for the fixture invoicing app.
|
||||
|
||||
Exposes a small HTTP API that wraps SQLAlchemy access to the fixture's
|
||||
postgres so soleprint tools can read/write without touching the app.
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
from adapters.sqlalchemy_bridge import router as db_router
|
||||
|
||||
app = FastAPI(title="Link — Fixture Bridge")
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health():
|
||||
return {"status": "ok", "target": "fixture-invoicing"}
|
||||
|
||||
|
||||
app.include_router(db_router, prefix="/db")
|
||||
4
cfg/sample/link/requirements.txt
Normal file
4
cfg/sample/link/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
fastapi==0.115.0
|
||||
uvicorn[standard]==0.32.0
|
||||
sqlalchemy==2.0.36
|
||||
psycopg2-binary==2.9.10
|
||||
Reference in New Issue
Block a user