Rewrite and expand all documentation for API7EE demo platform
This commit is contained in:
810
api/README.md
810
api/README.md
@@ -1,87 +1,787 @@
|
||||
# API Service - FastAPI
|
||||
# API Service - FastAPI Backend
|
||||
|
||||
A RESTful API service built with FastAPI featuring Swagger documentation.
|
||||
A RESTful API service built with FastAPI featuring automatic Swagger documentation, CRUD operations, and integrated LLM endpoints with OpenAI-compatible API support.
|
||||
|
||||
## Features
|
||||
## 📋 Overview
|
||||
|
||||
- 📚 Automatic Swagger/OpenAPI documentation
|
||||
- 🔄 RESTful API endpoints
|
||||
- ✅ Data validation with Pydantic
|
||||
- 📊 Statistics and monitoring endpoints
|
||||
- ❤️ Health check endpoints
|
||||
This API backend provides:
|
||||
|
||||
## Local Development
|
||||
- **RESTful CRUD API**: Items and Users management
|
||||
- **LLM Integration**: OpenAI-compatible chat endpoints for AI-powered features
|
||||
- **Automatic Documentation**: Swagger UI and ReDoc
|
||||
- **Data Validation**: Pydantic models with type checking
|
||||
- **Health Monitoring**: Health check endpoints
|
||||
- **Production Ready**: Designed for Kubernetes deployment with API7 Gateway
|
||||
|
||||
### Run with Python
|
||||
## ✨ Features
|
||||
|
||||
### REST API
|
||||
|
||||
- **Items Management**: Create, read, update, delete items
|
||||
- **Users Management**: User CRUD operations
|
||||
- **Pagination Support**: Query parameters for data filtering
|
||||
- **Validation**: Automatic request/response validation with Pydantic
|
||||
|
||||
### LLM Integration
|
||||
|
||||
- **Chat Endpoint**: OpenAI-compatible chat completions API
|
||||
- **Model Management**: List available LLM models
|
||||
- **Token Tracking**: Returns token usage per request
|
||||
- **Configurable**: Supports custom OpenAI-compatible backends (Open WebUI, Ollama, etc.)
|
||||
- **Rate Limited**: Designed to work with API7's AI rate limiting (100 tokens/60s)
|
||||
|
||||
### Documentation
|
||||
|
||||
- **Swagger UI**: Interactive API documentation at `/docs`
|
||||
- **ReDoc**: Alternative documentation at `/redoc`
|
||||
- **OpenAPI Schema**: JSON schema at `/openapi.json`
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Local Development
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
python >= 3.8
|
||||
pip
|
||||
```
|
||||
|
||||
# Run the application
|
||||
#### Install Dependencies
|
||||
|
||||
```bash
|
||||
cd api
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### Run the Application
|
||||
|
||||
```bash
|
||||
# Basic run
|
||||
python main.py
|
||||
|
||||
# Or use uvicorn directly
|
||||
uvicorn main:app --reload --host 0.0.0.0 --port 8000
|
||||
uvicorn main:app --reload --host 0.0.0.0 --port 8001
|
||||
|
||||
# With custom port
|
||||
uvicorn main:app --reload --port 8080
|
||||
```
|
||||
|
||||
### Run with Docker
|
||||
#### Access the API
|
||||
|
||||
- **Root**: http://localhost:8001/
|
||||
- **Swagger UI**: http://localhost:8001/docs
|
||||
- **ReDoc**: http://localhost:8001/redoc
|
||||
- **Health Check**: http://localhost:8001/health
|
||||
|
||||
### Docker
|
||||
|
||||
#### Build Image
|
||||
|
||||
```bash
|
||||
# Build image
|
||||
docker build -t fastapi-api .
|
||||
|
||||
# Run container
|
||||
docker run -p 8000:8000 fastapi-api
|
||||
docker build -t api-service .
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
#### Run Container
|
||||
|
||||
### Items
|
||||
- `GET /items` - List all items (with pagination)
|
||||
- `GET /items/{item_id}` - Get specific item
|
||||
- `POST /items` - Create new item
|
||||
- `PUT /items/{item_id}` - Update item
|
||||
- `DELETE /items/{item_id}` - Delete item
|
||||
|
||||
### Users
|
||||
- `GET /users` - List all users
|
||||
- `GET /users/{user_id}` - Get specific user
|
||||
- `POST /users` - Create new user
|
||||
|
||||
### Other
|
||||
- `GET /` - API information
|
||||
- `GET /health` - Health check
|
||||
- `GET /info` - Service information
|
||||
- `GET /stats` - API statistics
|
||||
|
||||
## Documentation
|
||||
|
||||
- Swagger UI: http://localhost:8000/docs
|
||||
- ReDoc: http://localhost:8000/redoc
|
||||
- OpenAPI JSON: http://localhost:8000/openapi.json
|
||||
|
||||
## Example Requests
|
||||
|
||||
### Create Item
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/items" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
# Basic run
|
||||
docker run -p 8001:8001 api-service
|
||||
|
||||
# With environment variables
|
||||
docker run -p 8001:8001 \
|
||||
-e OPENAI_API_BASE="http://host.docker.internal:11434/api" \
|
||||
-e OPENAI_API_KEY="your-api-key" \
|
||||
-e DEFAULT_LLM_MODEL="videogame-expert" \
|
||||
api-service
|
||||
```
|
||||
|
||||
## 🔌 API Endpoints
|
||||
|
||||
### Information Endpoints
|
||||
|
||||
#### `GET /`
|
||||
|
||||
Root endpoint with API information.
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Welcome to API Demo",
|
||||
"version": "1.0.0",
|
||||
"docs": "/docs",
|
||||
"timestamp": "2025-10-07T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
#### `GET /health`
|
||||
|
||||
Health check endpoint.
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"service": "api",
|
||||
"timestamp": "2025-10-07T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
### Items Endpoints
|
||||
|
||||
#### `GET /items`
|
||||
|
||||
Get all items with optional pagination.
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- None (returns all items)
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Laptop",
|
||||
"description": "High-performance laptop",
|
||||
"price": 999.99,
|
||||
"in_stock": true
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Mouse",
|
||||
"description": "Wireless mouse",
|
||||
"price": 29.99,
|
||||
"in_stock": true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### `GET /items/{item_id}`
|
||||
|
||||
Get a specific item by ID.
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Laptop",
|
||||
"description": "High-performance laptop",
|
||||
"price": 999.99,
|
||||
"in_stock": true
|
||||
}
|
||||
```
|
||||
|
||||
#### `POST /items`
|
||||
|
||||
Create a new item.
|
||||
|
||||
**Request Body**:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Monitor",
|
||||
"description": "4K Display",
|
||||
"price": 299.99,
|
||||
"in_stock": true
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Monitor",
|
||||
"description": "4K Display",
|
||||
"price": 299.99,
|
||||
"in_stock": true
|
||||
}
|
||||
```
|
||||
|
||||
#### `PUT /items/{item_id}`
|
||||
|
||||
Update an existing item.
|
||||
|
||||
**Request Body**:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Monitor",
|
||||
"description": "Updated 4K Display",
|
||||
"price": 279.99,
|
||||
"in_stock": true
|
||||
}
|
||||
```
|
||||
|
||||
#### `DELETE /items/{item_id}`
|
||||
|
||||
Delete an item.
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Item deleted successfully"
|
||||
}
|
||||
```
|
||||
|
||||
### Users Endpoints
|
||||
|
||||
#### `GET /users`
|
||||
|
||||
Get all users.
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"username": "john_doe",
|
||||
"email": "john@example.com",
|
||||
"active": true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### `GET /users/{user_id}`
|
||||
|
||||
Get a specific user by ID.
|
||||
|
||||
#### `POST /users`
|
||||
|
||||
Create a new user.
|
||||
|
||||
**Request Body**:
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "jane_doe",
|
||||
"email": "jane@example.com",
|
||||
"active": true
|
||||
}
|
||||
```
|
||||
|
||||
### LLM Endpoints
|
||||
|
||||
#### `POST /llm/chat`
|
||||
|
||||
Send a chat message to the LLM.
|
||||
|
||||
**Request Body**:
|
||||
|
||||
```json
|
||||
{
|
||||
"prompt": "What is The Legend of Zelda?",
|
||||
"max_tokens": 150,
|
||||
"temperature": 0.7,
|
||||
"model": "videogame-expert"
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"response": "The Legend of Zelda is a high-fantasy action-adventure video game franchise created by Japanese game designers Shigeru Miyamoto and Takashi Tezuka...",
|
||||
"tokens_used": 85,
|
||||
"model": "videogame-expert",
|
||||
"timestamp": "2025-10-07T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
**Rate Limiting**: When deployed with API7 Gateway, this endpoint is limited to **100 tokens per 60 seconds** using AI rate limiting.
|
||||
|
||||
#### `GET /llm/models`
|
||||
|
||||
List available LLM models.
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"models": [
|
||||
{
|
||||
"id": "videogame-expert",
|
||||
"name": "Videogame Expert",
|
||||
"max_tokens": 4096,
|
||||
"provider": "Open WebUI"
|
||||
}
|
||||
],
|
||||
"default_model": "videogame-expert",
|
||||
"timestamp": "2025-10-07T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
#### `GET /llm/health`
|
||||
|
||||
LLM service health check.
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"service": "llm-api",
|
||||
"provider": "Open WebUI",
|
||||
"endpoint": "http://localhost/api",
|
||||
"default_model": "videogame-expert",
|
||||
"rate_limit": "ai-rate-limiting enabled (100 tokens/60s)",
|
||||
"timestamp": "2025-10-07T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Configure the API service using environment variables:
|
||||
|
||||
| Variable | Description | Default | Required |
|
||||
| ------------------- | ---------------------------------- | ---------------------- | -------- |
|
||||
| `OPENAI_API_BASE` | OpenAI-compatible API endpoint URL | `http://localhost/api` | No |
|
||||
| `OPENAI_API_KEY` | API key for LLM service | `your-api-key` | No |
|
||||
| `DEFAULT_LLM_MODEL` | Default LLM model ID | `your-model-id` | No |
|
||||
|
||||
### Example Configuration
|
||||
|
||||
**Development**:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_BASE="http://localhost:11434/api"
|
||||
export OPENAI_API_KEY="not-required-for-ollama"
|
||||
export DEFAULT_LLM_MODEL="llama2"
|
||||
```
|
||||
|
||||
**Production (Open WebUI)**:
|
||||
|
||||
```bash
|
||||
export OPENAI_API_BASE="https://openwebui.example.com/api"
|
||||
export OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxx"
|
||||
export DEFAULT_LLM_MODEL="videogame-expert"
|
||||
```
|
||||
|
||||
**Kubernetes Deployment**:
|
||||
|
||||
```yaml
|
||||
env:
|
||||
- name: OPENAI_API_BASE
|
||||
value: "http://openwebui.ai:8080/api"
|
||||
- name: OPENAI_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: llm-secrets
|
||||
key: api-key
|
||||
- name: DEFAULT_LLM_MODEL
|
||||
value: "videogame-expert"
|
||||
```
|
||||
|
||||
## 📊 Data Models
|
||||
|
||||
### Item Model
|
||||
|
||||
```python
|
||||
class Item(BaseModel):
|
||||
id: Optional[int] = None
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
price: float
|
||||
in_stock: bool = True
|
||||
```
|
||||
|
||||
### User Model
|
||||
|
||||
```python
|
||||
class User(BaseModel):
|
||||
id: Optional[int] = None
|
||||
username: str
|
||||
email: str
|
||||
active: bool = True
|
||||
```
|
||||
|
||||
### LLM Request Model
|
||||
|
||||
```python
|
||||
class LLMRequest(BaseModel):
|
||||
prompt: str
|
||||
max_tokens: Optional[int] = 150
|
||||
temperature: Optional[float] = 0.7
|
||||
model: Optional[str] = DEFAULT_MODEL
|
||||
```
|
||||
|
||||
### LLM Response Model
|
||||
|
||||
```python
|
||||
class LLMResponse(BaseModel):
|
||||
response: str
|
||||
tokens_used: int
|
||||
model: str
|
||||
timestamp: str
|
||||
```
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### cURL Examples
|
||||
|
||||
**Create Item**:
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8001/items" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Keyboard",
|
||||
"description": "Mechanical keyboard",
|
||||
"price": 79.99,
|
||||
"in_stock": true
|
||||
}'
|
||||
```
|
||||
|
||||
### Get Items
|
||||
**Get Items**:
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8000/items?skip=0&limit=10&in_stock=true"
|
||||
curl "http://localhost:8001/items"
|
||||
```
|
||||
|
||||
### Get Statistics
|
||||
**Update Item**:
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8000/stats"
|
||||
curl -X PUT "http://localhost:8001/items/1" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Laptop Pro",
|
||||
"description": "Updated laptop",
|
||||
"price": 1099.99,
|
||||
"in_stock": true
|
||||
}'
|
||||
```
|
||||
|
||||
**Delete Item**:
|
||||
|
||||
```bash
|
||||
curl -X DELETE "http://localhost:8001/items/3"
|
||||
```
|
||||
|
||||
**LLM Chat**:
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8001/llm/chat" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"prompt": "Tell me about Mario Bros",
|
||||
"max_tokens": 100,
|
||||
"temperature": 0.7,
|
||||
"model": "videogame-expert"
|
||||
}'
|
||||
```
|
||||
|
||||
**Health Checks**:
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8001/health"
|
||||
curl "http://localhost:8001/llm/health"
|
||||
```
|
||||
|
||||
### Python Testing
|
||||
|
||||
```python
|
||||
import httpx
|
||||
|
||||
# Test item creation
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.post(
|
||||
"http://localhost:8001/items",
|
||||
json={
|
||||
"name": "Monitor",
|
||||
"description": "4K Display",
|
||||
"price": 299.99,
|
||||
"in_stock": True
|
||||
}
|
||||
)
|
||||
print(response.json())
|
||||
|
||||
# Test LLM chat
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.post(
|
||||
"http://localhost:8001/llm/chat",
|
||||
json={
|
||||
"prompt": "What is Minecraft?",
|
||||
"max_tokens": 150,
|
||||
"model": "videogame-expert"
|
||||
}
|
||||
)
|
||||
print(response.json())
|
||||
```
|
||||
|
||||
## 🐳 Docker
|
||||
|
||||
### Dockerfile
|
||||
|
||||
The Dockerfile uses Python 3.11 slim image and installs dependencies directly:
|
||||
|
||||
```dockerfile
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies
|
||||
RUN pip install --no-cache-dir fastapi uvicorn[standard] pydantic
|
||||
|
||||
# Copy application
|
||||
COPY db.json .
|
||||
COPY main.py .
|
||||
|
||||
EXPOSE 8001
|
||||
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8001"]
|
||||
```
|
||||
|
||||
### Build and Run
|
||||
|
||||
```bash
|
||||
# Build
|
||||
docker build -t api-service:latest .
|
||||
|
||||
# Run with environment variables
|
||||
docker run -d \
|
||||
--name api-service \
|
||||
-p 8001:8001 \
|
||||
-e OPENAI_API_BASE="http://host.docker.internal:11434/api" \
|
||||
-e OPENAI_API_KEY="your-key" \
|
||||
api-service:latest
|
||||
|
||||
# View logs
|
||||
docker logs -f api-service
|
||||
|
||||
# Stop and remove
|
||||
docker stop api-service
|
||||
docker rm api-service
|
||||
```
|
||||
|
||||
## ☸️ Kubernetes Deployment
|
||||
|
||||
### Basic Deployment
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: api-service
|
||||
namespace: api7ee
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: api
|
||||
spec:
|
||||
containers:
|
||||
- name: api
|
||||
image: git.commandware.com/demos/api7-demo/api:main
|
||||
ports:
|
||||
- containerPort: 8001
|
||||
name: http
|
||||
env:
|
||||
- name: OPENAI_API_BASE
|
||||
value: "http://openwebui.ai:8080/api"
|
||||
- name: OPENAI_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: llm-secrets
|
||||
key: api-key
|
||||
- name: DEFAULT_LLM_MODEL
|
||||
value: "videogame-expert"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8001
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8001
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: api-service
|
||||
namespace: api7ee
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8001
|
||||
name: http
|
||||
selector:
|
||||
app: api
|
||||
```
|
||||
|
||||
### With Helm
|
||||
|
||||
See the [Helm chart README](../helm/api7ee-demo-k8s/README.md) for full deployment options.
|
||||
|
||||
```bash
|
||||
helm install api7ee-demo ./helm/api7ee-demo-k8s \
|
||||
--set api.image.tag=v1.0.0 \
|
||||
--set api.replicaCount=5 \
|
||||
--namespace api7ee
|
||||
```
|
||||
|
||||
## 🔒 Security
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Environment Variables**: Store sensitive data (API keys) in Kubernetes Secrets
|
||||
2. **Non-root User**: Container runs as non-root user (UID 1000)
|
||||
3. **Read-only Filesystem**: Root filesystem is read-only
|
||||
4. **Input Validation**: All requests validated with Pydantic
|
||||
5. **CORS**: Configure CORS policies in API7 Gateway
|
||||
6. **Rate Limiting**: API7 Gateway enforces rate limits
|
||||
|
||||
### Example Secret
|
||||
|
||||
```bash
|
||||
kubectl create secret generic llm-secrets \
|
||||
--from-literal=api-key='your-openai-api-key' \
|
||||
-n api7ee
|
||||
```
|
||||
|
||||
## 📦 Dependencies
|
||||
|
||||
### Python Requirements
|
||||
|
||||
```
|
||||
fastapi==0.104.1
|
||||
uvicorn[standard]==0.24.0
|
||||
pydantic==2.5.0
|
||||
httpx==0.26.0
|
||||
```
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## 🚀 Production Deployment
|
||||
|
||||
### Recommended Configuration
|
||||
|
||||
```yaml
|
||||
api:
|
||||
replicaCount: 5
|
||||
autoscaling:
|
||||
enabled: true
|
||||
minReplicas: 5
|
||||
maxReplicas: 30
|
||||
targetCPUUtilizationPercentage: 70
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2000m
|
||||
memory: 2Gi
|
||||
requests:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
env:
|
||||
- name: LOG_LEVEL
|
||||
value: "warn"
|
||||
- name: ENVIRONMENT
|
||||
value: "production"
|
||||
```
|
||||
|
||||
### API7 Gateway Integration
|
||||
|
||||
When deployed behind API7 Gateway:
|
||||
|
||||
**Rate Limiting**:
|
||||
|
||||
- `/api/*`: 100 requests/60s per IP (standard rate limiting)
|
||||
- `/api/llm/*`: 100 tokens/60s (AI rate limiting)
|
||||
|
||||
**Routing**:
|
||||
|
||||
- Priority 10: `/api/*` routes
|
||||
- Priority 20: `/api/llm/*` routes (higher priority)
|
||||
|
||||
**Plugins**:
|
||||
|
||||
- `redirect`: HTTP → HTTPS
|
||||
- `limit-count`: IP-based rate limiting
|
||||
- `ai-rate-limiting`: Token-based LLM rate limiting
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
### Documentation
|
||||
|
||||
- **FastAPI**: https://fastapi.tiangolo.com/
|
||||
- **Pydantic**: https://docs.pydantic.dev/
|
||||
- **Uvicorn**: https://www.uvicorn.org/
|
||||
- **OpenAI API**: https://platform.openai.com/docs/api-reference
|
||||
|
||||
### Related
|
||||
|
||||
- [Main README](../README.md)
|
||||
- [Web Application README](../web/README.md)
|
||||
- [Helm Chart README](../helm/api7ee-demo-k8s/README.md)
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Issue**: LLM endpoints return errors
|
||||
|
||||
```bash
|
||||
# Check environment variables
|
||||
echo $OPENAI_API_BASE
|
||||
echo $OPENAI_API_KEY
|
||||
|
||||
# Test LLM backend directly
|
||||
curl -X POST "$OPENAI_API_BASE/chat/completions" \
|
||||
-H "Authorization: Bearer $OPENAI_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model":"videogame-expert","messages":[{"role":"user","content":"test"}]}'
|
||||
```
|
||||
|
||||
**Issue**: Rate limiting triggered
|
||||
|
||||
```bash
|
||||
# Check API7 Gateway logs
|
||||
kubectl logs -n api7ee -l app=api7-gateway
|
||||
|
||||
# Response: HTTP 429
|
||||
# Cause: Exceeded 100 tokens/60s or 100 req/60s
|
||||
# Solution: Wait for rate limit window to reset
|
||||
```
|
||||
|
||||
**Issue**: Health check fails
|
||||
|
||||
```bash
|
||||
# Check if service is running
|
||||
curl http://localhost:8001/health
|
||||
|
||||
# Check logs
|
||||
docker logs api-service
|
||||
# or
|
||||
kubectl logs -n api7ee -l app=api
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Version**: 1.0.0 | **Port**: 8001 | **Framework**: FastAPI 0.104.1
|
||||
|
||||
@@ -1,123 +1,267 @@
|
||||
# API7 Enterprise Edition Helm Chart
|
||||
# API7 Enterprise Edition Demo - Helm Chart
|
||||
|
||||
This Helm chart deploys the API7 Enterprise Edition demo application, consisting of a Web frontend and API backend service.
|
||||
A comprehensive Helm chart for deploying the API7 Enterprise Edition demo platform on Kubernetes. This chart deploys both web frontend and API backend services with full API7 Gateway integration, including automatic ADC configuration, TLS management, and advanced rate limiting.
|
||||
|
||||
## Prerequisites
|
||||
## 📋 Overview
|
||||
|
||||
- Kubernetes 1.19+
|
||||
- Helm 3.8.0+
|
||||
- PV provisioner support in the underlying infrastructure (optional)
|
||||
- Ingress controller (e.g., NGINX Ingress Controller)
|
||||
This Helm chart provides:
|
||||
|
||||
## Installation
|
||||
- **Dual Service Deployment**: Web frontend + API backend
|
||||
- **API7 Gateway Integration**: Automatic ADC (API7 Declarative CLI) configuration
|
||||
- **TLS/SSL Management**: cert-manager integration or custom certificates
|
||||
- **Service Discovery**: Kubernetes-native service discovery
|
||||
- **Rate Limiting**: Standard and AI token-based rate limiting
|
||||
- **Autoscaling**: Horizontal Pod Autoscaler (HPA) support
|
||||
- **High Availability**: Pod Disruption Budgets and multi-replica deployment
|
||||
- **Security**: Pod Security Contexts, RBAC, and Network Policies
|
||||
|
||||
### Add the Helm repository (if published)
|
||||
## 🎯 Features
|
||||
|
||||
### Deployments
|
||||
|
||||
- **Web Service** (apache-service): FastAPI frontend with embedded documentation
|
||||
- **API Service** (nginx-service): FastAPI backend with REST API and LLM endpoints
|
||||
|
||||
### API7 Gateway Configuration
|
||||
|
||||
- **Automatic ADC Sync**: Configures routes, services, and upstreams
|
||||
- **Advanced Rate Limiting**:
|
||||
- Standard: 100 req/60s per IP for `/api/*`
|
||||
- AI: 100 tokens/60s for `/api/llm/*`
|
||||
- **Route Prioritization**: LLM (20) > API (10) > Web (1)
|
||||
- **TLS/SSL**: Automatic HTTPS redirect and certificate management
|
||||
- **Plugins**: CORS, Prometheus metrics, request logging, authentication
|
||||
|
||||
### Kubernetes Resources
|
||||
|
||||
- Deployments (Web and API)
|
||||
- Services (ClusterIP)
|
||||
- Ingress (NGINX)
|
||||
- ConfigMaps (Application config and ADC config)
|
||||
- Secrets (TLS certificates, API7 credentials)
|
||||
- ServiceAccount and RBAC
|
||||
- HorizontalPodAutoscaler
|
||||
- PodDisruptionBudget
|
||||
- Certificate (cert-manager)
|
||||
- Job (ADC sync)
|
||||
|
||||
## 📦 Prerequisites
|
||||
|
||||
- **Kubernetes**: v1.19 or higher
|
||||
- **Helm**: 3.8.0 or higher
|
||||
- **API7 Enterprise Edition**: Installed and configured
|
||||
- **Ingress Controller**: NGINX Ingress Controller (recommended)
|
||||
- **cert-manager**: v1.0+ (optional, for automatic TLS)
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
### Add Helm Repository
|
||||
|
||||
```bash
|
||||
# Add the Gitea Helm repository
|
||||
helm repo add api7ee https://git.commandware.com/api/packages/demos/helm
|
||||
|
||||
# Update repositories
|
||||
helm repo update
|
||||
|
||||
# Search for available versions
|
||||
helm search repo api7ee/api7ee-demo-k8s
|
||||
```
|
||||
|
||||
### Install the chart
|
||||
### Basic Installation
|
||||
|
||||
```bash
|
||||
# Install with default values
|
||||
helm install my-api7ee ./helm/api7ee-demo-k8s-demo-k8s
|
||||
helm install api7ee-demo api7ee/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
--create-namespace
|
||||
|
||||
# Install in a specific namespace
|
||||
helm install my-api7ee ./helm/api7ee-demo-k8s-demo-k8s --namespace api7ee --create-namespace
|
||||
|
||||
# Install with custom values file
|
||||
helm install my-api7ee ./helm/api7ee-demo-k8s-demo-k8s -f custom-values.yaml
|
||||
# Check installation
|
||||
helm list -n api7ee
|
||||
kubectl get pods -n api7ee
|
||||
```
|
||||
|
||||
## Configuration
|
||||
### Installation with Custom Values
|
||||
|
||||
### API7 Gateway Integration
|
||||
```bash
|
||||
# Install with custom values file
|
||||
helm install api7ee-demo api7ee/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
--create-namespace \
|
||||
-f custom-values.yaml
|
||||
|
||||
This Helm chart includes automatic API7 Gateway configuration using ADC (API7 Declarative CLI). When `api7.enabled` is set to `true`, the chart will:
|
||||
# Install with command-line overrides
|
||||
helm install api7ee-demo api7ee/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
--set web.replicaCount=3 \
|
||||
--set api.replicaCount=5 \
|
||||
--set api7.gateway.adminKey="your-admin-key" \
|
||||
--set api7.hosts[0]="your-domain.com"
|
||||
```
|
||||
|
||||
1. **Deploy ADC Configuration**: Creates routes, services, and upstreams for your applications
|
||||
2. **Configure TLS/SSL**: Manages certificates via cert-manager or custom certificates
|
||||
3. **Enable Service Discovery**: Uses Kubernetes native service discovery
|
||||
4. **Apply Security Policies**: Configures rate limiting, CORS, and authentication
|
||||
5. **Auto-publish Routes**: Optionally publishes routes automatically after deployment
|
||||
### Install from Local Chart
|
||||
|
||||
### Key Configuration Options
|
||||
```bash
|
||||
# Install from local directory
|
||||
helm install api7ee-demo ./helm/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
--create-namespace
|
||||
|
||||
# With development values
|
||||
helm install api7ee-dev ./helm/api7ee-demo-k8s \
|
||||
-f ./helm/api7ee-demo-k8s/values-dev.yaml \
|
||||
--namespace api7ee-dev
|
||||
```
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
### Global Configuration
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| ------------------------- | ---------------------- | ------- |
|
||||
| `global.imageRegistry` | Global Docker registry | `""` |
|
||||
| `global.imagePullSecrets` | Image pull secrets | `[]` |
|
||||
|
||||
### Web Service Configuration
|
||||
|
||||
| Parameter | Description | Default |
|
||||
| ------------------------------------------------ | --------------------- | ---------------------- |
|
||||
| `web.enabled` | Enable Web component | `true` |
|
||||
| `web.replicaCount` | Number of Web replicas | `2` |
|
||||
| `web.image.repository` | Web image repository | `api7ee/web` |
|
||||
| `web.image.tag` | Web image tag | `main` |
|
||||
| `web.service.port` | Web service port | `8000` |
|
||||
| `web.replicaCount` | Number of replicas | `2` |
|
||||
| `web.image.registry` | Image registry | `gitea.server_url` |
|
||||
| `web.image.repository` | Image repository | `gitea.repository/web` |
|
||||
| `web.image.tag` | Image tag | `main` |
|
||||
| `web.image.pullPolicy` | Image pull policy | `IfNotPresent` |
|
||||
| `web.service.type` | Service type | `ClusterIP` |
|
||||
| `web.service.port` | Service port | `8000` |
|
||||
| `web.resources.limits.cpu` | CPU limit | `500m` |
|
||||
| `web.resources.limits.memory` | Memory limit | `512Mi` |
|
||||
| `web.resources.requests.cpu` | CPU request | `250m` |
|
||||
| `web.resources.requests.memory` | Memory request | `256Mi` |
|
||||
| `web.autoscaling.enabled` | Enable HPA | `false` |
|
||||
| `web.autoscaling.minReplicas` | Min replicas | `2` |
|
||||
| `web.autoscaling.maxReplicas` | Max replicas | `10` |
|
||||
| `web.autoscaling.targetCPUUtilizationPercentage` | CPU target | `80` |
|
||||
| `web.env` | Environment variables | `[]` |
|
||||
|
||||
### API Service Configuration
|
||||
|
||||
| Parameter | Description | Default |
|
||||
| ------------------------------------------------ | --------------------- | ---------------------------------- |
|
||||
| `api.enabled` | Enable API component | `true` |
|
||||
| `api.replicaCount` | Number of API replicas | `3` |
|
||||
| `api.image.repository` | API image repository | `api7ee/api` |
|
||||
| `api.image.tag` | API image tag | `main` |
|
||||
| `api.service.port` | API service port | `8080` |
|
||||
| `api.replicaCount` | Number of replicas | `3` |
|
||||
| `api.image.registry` | Image registry | `gitea.server_url` |
|
||||
| `api.image.repository` | Image repository | `gitea.repository/api` |
|
||||
| `api.image.tag` | Image tag | `main` |
|
||||
| `api.image.pullPolicy` | Image pull policy | `IfNotPresent` |
|
||||
| `api.service.type` | Service type | `ClusterIP` |
|
||||
| `api.service.port` | Service port | `8080` |
|
||||
| `api.resources.limits.cpu` | CPU limit | `1000m` |
|
||||
| `api.resources.limits.memory` | Memory limit | `1Gi` |
|
||||
| `api.resources.requests.cpu` | CPU request | `500m` |
|
||||
| `api.resources.requests.memory` | Memory request | `512Mi` |
|
||||
| `api.autoscaling.enabled` | Enable HPA | `true` |
|
||||
| `api.autoscaling.minReplicas` | Min replicas | `3` |
|
||||
| `api.autoscaling.maxReplicas` | Max replicas | `20` |
|
||||
| `api.autoscaling.targetCPUUtilizationPercentage` | CPU target | `70` |
|
||||
| `api.env` | Environment variables | `[{name: LOG_LEVEL, value: info}]` |
|
||||
|
||||
### Ingress Configuration
|
||||
|
||||
| Parameter | Description | Default |
|
||||
| --------------------------- | ------------------- | ---------------------------- |
|
||||
| `ingress.enabled` | Enable ingress | `true` |
|
||||
| `ingress.hosts[0].host` | Ingress hostname | `demo.commandware.it` |
|
||||
| `api7.enabled` | Enable API7 ADC configuration | `true` |
|
||||
| `api7.gateway.adminUrl` | API7 Gateway Admin API URL | `http://api7-gateway.api7ee:9180` |
|
||||
| `api7.hosts` | Hosts for API7 routing | `[demo.commandware.it]` |
|
||||
| `api7.tls.certManager.enabled` | Use cert-manager for TLS | `true` |
|
||||
| `ingress.className` | Ingress class | `nginx` |
|
||||
| `ingress.annotations` | Ingress annotations | See values.yaml |
|
||||
| `ingress.hosts[0].host` | Hostname | `api7-demo.commandware.it` |
|
||||
| `ingress.tls[0].secretName` | TLS secret | `api7ee-tls` |
|
||||
| `ingress.tls[0].hosts` | TLS hosts | `[api7-demo.commandware.it]` |
|
||||
|
||||
### API7 Gateway Configuration
|
||||
|
||||
| Parameter | Description | Default |
|
||||
| ----------------------------- | ---------------------- | ------------------------------------ |
|
||||
| `api7.enabled` | Enable API7 ADC config | `true` |
|
||||
| `api7.adc.image` | ADC Docker image | `ghcr.io/api7/adc:latest` |
|
||||
| `api7.adc.verbose` | Verbose logging | `true` |
|
||||
| `api7.adc.tlsSkipVerify` | Skip TLS verify | `false` |
|
||||
| `api7.gateway.adminUrl` | API7 Admin API URL | `http://api7ee3-0-xxx-dp-manager...` |
|
||||
| `api7.gateway.adminKey` | API7 Admin API key | `edd1c9f034335f136f87ad84b625c8f1` |
|
||||
| `api7.gateway.group` | Gateway group | `default` |
|
||||
| `api7.gateway.gatewayService` | Gateway service name | `gateway-0-xxx-gateway` |
|
||||
| `api7.backend` | Backend type | `api7ee` |
|
||||
| `api7.autoPublish` | Auto-publish routes | `true` |
|
||||
| `api7.hosts` | Routing hosts | `[api7-demo.commandware.it]` |
|
||||
|
||||
### Custom Values Examples
|
||||
### TLS Configuration
|
||||
|
||||
#### Configure API7 Gateway:
|
||||
|
||||
```yaml
|
||||
api7:
|
||||
enabled: true
|
||||
gateway:
|
||||
adminUrl: http://your-api7-gateway:9180
|
||||
adminKey: "your-admin-key-here"
|
||||
group: production
|
||||
hosts:
|
||||
- api.yourdomain.com
|
||||
tls:
|
||||
certManager:
|
||||
enabled: true
|
||||
issuer: letsencrypt-prod
|
||||
plugins:
|
||||
rateLimit:
|
||||
enabled: true
|
||||
count: 1000
|
||||
timeWindow: 60
|
||||
auth:
|
||||
enabled: true
|
||||
consumers:
|
||||
- username: api-client
|
||||
apiKey: secure-api-key-12345
|
||||
```
|
||||
|
||||
#### Using a private registry:
|
||||
| Parameter | Description | Default |
|
||||
| --------------------------------- | ------------------- | ---------------------- |
|
||||
| `api7.tls.enabled` | Enable TLS | `true` |
|
||||
| `api7.tls.certManager.enabled` | Use cert-manager | `true` |
|
||||
| `api7.tls.certManager.issuer` | ClusterIssuer name | `cloudflare-acme-prod` |
|
||||
| `api7.tls.certManager.issuerKind` | Issuer kind | `ClusterIssuer` |
|
||||
| `api7.tls.secretName` | Existing TLS secret | `""` |
|
||||
| `api7.tls.certificate` | Direct certificate | `""` |
|
||||
| `api7.tls.key` | Direct key | `""` |
|
||||
|
||||
### Rate Limiting Configuration
|
||||
|
||||
| Parameter | Description | Default |
|
||||
| ---------------------------------------- | ----------------------------- | -------------- |
|
||||
| `api7.plugins.rateLimit.enabled` | Enable standard rate limiting | `true` |
|
||||
| `api7.plugins.rateLimit.count` | Request limit | `100` |
|
||||
| `api7.plugins.rateLimit.timeWindow` | Time window (seconds) | `60` |
|
||||
| `api7.plugins.rateLimit.keyType` | Key type | `var` |
|
||||
| `api7.plugins.rateLimit.key` | Key variable | `remote_addr` |
|
||||
| `api7.plugins.aiRateLimit.enabled` | Enable AI rate limiting | `true` |
|
||||
| `api7.plugins.aiRateLimit.limit` | Token limit | `100` |
|
||||
| `api7.plugins.aiRateLimit.timeWindow` | Time window (seconds) | `60` |
|
||||
| `api7.plugins.aiRateLimit.limitStrategy` | Limit strategy | `total_tokens` |
|
||||
|
||||
### Additional Plugins
|
||||
|
||||
| Parameter | Description | Default |
|
||||
| --------------------------------- | ------------------------- | ------- |
|
||||
| `api7.plugins.cors.enabled` | Enable CORS | `true` |
|
||||
| `api7.plugins.cors.allowOrigins` | Allowed origins | `["*"]` |
|
||||
| `api7.plugins.auth.enabled` | Enable authentication | `false` |
|
||||
| `api7.plugins.prometheus.enabled` | Enable Prometheus metrics | `true` |
|
||||
| `api7.plugins.logging.enabled` | Enable request logging | `false` |
|
||||
|
||||
## 📝 Configuration Examples
|
||||
|
||||
### Production Deployment
|
||||
|
||||
```yaml
|
||||
# production-values.yaml
|
||||
global:
|
||||
imageRegistry: my-registry.example.com
|
||||
imageRegistry: "git.commandware.com"
|
||||
imagePullSecrets:
|
||||
- name: my-registry-secret
|
||||
```
|
||||
- name: registry-secret
|
||||
|
||||
#### Enabling autoscaling:
|
||||
|
||||
```yaml
|
||||
web:
|
||||
replicaCount: 3
|
||||
image:
|
||||
tag: "v1.0.0"
|
||||
pullPolicy: Always
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
autoscaling:
|
||||
enabled: true
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
targetCPUUtilizationPercentage: 70
|
||||
```
|
||||
minReplicas: 3
|
||||
maxReplicas: 15
|
||||
|
||||
#### Custom resource limits:
|
||||
|
||||
```yaml
|
||||
api:
|
||||
replicaCount: 5
|
||||
image:
|
||||
tag: "v1.0.0"
|
||||
pullPolicy: Always
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2000m
|
||||
@@ -125,31 +269,406 @@ api:
|
||||
requests:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
autoscaling:
|
||||
enabled: true
|
||||
minReplicas: 5
|
||||
maxReplicas: 30
|
||||
|
||||
api7:
|
||||
gateway:
|
||||
adminKey: "${API7_ADMIN_KEY}" # Use secret
|
||||
hosts:
|
||||
- api7-demo.yourdomain.com
|
||||
plugins:
|
||||
rateLimit:
|
||||
count: 1000
|
||||
auth:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
```bash
|
||||
helm install api7ee-prod api7ee/api7ee-demo-k8s \
|
||||
-f production-values.yaml \
|
||||
--namespace api7ee-prod \
|
||||
--create-namespace
|
||||
```
|
||||
|
||||
### Custom Domain and TLS
|
||||
|
||||
```yaml
|
||||
# custom-domain-values.yaml
|
||||
api7:
|
||||
hosts:
|
||||
- api.example.com
|
||||
- demo.example.com
|
||||
tls:
|
||||
certManager:
|
||||
enabled: true
|
||||
issuer: letsencrypt-prod
|
||||
|
||||
ingress:
|
||||
hosts:
|
||||
- host: api.example.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
service: web
|
||||
tls:
|
||||
- secretName: example-tls
|
||||
hosts:
|
||||
- api.example.com
|
||||
```
|
||||
|
||||
### High Resource Environment
|
||||
|
||||
```yaml
|
||||
# high-resources-values.yaml
|
||||
web:
|
||||
replicaCount: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: 2000m
|
||||
memory: 2Gi
|
||||
requests:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
autoscaling:
|
||||
enabled: true
|
||||
maxReplicas: 20
|
||||
|
||||
api:
|
||||
replicaCount: 10
|
||||
resources:
|
||||
limits:
|
||||
cpu: 4000m
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 2000m
|
||||
memory: 2Gi
|
||||
autoscaling:
|
||||
enabled: true
|
||||
maxReplicas: 50
|
||||
|
||||
podDisruptionBudget:
|
||||
enabled: true
|
||||
minAvailable: 3
|
||||
```
|
||||
|
||||
### Custom API7 Gateway
|
||||
|
||||
```yaml
|
||||
# custom-gateway-values.yaml
|
||||
api7:
|
||||
gateway:
|
||||
adminUrl: http://my-api7-gateway:9180
|
||||
adminKey: "my-custom-key"
|
||||
group: production
|
||||
gatewayService: my-gateway-service
|
||||
backend: apisix # or api7ee
|
||||
autoPublish: false # Manual publish
|
||||
```
|
||||
|
||||
### LLM Configuration
|
||||
|
||||
```yaml
|
||||
# llm-values.yaml
|
||||
api:
|
||||
env:
|
||||
- name: OPENAI_API_BASE
|
||||
value: "http://openwebui.ai:8080/api"
|
||||
- name: OPENAI_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: llm-secrets
|
||||
key: api-key
|
||||
- name: DEFAULT_LLM_MODEL
|
||||
value: "videogame-expert"
|
||||
|
||||
api7:
|
||||
plugins:
|
||||
aiRateLimit:
|
||||
enabled: true
|
||||
limit: 200 # Higher limit
|
||||
timeWindow: 60
|
||||
```
|
||||
|
||||
### Development Environment
|
||||
|
||||
Use the included `values-dev.yaml`:
|
||||
|
||||
```bash
|
||||
# Upgrade to a new version
|
||||
helm upgrade my-api7ee ./helm/api7ee-demo-k8s-demo-k8s
|
||||
helm install api7ee-dev ./helm/api7ee-demo-k8s \
|
||||
-f ./helm/api7ee-demo-k8s/values-dev.yaml \
|
||||
--namespace api7ee-dev
|
||||
```
|
||||
|
||||
## 🔄 Upgrade and Rollback
|
||||
|
||||
### Upgrade Release
|
||||
|
||||
```bash
|
||||
# Upgrade with new values
|
||||
helm upgrade my-api7ee ./helm/api7ee-demo-k8s-demo-k8s --set web.replicaCount=3
|
||||
helm upgrade api7ee-demo api7ee/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
-f new-values.yaml
|
||||
|
||||
# Upgrade with inline values
|
||||
helm upgrade api7ee-demo api7ee/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
--reuse-values \
|
||||
--set api.replicaCount=5
|
||||
|
||||
# Force upgrade
|
||||
helm upgrade api7ee-demo api7ee/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
--force
|
||||
```
|
||||
|
||||
## Uninstallation
|
||||
### Rollback
|
||||
|
||||
```bash
|
||||
# Uninstall the release
|
||||
helm uninstall my-api7ee
|
||||
# View release history
|
||||
helm history api7ee-demo -n api7ee
|
||||
|
||||
# Uninstall from a specific namespace
|
||||
helm uninstall my-api7ee --namespace api7ee
|
||||
# Rollback to previous release
|
||||
helm rollback api7ee-demo -n api7ee
|
||||
|
||||
# Rollback to specific revision
|
||||
helm rollback api7ee-demo 3 -n api7ee
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
### Verify Upgrade
|
||||
|
||||
If metrics are enabled, the services expose Prometheus-compatible metrics:
|
||||
```bash
|
||||
# Check release status
|
||||
helm status api7ee-demo -n api7ee
|
||||
|
||||
# View current values
|
||||
helm get values api7ee-demo -n api7ee
|
||||
|
||||
# Check all resources
|
||||
kubectl get all -n api7ee -l app.kubernetes.io/instance=api7ee-demo
|
||||
```
|
||||
|
||||
## 🗑️ Uninstallation
|
||||
|
||||
```bash
|
||||
# Uninstall release
|
||||
helm uninstall api7ee-demo --namespace api7ee
|
||||
|
||||
# Keep release history (for rollback)
|
||||
helm uninstall api7ee-demo --namespace api7ee --keep-history
|
||||
|
||||
# Delete namespace
|
||||
kubectl delete namespace api7ee
|
||||
```
|
||||
|
||||
## 🔍 Verification and Testing
|
||||
|
||||
### Check Deployment Status
|
||||
|
||||
```bash
|
||||
# Helm release status
|
||||
helm list -n api7ee
|
||||
helm status api7ee-demo -n api7ee
|
||||
|
||||
# Kubernetes resources
|
||||
kubectl get all -n api7ee
|
||||
kubectl get pods -n api7ee -w
|
||||
|
||||
# Check specific resources
|
||||
kubectl get deployments -n api7ee
|
||||
kubectl get services -n api7ee
|
||||
kubectl get ingress -n api7ee
|
||||
kubectl get hpa -n api7ee
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# Web service logs
|
||||
kubectl logs -n api7ee -l app=apache-service --tail=50
|
||||
|
||||
# API service logs
|
||||
kubectl logs -n api7ee -l app=nginx-service --tail=50
|
||||
|
||||
# ADC sync job logs
|
||||
kubectl logs -n api7ee -l app.kubernetes.io/component=adc-sync
|
||||
|
||||
# All logs
|
||||
kubectl logs -n api7ee -l app.kubernetes.io/instance=api7ee-demo --all-containers
|
||||
```
|
||||
|
||||
### Test Endpoints
|
||||
|
||||
```bash
|
||||
# Get ingress URL
|
||||
INGRESS_HOST=$(kubectl get ingress -n api7ee api7ee-demo-ingress -o jsonpath='{.spec.rules[0].host}')
|
||||
|
||||
# Test web service
|
||||
curl https://$INGRESS_HOST/
|
||||
|
||||
# Test API
|
||||
curl https://$INGRESS_HOST/api/items
|
||||
|
||||
# Test health checks
|
||||
curl https://$INGRESS_HOST/health
|
||||
curl https://$INGRESS_HOST/api/health
|
||||
|
||||
# Test LLM endpoint
|
||||
curl -X POST https://$INGRESS_HOST/api/llm/chat \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"prompt": "What is Zelda?",
|
||||
"max_tokens": 100
|
||||
}'
|
||||
```
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### 1. ADC Sync Job Fails
|
||||
|
||||
**Check job logs**:
|
||||
|
||||
```bash
|
||||
kubectl logs -n api7ee -l app.kubernetes.io/component=adc-sync
|
||||
|
||||
# Common errors:
|
||||
# - "connection refused" → Check adminUrl
|
||||
# - "unauthorized" → Verify adminKey
|
||||
# - "route not found" → Check backend type (api7ee vs apisix)
|
||||
```
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
# Update API7 credentials
|
||||
helm upgrade api7ee-demo api7ee/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
--reuse-values \
|
||||
--set api7.gateway.adminKey="correct-admin-key"
|
||||
```
|
||||
|
||||
#### 2. Pods Not Starting
|
||||
|
||||
**Check pod status**:
|
||||
|
||||
```bash
|
||||
kubectl describe pod -n api7ee <pod-name>
|
||||
|
||||
# Common issues:
|
||||
# - ImagePullBackOff → Check image registry credentials
|
||||
# - CrashLoopBackOff → Check application logs
|
||||
# - Pending → Check resources and node capacity
|
||||
```
|
||||
|
||||
**Solution for ImagePullBackOff**:
|
||||
|
||||
```bash
|
||||
# Create registry secret
|
||||
kubectl create secret docker-registry gitea-registry \
|
||||
--docker-server=git.commandware.com \
|
||||
--docker-username=<USERNAME> \
|
||||
--docker-password=<TOKEN> \
|
||||
-n api7ee
|
||||
|
||||
# Update values
|
||||
helm upgrade api7ee-demo api7ee/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
--reuse-values \
|
||||
--set global.imagePullSecrets[0].name=gitea-registry
|
||||
```
|
||||
|
||||
#### 3. Routes Return 404
|
||||
|
||||
**Cause**: Routes not published to gateway group
|
||||
|
||||
**Check API7 Dashboard**:
|
||||
|
||||
```
|
||||
Services → Select service → Routes → Check publication status
|
||||
```
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
# Enable auto-publish
|
||||
helm upgrade api7ee-demo api7ee/api7ee-demo-k8s \
|
||||
--namespace api7ee \
|
||||
--reuse-values \
|
||||
--set api7.autoPublish=true
|
||||
|
||||
# Or publish manually via Dashboard:
|
||||
# Click "Publish" → Select "default" gateway group
|
||||
```
|
||||
|
||||
#### 4. TLS Certificate Issues
|
||||
|
||||
**Check certificate status**:
|
||||
|
||||
```bash
|
||||
kubectl get certificate -n api7ee
|
||||
kubectl describe certificate -n api7ee api7ee-tls
|
||||
|
||||
# Check cert-manager logs
|
||||
kubectl logs -n cert-manager -l app=cert-manager --tail=50
|
||||
```
|
||||
|
||||
**Verify cert-manager configuration**:
|
||||
|
||||
```bash
|
||||
# Check ClusterIssuer
|
||||
kubectl get clusterissuer cloudflare-acme-prod
|
||||
|
||||
# Check challenge
|
||||
kubectl get challenge -n api7ee
|
||||
```
|
||||
|
||||
#### 5. Service Discovery Not Working
|
||||
|
||||
**Check services have named ports**:
|
||||
|
||||
```bash
|
||||
kubectl get svc -n api7ee apache-service -o yaml | grep -A5 ports
|
||||
|
||||
# Ports must have 'name' field:
|
||||
# ports:
|
||||
# - port: 80
|
||||
# name: http # ← Required
|
||||
```
|
||||
|
||||
**Check endpoints**:
|
||||
|
||||
```bash
|
||||
kubectl get endpoints -n api7ee
|
||||
```
|
||||
|
||||
#### 6. HPA Not Scaling
|
||||
|
||||
**Check HPA status**:
|
||||
|
||||
```bash
|
||||
kubectl get hpa -n api7ee
|
||||
kubectl describe hpa -n api7ee <hpa-name>
|
||||
```
|
||||
|
||||
**Verify metrics-server**:
|
||||
|
||||
```bash
|
||||
kubectl top nodes
|
||||
kubectl top pods -n api7ee
|
||||
|
||||
# If metrics not available, install metrics-server:
|
||||
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
|
||||
```
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
### Prometheus Metrics
|
||||
|
||||
If Prometheus is enabled:
|
||||
|
||||
```yaml
|
||||
metrics:
|
||||
@@ -159,59 +678,150 @@ metrics:
|
||||
interval: 30s
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### API7 ADC Sync Issues
|
||||
|
||||
If the ADC sync job fails:
|
||||
**View metrics**:
|
||||
|
||||
```bash
|
||||
# Check the job status
|
||||
kubectl get jobs -l app.kubernetes.io/instance=my-api7ee
|
||||
# Check ServiceMonitor
|
||||
kubectl get servicemonitor -n api7ee
|
||||
|
||||
# View job logs
|
||||
kubectl logs job/my-api7ee-adc-sync
|
||||
|
||||
# Manually run ADC sync
|
||||
kubectl run adc-debug --rm -it --image=ghcr.io/api7/adc:latest -- /bin/sh
|
||||
# Query Prometheus
|
||||
curl http://<prometheus-server>/api/v1/query?query=up{job="api7ee"}
|
||||
```
|
||||
|
||||
### Verify API7 Configuration
|
||||
### API7 Dashboard
|
||||
|
||||
Access API7 Dashboard to view:
|
||||
|
||||
- Route traffic and statistics
|
||||
- Rate limiting metrics
|
||||
- Service health and upstreams
|
||||
- Plugin performance
|
||||
|
||||
## 🔐 Security
|
||||
|
||||
### Security Features
|
||||
|
||||
- **Pod Security Context**: Runs as non-root user (UID 1000)
|
||||
- **Security Context**: Drops all capabilities, prevents privilege escalation
|
||||
- **Read-only Root Filesystem**: Enabled for both services
|
||||
- **Network Policies**: Optional network policy support
|
||||
- **RBAC**: ServiceAccount with minimal permissions
|
||||
- **Secrets Management**: TLS certificates and API keys stored securely
|
||||
|
||||
### Enable Network Policies
|
||||
|
||||
```yaml
|
||||
networkPolicy:
|
||||
enabled: true
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: api7ee
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8000
|
||||
```
|
||||
|
||||
### Secrets Management
|
||||
|
||||
**Create secrets before installation**:
|
||||
|
||||
```bash
|
||||
# Check if routes are configured
|
||||
curl -H "X-API-KEY: your-admin-key" http://api7-gateway:9180/apisix/admin/routes
|
||||
# API7 admin key
|
||||
kubectl create secret generic api7-admin-key \
|
||||
--from-literal=adminKey='your-admin-key' \
|
||||
-n api7ee
|
||||
|
||||
# Check service discovery
|
||||
curl -H "X-API-KEY: your-admin-key" http://api7-gateway:9180/apisix/admin/upstreams
|
||||
# LLM API key
|
||||
kubectl create secret generic llm-secrets \
|
||||
--from-literal=api-key='your-llm-api-key' \
|
||||
-n api7ee
|
||||
|
||||
# Image pull secret
|
||||
kubectl create secret docker-registry gitea-registry \
|
||||
--docker-server=git.commandware.com \
|
||||
--docker-username=<user> \
|
||||
--docker-password=<token> \
|
||||
-n api7ee
|
||||
```
|
||||
|
||||
### Check deployment status:
|
||||
```bash
|
||||
kubectl get deployments -l app.kubernetes.io/instance=my-api7ee
|
||||
**Reference in values**:
|
||||
|
||||
```yaml
|
||||
api7:
|
||||
gateway:
|
||||
adminKey: "${API7_ADMIN_KEY}"
|
||||
|
||||
api:
|
||||
env:
|
||||
- name: OPENAI_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: llm-secrets
|
||||
key: api-key
|
||||
```
|
||||
|
||||
### View logs:
|
||||
```bash
|
||||
# Web component logs
|
||||
kubectl logs -l app.kubernetes.io/instance=my-api7ee,app.kubernetes.io/component=web
|
||||
## 📚 Chart Structure
|
||||
|
||||
# API component logs
|
||||
kubectl logs -l app.kubernetes.io/instance=my-api7ee,app.kubernetes.io/component=api
|
||||
```
|
||||
helm/api7ee-demo-k8s/
|
||||
├── Chart.yaml # Chart metadata
|
||||
├── values.yaml # Default values
|
||||
├── values-dev.yaml # Development overrides
|
||||
├── values-production.yaml # Production overrides
|
||||
├── templates/
|
||||
│ ├── NOTES.txt # Post-install notes
|
||||
│ ├── _helpers.tpl # Template helpers
|
||||
│ ├── deployment-web.yaml # Web deployment
|
||||
│ ├── deployment-api.yaml # API deployment
|
||||
│ ├── service-web.yaml # Web service
|
||||
│ ├── service-api.yaml # API service
|
||||
│ ├── ingress.yaml # Ingress resource
|
||||
│ ├── configmap.yaml # Application config
|
||||
│ ├── configmap-adc.yaml # API7 ADC config
|
||||
│ ├── job-adc-sync.yaml # ADC sync job
|
||||
│ ├── secret.yaml # Application secrets
|
||||
│ ├── secret-api7.yaml # API7 secrets
|
||||
│ ├── certificate.yaml # cert-manager certificate
|
||||
│ ├── serviceaccount.yaml # ServiceAccount
|
||||
│ ├── rbac-adc.yaml # RBAC for ADC
|
||||
│ ├── hpa-web.yaml # Web HPA
|
||||
│ ├── hpa-api.yaml # API HPA
|
||||
│ └── poddisruptionbudget.yaml # PDB
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
### Check HPA status:
|
||||
```bash
|
||||
kubectl get hpa -l app.kubernetes.io/instance=my-api7ee
|
||||
```
|
||||
## 📦 Chart Information
|
||||
|
||||
## Security Considerations
|
||||
- **Name**: api7ee-demo-k8s
|
||||
- **Version**: 0.1.0
|
||||
- **App Version**: 1.0.0
|
||||
- **Type**: application
|
||||
- **Keywords**: api7, api-gateway, web, api
|
||||
- **Home**: https://demo.commandware.it
|
||||
- **Sources**: https://git.commandware.com/demos/api7-demo
|
||||
|
||||
- Pod Security Context is configured to run as non-root user (UID 1000)
|
||||
- Security Context drops all capabilities and prevents privilege escalation
|
||||
- Read-only root filesystem is enabled
|
||||
- Network policies can be enabled to restrict traffic
|
||||
## 📄 Resources
|
||||
|
||||
## Support
|
||||
### Documentation
|
||||
|
||||
For issues and questions, please contact support@commandware.com or visit https://git.commandware.com/demos/api7-demo
|
||||
- **Helm**: https://helm.sh/docs/
|
||||
- **API7 Enterprise**: https://docs.api7.ai/
|
||||
- **Kubernetes**: https://kubernetes.io/docs/
|
||||
|
||||
### Related
|
||||
|
||||
- [Main README](../../README.md)
|
||||
- [Web Application README](../../web/README.md)
|
||||
- [API Application README](../../api/README.md)
|
||||
|
||||
## 🤝 Support
|
||||
|
||||
- **Issues**: https://git.commandware.com/demos/api7-demo/issues
|
||||
- **Email**: support@commandware.com
|
||||
- **Repository**: https://git.commandware.com/demos/api7-demo
|
||||
|
||||
---
|
||||
|
||||
**Chart Version**: 0.1.0 | **Maintainer**: CommandWare | **License**: Demo Project
|
||||
|
||||
761
web/README.md
761
web/README.md
@@ -1,53 +1,96 @@
|
||||
# Web Application with Documentation
|
||||
# Web Application - FastAPI Frontend with Documentation
|
||||
|
||||
FastAPI web application serving a demo dashboard and comprehensive MkDocs documentation.
|
||||
A modern web frontend built with FastAPI featuring an interactive dashboard, embedded MkDocs documentation, and API proxy functionality for seamless integration with the backend API service.
|
||||
|
||||
## Features
|
||||
## 📋 Overview
|
||||
|
||||
- **Web Dashboard**: Simple HTML interface with metrics display
|
||||
- **Documentation Site**: Complete API7 Enterprise setup guide at `/docs`
|
||||
- **Health Checks**: Monitoring endpoint at `/health`
|
||||
This web application serves as the frontend for the API7 Enterprise Edition demo platform, providing:
|
||||
|
||||
## Documentation
|
||||
- **Interactive Dashboard**: Modern UI with real-time statistics
|
||||
- **Embedded Documentation**: Complete MkDocs documentation site at `/docs`
|
||||
- **API Proxy**: Seamless proxying of requests to the backend API
|
||||
- **LLM Chat Interface**: Interactive chat with AI videogame expert
|
||||
- **Health Monitoring**: Health check endpoints
|
||||
- **Static Assets**: Custom CSS and JavaScript for enhanced UX
|
||||
|
||||
The application includes comprehensive documentation built with MkDocs Material theme, covering:
|
||||
## ✨ Features
|
||||
|
||||
- **Architecture Overview**: Complete infrastructure and component details
|
||||
- **Getting Started**: Quick setup and deployment guide
|
||||
- **API7 Configuration**: Route and service configuration with examples
|
||||
### Web Pages
|
||||
|
||||
- **Home Page** (`/`): Dashboard with feature overview and statistics
|
||||
- **Items Page** (`/items`): Browse and manage items
|
||||
- **Users Page** (`/users`): View and manage users
|
||||
- **LLM Chat** (`/llm`): Interactive AI chat interface
|
||||
- **Documentation** (`/docs`): Full project documentation (MkDocs)
|
||||
|
||||
### API Proxy Endpoints
|
||||
|
||||
The web application proxies the following API endpoints:
|
||||
|
||||
- `GET /api/items` → Backend `/items`
|
||||
- `GET /api/items/{item_id}` → Backend `/items/{item_id}`
|
||||
- `GET /api/users` → Backend `/users`
|
||||
- `GET /api/users/{user_id}` → Backend `/users/{user_id}`
|
||||
- `POST /api/llm/chat` → Backend `/llm/chat`
|
||||
- `GET /api/llm/models` → Backend `/llm/models`
|
||||
- `GET /api/llm/health` → Backend `/llm/health`
|
||||
- `GET /api/config` → Returns frontend configuration
|
||||
|
||||
### Documentation Site
|
||||
|
||||
The embedded MkDocs documentation includes:
|
||||
|
||||
- **Getting Started**: Quick setup guide
|
||||
- **Architecture**: System architecture and component details
|
||||
- **Kubernetes Resources**: Complete resource reference
|
||||
- **CI/CD Pipeline**: Gitea Actions workflow documentation
|
||||
- **API7 Configuration**: Gateway setup and configuration
|
||||
- **CI/CD Pipeline**: Automation and deployment workflows
|
||||
- **Troubleshooting**: Common issues and solutions
|
||||
|
||||
## Running Locally
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
```bash
|
||||
python >= 3.8
|
||||
pip
|
||||
```
|
||||
|
||||
### Local Development
|
||||
|
||||
#### Install Dependencies
|
||||
|
||||
```bash
|
||||
cd web
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Start Application
|
||||
#### Run the Application
|
||||
|
||||
```bash
|
||||
# Basic run (connects to localhost:8001 by default)
|
||||
python main.py
|
||||
|
||||
# With custom API backend URL
|
||||
export API_BASE_URL="http://localhost:8001"
|
||||
python main.py
|
||||
|
||||
# Or use uvicorn directly
|
||||
uvicorn main:app --reload --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
**Access**:
|
||||
#### Access the Application
|
||||
|
||||
- Main Page: http://localhost:8000
|
||||
- Documentation: http://localhost:8000/docs/
|
||||
- Health Check: http://localhost:8000/health
|
||||
- **Home**: http://localhost:8000
|
||||
- **Items**: http://localhost:8000/items
|
||||
- **Users**: http://localhost:8000/users
|
||||
- **LLM Chat**: http://localhost:8000/llm
|
||||
- **Documentation**: http://localhost:8000/docs
|
||||
- **Health Check**: http://localhost:8000/health
|
||||
|
||||
### Build Documentation Manually
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
mkdocs build -f docs/mkdocs.yml -d site
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
### Build Image
|
||||
#### Build Image
|
||||
|
||||
```bash
|
||||
docker build -t web-app .
|
||||
@@ -56,23 +99,379 @@ docker build -t web-app .
|
||||
The Dockerfile:
|
||||
|
||||
1. Installs Python dependencies
|
||||
2. Copies application and documentation source
|
||||
3. Builds static documentation site with MkDocs
|
||||
4. Serves both the app and docs
|
||||
2. Copies application code, templates, static assets, and docs
|
||||
3. Builds static documentation with MkDocs
|
||||
4. Serves both the app and documentation
|
||||
|
||||
### Run Container
|
||||
#### Run Container
|
||||
|
||||
```bash
|
||||
# Basic run
|
||||
docker run -p 8000:8000 web-app
|
||||
|
||||
# With custom API backend URL
|
||||
docker run -p 8000:8000 \
|
||||
-e API_BASE_URL="http://api-backend:8001" \
|
||||
web-app
|
||||
|
||||
# Run with host network (for local testing)
|
||||
docker run --network host \
|
||||
-e API_BASE_URL="http://localhost:8001" \
|
||||
web-app
|
||||
```
|
||||
|
||||
## Kubernetes Deployment
|
||||
## 🔧 Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description | Default | Required |
|
||||
| -------------- | --------------- | ----------------------- | -------- |
|
||||
| `API_BASE_URL` | Backend API URL | `http://localhost:8001` | No |
|
||||
|
||||
### Example Configuration
|
||||
|
||||
**Development**:
|
||||
|
||||
```bash
|
||||
export API_BASE_URL="http://localhost:8001"
|
||||
python main.py
|
||||
```
|
||||
|
||||
**Docker**:
|
||||
|
||||
```bash
|
||||
docker run -p 8000:8000 \
|
||||
-e API_BASE_URL="http://api-service:8001" \
|
||||
web-app
|
||||
```
|
||||
|
||||
**Kubernetes**:
|
||||
|
||||
```yaml
|
||||
env:
|
||||
- name: API_BASE_URL
|
||||
value: "http://nginx-service.api7ee.svc.cluster.local:8080"
|
||||
```
|
||||
|
||||
## 📄 Pages and Routes
|
||||
|
||||
### HTML Pages
|
||||
|
||||
#### `GET /`
|
||||
|
||||
Home dashboard with feature cards and statistics.
|
||||
|
||||
**Features**:
|
||||
|
||||
- Feature cards (Items, Users, LLM, API Docs)
|
||||
- Real-time statistics (item count, user count)
|
||||
- Feature highlights
|
||||
- Links to all sections
|
||||
|
||||
#### `GET /items`
|
||||
|
||||
Items management page.
|
||||
|
||||
**Features**:
|
||||
|
||||
- Display all items from API
|
||||
- Real-time data fetching
|
||||
- Interactive UI
|
||||
|
||||
#### `GET /users`
|
||||
|
||||
Users management page.
|
||||
|
||||
**Features**:
|
||||
|
||||
- Display all users from API
|
||||
- User information cards
|
||||
- Real-time data updates
|
||||
|
||||
#### `GET /llm`
|
||||
|
||||
LLM chat interface.
|
||||
|
||||
**Features**:
|
||||
|
||||
- Interactive chat with AI
|
||||
- Markdown rendering for responses
|
||||
- Token usage display
|
||||
- Rate limit indicator (100 tokens/60s)
|
||||
- Model selection (videogame-expert)
|
||||
- Real-time status updates
|
||||
|
||||
### API Proxy Routes
|
||||
|
||||
#### `GET /api/items`
|
||||
|
||||
Proxy to backend API items endpoint.
|
||||
|
||||
**Backend**: `GET {API_BASE_URL}/items`
|
||||
|
||||
#### `GET /api/items/{item_id}`
|
||||
|
||||
Proxy to backend API specific item endpoint.
|
||||
|
||||
**Backend**: `GET {API_BASE_URL}/items/{item_id}`
|
||||
|
||||
#### `GET /api/users`
|
||||
|
||||
Proxy to backend API users endpoint.
|
||||
|
||||
**Backend**: `GET {API_BASE_URL}/users`
|
||||
|
||||
#### `GET /api/users/{user_id}`
|
||||
|
||||
Proxy to backend API specific user endpoint.
|
||||
|
||||
**Backend**: `GET {API_BASE_URL}/users/{user_id}`
|
||||
|
||||
#### `POST /api/llm/chat`
|
||||
|
||||
Proxy to backend LLM chat endpoint.
|
||||
|
||||
**Backend**: `POST {API_BASE_URL}/llm/chat`
|
||||
|
||||
**Request Body**:
|
||||
|
||||
```json
|
||||
{
|
||||
"prompt": "What is Zelda?",
|
||||
"max_tokens": 150,
|
||||
"temperature": 0.7,
|
||||
"model": "videogame-expert"
|
||||
}
|
||||
```
|
||||
|
||||
#### `GET /api/llm/models`
|
||||
|
||||
Proxy to backend LLM models endpoint.
|
||||
|
||||
**Backend**: `GET {API_BASE_URL}/llm/models`
|
||||
|
||||
#### `GET /api/llm/health`
|
||||
|
||||
Proxy to backend LLM health check.
|
||||
|
||||
**Backend**: `GET {API_BASE_URL}/llm/health`
|
||||
|
||||
### Health Check
|
||||
|
||||
#### `GET /health`
|
||||
|
||||
Web application health check.
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"service": "web",
|
||||
"version": "1.0.0",
|
||||
"api_backend": "http://localhost:8001",
|
||||
"api_status": "healthy"
|
||||
}
|
||||
```
|
||||
|
||||
**API Status Values**:
|
||||
|
||||
- `healthy`: Backend is responding
|
||||
- `unhealthy`: Backend returned non-200 status
|
||||
- `unreachable`: Cannot connect to backend
|
||||
|
||||
### Configuration Endpoint
|
||||
|
||||
#### `GET /api/config`
|
||||
|
||||
Get current frontend configuration.
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"api_base_url": "http://localhost:8001"
|
||||
}
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### MkDocs Configuration
|
||||
|
||||
The application includes a comprehensive documentation site built with MkDocs Material theme.
|
||||
|
||||
**Configuration file**: `mkdocs.yml`
|
||||
|
||||
**Theme Features**:
|
||||
|
||||
- Material Design theme
|
||||
- Light/Dark mode toggle
|
||||
- Navigation tabs and sections
|
||||
- Search functionality
|
||||
- Syntax highlighting
|
||||
- Code copy buttons
|
||||
|
||||
### Documentation Structure
|
||||
|
||||
```
|
||||
docs/
|
||||
├── index.md # Documentation home
|
||||
├── getting-started.md # Quick start guide
|
||||
├── architecture.md # System architecture
|
||||
├── kubernetes-resources.md # K8s resources reference
|
||||
├── api7-configuration.md # API7 Gateway setup
|
||||
├── cicd-pipeline.md # CI/CD documentation
|
||||
└── troubleshooting.md # Troubleshooting guide
|
||||
```
|
||||
|
||||
### Building Documentation
|
||||
|
||||
#### Serve Locally (Development)
|
||||
|
||||
```bash
|
||||
cd web
|
||||
mkdocs serve
|
||||
|
||||
# Access at http://localhost:8001
|
||||
```
|
||||
|
||||
#### Build Static Site
|
||||
|
||||
```bash
|
||||
mkdocs build -d site
|
||||
|
||||
# Output directory: web/site/
|
||||
```
|
||||
|
||||
The Docker build automatically builds the documentation during image creation.
|
||||
|
||||
### Updating Documentation
|
||||
|
||||
1. Edit markdown files in `docs/` directory
|
||||
2. Test locally with `mkdocs serve`
|
||||
3. Commit changes
|
||||
4. Rebuild Docker image or re-deploy
|
||||
|
||||
## 🎨 Templates and Static Assets
|
||||
|
||||
### Templates (Jinja2)
|
||||
|
||||
Located in `templates/`:
|
||||
|
||||
- **base.html**: Base template with common HTML structure
|
||||
- **index.html**: Home dashboard page
|
||||
- **items.html**: Items management page
|
||||
- **users.html**: Users management page
|
||||
- **llm.html**: LLM chat interface
|
||||
|
||||
### Static Assets
|
||||
|
||||
Located in `static/`:
|
||||
|
||||
- **css/**: Custom stylesheets
|
||||
- **js/**: JavaScript files
|
||||
|
||||
### Template Variables
|
||||
|
||||
Templates have access to:
|
||||
|
||||
- `request`: Starlette Request object
|
||||
- Context variables passed from route handlers
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Manual Testing
|
||||
|
||||
```bash
|
||||
# Test home page
|
||||
curl http://localhost:8000/
|
||||
|
||||
# Test health check
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Test API proxy
|
||||
curl http://localhost:8000/api/items
|
||||
curl http://localhost:8000/api/users
|
||||
|
||||
# Test LLM proxy
|
||||
curl -X POST http://localhost:8000/api/llm/chat \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"prompt": "What is Mario?",
|
||||
"max_tokens": 100
|
||||
}'
|
||||
|
||||
# Test configuration
|
||||
curl http://localhost:8000/api/config
|
||||
```
|
||||
|
||||
### Browser Testing
|
||||
|
||||
1. Navigate to http://localhost:8000
|
||||
2. Check all navigation links work
|
||||
3. Verify items and users load
|
||||
4. Test LLM chat interface
|
||||
5. Browse documentation at /docs
|
||||
|
||||
## 🐳 Docker
|
||||
|
||||
### Dockerfile Breakdown
|
||||
|
||||
```dockerfile
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy application files
|
||||
COPY main.py .
|
||||
COPY docs/ ./docs/
|
||||
COPY static/ ./static/
|
||||
COPY templates/ ./templates/
|
||||
COPY mkdocs.yml .
|
||||
|
||||
# Build documentation
|
||||
RUN mkdocs build -d site
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
```
|
||||
|
||||
### Multi-stage Build Benefits
|
||||
|
||||
- Dependencies installed during build
|
||||
- Documentation pre-built as static files
|
||||
- Smaller runtime container
|
||||
- Faster startup time
|
||||
|
||||
### Build and Push
|
||||
|
||||
```bash
|
||||
# Build
|
||||
docker build -t git.commandware.com/demos/api7-demo/web:latest .
|
||||
|
||||
# Tag
|
||||
docker tag git.commandware.com/demos/api7-demo/web:latest \
|
||||
git.commandware.com/demos/api7-demo/web:v1.0.0
|
||||
|
||||
# Push
|
||||
docker push git.commandware.com/demos/api7-demo/web:latest
|
||||
docker push git.commandware.com/demos/api7-demo/web:v1.0.0
|
||||
```
|
||||
|
||||
## ☸️ Kubernetes Deployment
|
||||
|
||||
### Basic Deployment
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web
|
||||
name: web-service
|
||||
namespace: api7ee
|
||||
spec:
|
||||
replicas: 2
|
||||
@@ -90,14 +489,28 @@ spec:
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
name: http
|
||||
env:
|
||||
- name: API_BASE_URL
|
||||
value: "http://nginx-service.api7ee.svc.cluster.local:8080"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 256Mi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
@@ -114,55 +527,259 @@ spec:
|
||||
app: web
|
||||
```
|
||||
|
||||
## Documentation Structure
|
||||
### With Helm
|
||||
|
||||
```
|
||||
docs/
|
||||
├── mkdocs.yml # MkDocs configuration
|
||||
├── index.md # Documentation home
|
||||
├── getting-started.md # Quick start guide
|
||||
├── architecture.md # Infrastructure architecture
|
||||
├── kubernetes-resources.md # K8s resources reference
|
||||
├── api7-configuration.md # API7 Gateway config guide
|
||||
├── cicd-pipeline.md # CI/CD documentation
|
||||
└── troubleshooting.md # Troubleshooting guide
|
||||
```
|
||||
See the [Helm chart README](../helm/api7ee-demo-k8s/README.md) for full deployment options.
|
||||
|
||||
## Endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
| --------- | --------------------------- |
|
||||
| `/` | Main web dashboard |
|
||||
| `/docs/` | Documentation site (MkDocs) |
|
||||
| `/health` | Health check endpoint |
|
||||
|
||||
## CI/CD
|
||||
|
||||
Images are automatically built and pushed to Gitea registry on every push:
|
||||
|
||||
**Registry**: `git.commandware.com/demos/api7-demo/web:<branch>`
|
||||
|
||||
See [CI/CD Pipeline documentation](docs/cicd-pipeline.md) for details.
|
||||
|
||||
## Development
|
||||
|
||||
### Update Documentation
|
||||
|
||||
1. Edit markdown files in `docs/` directory
|
||||
2. Test locally:
|
||||
```bash
|
||||
mkdocs serve -f docs/mkdocs.yml
|
||||
helm install api7ee-demo ./helm/api7ee-demo-k8s \
|
||||
--set web.image.tag=v1.0.0 \
|
||||
--set web.replicaCount=3 \
|
||||
--namespace api7ee
|
||||
```
|
||||
3. View at http://localhost:8001
|
||||
4. Rebuild with `mkdocs build` or rebuild Docker image
|
||||
|
||||
### Dependencies
|
||||
## 📦 Dependencies
|
||||
|
||||
### Python Requirements
|
||||
|
||||
```
|
||||
fastapi==0.104.1
|
||||
uvicorn[standard]==0.24.0
|
||||
jinja2==3.1.3
|
||||
python-multipart==0.0.6
|
||||
httpx==0.26.0
|
||||
mkdocs==1.5.3
|
||||
mkdocs-material==9.5.3
|
||||
pymdown-extensions==10.7
|
||||
```
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Dependency Breakdown
|
||||
|
||||
- **fastapi**: Web framework
|
||||
- **uvicorn**: ASGI server
|
||||
- **uvicorn**: ASGI server with WebSocket support
|
||||
- **jinja2**: Template engine for HTML pages
|
||||
- **python-multipart**: Form data parsing
|
||||
- **httpx**: Async HTTP client for API proxying
|
||||
- **mkdocs**: Documentation site generator
|
||||
- **mkdocs-material**: Material theme for MkDocs
|
||||
- **pymdown-extensions**: Additional markdown extensions
|
||||
|
||||
## 🚀 Production Deployment
|
||||
|
||||
### Recommended Configuration
|
||||
|
||||
```yaml
|
||||
web:
|
||||
replicaCount: 3
|
||||
autoscaling:
|
||||
enabled: true
|
||||
minReplicas: 3
|
||||
maxReplicas: 15
|
||||
targetCPUUtilizationPercentage: 80
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
env:
|
||||
- name: API_BASE_URL
|
||||
value: "http://nginx-service.api7ee.svc.cluster.local:8080"
|
||||
```
|
||||
|
||||
### API7 Gateway Integration
|
||||
|
||||
When deployed behind API7 Gateway:
|
||||
|
||||
**Routing**:
|
||||
|
||||
- Priority 1: `/*` routes to web service (matches all except `/api`)
|
||||
- Hosts: `api7-demo.commandware.it`
|
||||
|
||||
**Plugins**:
|
||||
|
||||
- `redirect`: HTTP → HTTPS enforcement
|
||||
- No rate limiting on web pages (only on API endpoints)
|
||||
|
||||
**Service Discovery**:
|
||||
|
||||
```yaml
|
||||
upstream:
|
||||
name: apache-upstream
|
||||
nodes:
|
||||
- host: apache-service.api7ee.svc.cluster.local
|
||||
port: 80
|
||||
weight: 100
|
||||
```
|
||||
|
||||
## 🔒 Security
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Non-root User**: Container runs as non-root (UID 1000)
|
||||
2. **Read-only Filesystem**: Root filesystem is read-only
|
||||
3. **CORS**: Configured via API7 Gateway
|
||||
4. **Input Validation**: FastAPI automatic validation
|
||||
5. **Proxy Security**: Validates API responses before forwarding
|
||||
|
||||
### Security Headers
|
||||
|
||||
Consider adding these headers via API7 Gateway:
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
response-rewrite:
|
||||
headers:
|
||||
X-Frame-Options: DENY
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: "1; mode=block"
|
||||
```
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
### Health Checks
|
||||
|
||||
The `/health` endpoint provides:
|
||||
|
||||
- Web service status
|
||||
- API backend connectivity
|
||||
- API backend health status
|
||||
|
||||
**Kubernetes Probes**:
|
||||
|
||||
```yaml
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
```
|
||||
|
||||
### Logging
|
||||
|
||||
Monitor application logs:
|
||||
|
||||
```bash
|
||||
# Docker
|
||||
docker logs -f web-app
|
||||
|
||||
# Kubernetes
|
||||
kubectl logs -n api7ee -l app=web --tail=100 -f
|
||||
|
||||
# Specific pod
|
||||
kubectl logs -n api7ee web-service-xxx-xxx -f
|
||||
```
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Issue**: Cannot connect to API backend
|
||||
|
||||
```bash
|
||||
# Check API_BASE_URL
|
||||
curl http://localhost:8000/api/config
|
||||
|
||||
# Check backend health
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Response shows api_status: "unreachable"
|
||||
# Solution: Verify API_BASE_URL is correct and backend is running
|
||||
```
|
||||
|
||||
**Issue**: Documentation not showing
|
||||
|
||||
```bash
|
||||
# Rebuild documentation
|
||||
mkdocs build -d site
|
||||
|
||||
# Check if site directory exists
|
||||
ls -la site/
|
||||
|
||||
# Rebuild Docker image
|
||||
docker build -t web-app .
|
||||
```
|
||||
|
||||
**Issue**: Static assets not loading
|
||||
|
||||
```bash
|
||||
# Check static directory exists
|
||||
ls -la static/
|
||||
|
||||
# Verify static mount in Docker
|
||||
docker run -it web-app ls -la /app/static
|
||||
|
||||
# Check browser console for 404 errors
|
||||
```
|
||||
|
||||
**Issue**: Templates not rendering
|
||||
|
||||
```bash
|
||||
# Check templates directory
|
||||
ls -la templates/
|
||||
|
||||
# Verify template files exist
|
||||
ls templates/*.html
|
||||
|
||||
# Check application logs for Jinja2 errors
|
||||
docker logs web-app
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Run with debug logging:
|
||||
|
||||
```python
|
||||
# In main.py, add:
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
# Or with uvicorn:
|
||||
uvicorn main:app --log-level debug
|
||||
```
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
### Documentation
|
||||
|
||||
- **FastAPI**: https://fastapi.tiangolo.com/
|
||||
- **MkDocs**: https://www.mkdocs.org/
|
||||
- **MkDocs Material**: https://squidfunk.github.io/mkdocs-material/
|
||||
- **Jinja2**: https://jinja.palletsprojects.com/
|
||||
- **HTTPX**: https://www.python-httpx.org/
|
||||
|
||||
### Related
|
||||
|
||||
- [Main README](../README.md)
|
||||
- [API Application README](../api/README.md)
|
||||
- [Helm Chart README](../helm/api7ee-demo-k8s/README.md)
|
||||
|
||||
## 🎯 Future Enhancements
|
||||
|
||||
Potential improvements:
|
||||
|
||||
- [ ] User authentication
|
||||
- [ ] WebSocket support for real-time updates
|
||||
- [ ] Progressive Web App (PWA) features
|
||||
- [ ] Advanced caching strategies
|
||||
- [ ] Internationalization (i18n)
|
||||
- [ ] Enhanced error pages
|
||||
|
||||
---
|
||||
|
||||
_FastAPI web application with integrated MkDocs documentation for API7 Enterprise demo._
|
||||
**Version**: 1.0.0 | **Port**: 8000 | **Framework**: FastAPI 0.104.1 | **Theme**: Material for MkDocs 9.5.3
|
||||
|
||||
Reference in New Issue
Block a user