From 36976a3876becfb0a818c64bfc7f15937fa1720b Mon Sep 17 00:00:00 2001 From: Mike Kell Date: Fri, 13 Jun 2025 12:32:16 +0000 Subject: [PATCH] feat: conditional Keycloak via compose profile + Makefile probe --- Makefile | 43 +++++++++++++++++++++++++++++---------- dev-compose.yaml | 52 +++++++++++++++++++++++++++++++++--------------- pytest.ini | 2 ++ 3 files changed, 70 insertions(+), 27 deletions(-) diff --git a/Makefile b/Makefile index ec631b1..db6e423 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,40 @@ +# Root Makefile for CMMC-Platform local dev + compose = podman-compose -f dev-compose.yaml -up: ## start local stack - $(compose) up -d +# ---------------------------------------------------------- +# Helpers +# ---------------------------------------------------------- +create-proxy-net: + @podman network exists nginx-proxy || podman network create nginx-proxy -down: ## stop stack - $(compose) down +# probe external Keycloak once and cache the flag +check-idp: + @echo "🔍 Probing $(KEYCLOAK_URL) for existing Keycloak..." + @if curl -sf "${KEYCLOAK_URL:-http://keycloak.local:8080}/realms/master" >/dev/null ; \ + then echo "🥳 External Keycloak detected!"; echo 1 >.idp_flag ; \ + else echo "🛠 No external Keycloak found."; echo 0 >.idp_flag ; fi -logs: ## follow logs - $(compose) logs -f - -build: ## build FastAPI image locally +# ---------------------------------------------------------- +# Lifecycle targets +# ---------------------------------------------------------- +build: ## Build FastAPI image podman build -t cmmc-fastapi:latest -f .container-images/fastapi.Dockerfile . -test: ## run pytest quietly - pytest -q +up: create-proxy-net check-idp ## Start stack (auto-starts Keycloak only if needed) + @if [ "`cat .idp_flag`" = "1" ]; then \ + $(compose) up -d ; \ + else \ + $(compose) --profile idp up -d ; \ + fi +down: ## Stop stack + $(compose) down -.PHONY: up down logs build test +logs: ## Tail logs + $(compose) logs -f + +test: ## Run pytest + PYTHONPATH=. pytest -q + +.PHONY: build up down logs test create-proxy-net check-idp diff --git a/dev-compose.yaml b/dev-compose.yaml index 4be5ca0..5b178db 100644 --- a/dev-compose.yaml +++ b/dev-compose.yaml @@ -3,7 +3,11 @@ version: "3.9" x-common-env: &common-env TZ: "UTC" +############################################################ +# SERVICES +############################################################ services: + # ────────────────────────────── kong: image: docker.io/library/kong:3.7 container_name: kong @@ -16,35 +20,51 @@ services: volumes: - ./kong/kong.yml:/config/kong.yml:ro ports: - - "8000:8000" # proxy - - "8001:8001" # admin api + - "8000:8000" # proxy (handy for localhost curl) + - "8001:8001" # admin + networks: [internal, nginx-proxy] + + # ────────────────────────────── + fastapi: + image: cmmc-fastapi:latest + container_name: fastapi + restart: unless-stopped + environment: + <<: *common-env + # Default to local container; overridden by external URL in Makefile/CI + KEYCLOAK_URL: "${KEYCLOAK_URL:-http://keycloak:8080}" + KEYCLOAK_REALM: "cmmc-platform-dev" + KEYCLOAK_CLIENT_ID: "frontend" + ports: + # keep reachable only from localhost, not LAN + - "127.0.0.1:8008:8000" networks: [internal] + # ────────────────────────────── + # Starts ONLY when profile `idp` is requested keycloak: image: quay.io/keycloak/keycloak:25.0.0 container_name: keycloak command: start-dev + profiles: ["idp"] # ← optional profile flag restart: unless-stopped environment: <<: *common-env KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin KC_PROXY_HEADERS: xforwarded - ports: - - "8080:8080" - networks: [internal] - - fastapi: - image: cmmc-fastapi:latest # built by CI or `make build` - container_name: fastapi - restart: unless-stopped - environment: - <<: *common-env - APP_ENV: dev - ports: - - "8008:8000" - networks: [internal] + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/realms/master"] + interval: 10s + retries: 5 + networks: [internal, nginx-proxy] +############################################################ +# NETWORKS +############################################################ networks: internal: driver: bridge + nginx-proxy: # external bridge Nginx-Proxy-Manager already uses + external: true + name: nginx-proxy diff --git a/pytest.ini b/pytest.ini index a635c5c..b5ad6b6 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,4 @@ [pytest] pythonpath = . +filterwarnings = + ignore:Please use `import python_multipart`:PendingDeprecationWarning