Adaptive API
The Adaptive API Gateway enables on-the-fly API extensibility in airgapped environments. Deploy new APIs via ConfigMaps without rebuilding Docker images.
Overview
The /api/adaptive endpoint provides a dynamic API gateway that supports:
-
Auto-generation of working endpoints from OpenAPI 3.0 specifications
-
Hot-reload of new APIs via ConfigMaps (no pod restart required)
-
Custom Python handler injection for business logic
-
Integration with SDL Swagger UI
-
Full CRUD support (GET, POST, PUT, DELETE, PATCH)
How It Works
The Adaptive API Gateway uses a two-phase approach:
Phase 1: OpenAPI Spec (Auto-Generated Endpoints)
Create an OpenAPI 3.0 specification and deploy it as a ConfigMap. The gateway automatically generates working endpoints that return example data from the spec.
Use cases:
-
API design and prototyping
-
Frontend development (mock backend)
-
Contract-first development
-
API documentation
Authentication
|
Authentication is handled by the SDL API Gateway, not by the Adaptive API itself. The Adaptive API requires sdl-api to be deployed as an upstream dependency. |
All requests to /api/adaptive/* are routed through the SDL API Gateway, which enforces authentication using:
-
Basic Auth (
df_basic): Username/password authentication -
Bearer JWT (
df_bearer_jwt): JWT tokens from Keycloak
# Using Basic Auth
curl -u username:password https://localhost/api/adaptive/my-api/endpoint
# Using Bearer Token
curl -H "Authorization: Bearer $TOKEN" https://localhost/api/adaptive/my-api/endpoint
Swagger UI Authentication
-
Click the Authorize button (lock icon)
-
Choose authentication method:
-
df_basic: Enter username and password
-
df_bearer_jwt: Enter JWT token from Keycloak
-
-
Click Authorize
-
All "Try it out" requests will include authentication
| The security schemes in Swagger UI are for documentation purposes. Actual authentication enforcement happens at the SDL API Gateway layer. |
Direct Access
When accessing the Adaptive API service directly (bypassing the SDL API Gateway), no authentication is enforced. This is intended for:
-
Kubernetes health probes
-
Internal service-to-service communication
-
Development and testing environments
For production deployments, always access through the SDL API Gateway.
Quick Start
See Adaptive API Quick Start for a complete example of deploying a Library API with both auto-generated and custom endpoints.
Gateway Endpoints
Documentation
-
GET /api/adaptive/swagger-ui/- Interactive Swagger UI documentation -
GET /api/adaptive/openapi.json- OpenAPI 3.0 schema
Management
-
GET /api/adaptive/- Gateway information and endpoint listing -
GET /api/adaptive/actuator/health/liveness- Kubernetes liveness probe -
GET /api/adaptive/actuator/health/readiness- Kubernetes readiness probe -
GET /api/adaptive/actuator/info- Application information (requires auth) -
POST /api/adaptive/actuator/refresh- Hot-reload routes and handlers (requires auth)
Adding New APIs
Option 1: OpenAPI Spec Only (Auto-Generated)
Perfect for API design, prototyping, and frontend development.
-
Create your OpenAPI 3.0 specification
-
Deploy as ConfigMap
-
Gateway auto-generates working endpoints
-
Returns example data from spec
# Create ConfigMap with your spec
kubectl get configmap df-adaptive-api-sample-specs -n svraft \
-o jsonpath='{.data.sample-crud\.openapi\.yaml}' > /tmp/existing-spec.yaml
kubectl create configmap df-adaptive-api-sample-specs \
--from-file=sample-crud.openapi.yaml=/tmp/existing-spec.yaml \
--from-file=my-api.openapi.yaml=/tmp/my-api.openapi.yaml \
-n svraft --dry-run=client -o yaml | kubectl apply -f -
# Restart deployment
kubectl rollout restart deployment df-adaptive-api -n svraft
Option 2: Custom Python Handler (Real Logic)
For production implementations with real business logic.
-
Write Python FastAPI handler
-
Deploy as ConfigMap
-
Handlers override auto-generated routes
-
Full access to FastAPI features
# my_handler.py
from fastapi import APIRouter, HTTPException
router = APIRouter(tags=["My API"])
@router.get("/items")
async def list_items():
return {"items": [{"id": 1, "name": "Item 1"}]}
@router.get("/items/{item_id}")
async def get_item(item_id: int):
if item_id == 1:
return {"id": 1, "name": "Item 1"}
raise HTTPException(status_code=404, detail="Not found")
# Deploy handler
kubectl create configmap df-adaptive-api-handlers \
--from-file=my_handler.py=/tmp/my_handler.py \
-n svraft --dry-run=client -o yaml | kubectl apply -f -
# Restart deployment
kubectl rollout restart deployment df-adaptive-api -n svraft
Your API will be available at /api/adaptive/my (filename my_handler.py → mount path /my).
Path Mapping Convention
Handler filenames determine the API mount path:
| Handler Filename | Mount Path | Example Endpoint |
|---|---|---|
|
|
|
|
|
|
|
|
|
Rules:
-
_handlersuffix is removed -
Underscores (
_) are converted to hyphens (-) -
Routes in handler are relative to mount path
Hot Reload
Reload routes without pod restart:
curl -u username:password -X POST https://localhost/api/adaptive/actuator/refresh
Returns:
{
"status": "success",
"message": "Routes reloaded successfully",
"handlers": ["library-api_handler.py"],
"specs": ["sample-crud.openapi.yaml"]
}
ConfigMap changes require kubectl rollout restart to remount updated volumes.
Hot-reload only works for changes to already-mounted files.
|
Configuration
Environment variables (set in Helm values):
| Variable | Description | Default |
|---|---|---|
|
Enable authentication enforcement |
|
|
Keycloak server URL |
|
|
Keycloak realm name |
|
|
Directory containing OpenAPI specs |
|
|
Directory containing custom handlers |
|
|
Enable hot-reload |
|
Examples
See Adaptive API Quick Start for a complete walkthrough including:
-
Creating OpenAPI specifications
-
Deploying to Kubernetes
-
Testing auto-generated endpoints
-
Adding custom Python handlers
-
Authentication
Troubleshooting
Specs Not Loading
Check ConfigMaps and logs:
# View specs ConfigMap
kubectl get configmap df-adaptive-api-sample-specs -n svraft -o yaml
# Check logs for loading errors
kubectl logs -l app.kubernetes.io/name=df-adaptive-api -n svraft -c api --tail=100
Handler Errors
Check Python syntax and imports:
# View handler logs
kubectl logs -l app.kubernetes.io/name=df-adaptive-api -n svraft -c api -f
# Test handler syntax locally
python -m py_compile my_handler.py
Authentication Failures
Verify credentials and check if auth is enabled:
# Check if auth is enabled
kubectl get deployment df-adaptive-api -n svraft \
-o jsonpath='{.spec.template.spec.containers[0].env[?(@.name=="AUTH_ENABLED")].value}'
# Disable auth for testing
kubectl set env deployment/df-adaptive-api -n svraft AUTH_ENABLED=false
kubectl rollout restart deployment df-adaptive-api -n svraft
Route Conflicts (Spec vs Handler)
If both an OpenAPI spec and custom handler define the same routes, the spec-generated route may take precedence.
Solution: Remove the OpenAPI spec from the ConfigMap when deploying a custom handler:
# Keep only other specs, remove conflicting one
kubectl get configmap df-adaptive-api-sample-specs -n svraft \
-o jsonpath='{.data.sample-crud\.openapi\.yaml}' > /tmp/sample-crud.yaml
kubectl create configmap df-adaptive-api-sample-specs \
--from-file=sample-crud.openapi.yaml=/tmp/sample-crud.yaml \
-n svraft --dry-run=client -o yaml | kubectl apply -f -
kubectl rollout restart deployment df-adaptive-api -n svraft