feat: Rust sensing server with full DensePose-compatible API
Replace Python FastAPI + WebSocket servers with a single 2.1MB Rust binary (wifi-densepose-sensing-server) that serves all UI endpoints: - REST: /health/*, /api/v1/info, /api/v1/pose/current, /api/v1/pose/stats, /api/v1/pose/zones/summary, /api/v1/stream/status - WebSocket: /api/v1/stream/pose (pose_data with 17 COCO keypoints), /ws/sensing (raw sensing_update stream on port 8765) - Static: /ui/* with no-cache headers WiFi-derived pose estimation: derive_pose_from_sensing() generates 17 COCO keypoints from CSI/WiFi signal data with motion-driven animation. Data sources: ESP32 CSI via UDP :5005, Windows WiFi via netsh, simulation fallback. Auto-detection probes each in order. UI changes: - Point all endpoints to Rust server on :8080 (was Python :8000) - Fix WebSocket sensing URL to include /ws/sensing path - Remove sensingOnlyMode gating — all tabs init normally - Remove api.service.js sensing-only short-circuit - Fix clearPingInterval bug in websocket.service.js Also removes obsolete k8s/ template manifests. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -1,287 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: wifi-densepose-config
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: config
|
||||
data:
|
||||
# Application Configuration
|
||||
ENVIRONMENT: "production"
|
||||
LOG_LEVEL: "info"
|
||||
DEBUG: "false"
|
||||
RELOAD: "false"
|
||||
WORKERS: "4"
|
||||
|
||||
# API Configuration
|
||||
API_PREFIX: "/api/v1"
|
||||
DOCS_URL: "/docs"
|
||||
REDOC_URL: "/redoc"
|
||||
OPENAPI_URL: "/openapi.json"
|
||||
|
||||
# Feature Flags
|
||||
ENABLE_AUTHENTICATION: "true"
|
||||
ENABLE_RATE_LIMITING: "true"
|
||||
ENABLE_WEBSOCKETS: "true"
|
||||
ENABLE_REAL_TIME_PROCESSING: "true"
|
||||
ENABLE_HISTORICAL_DATA: "true"
|
||||
ENABLE_TEST_ENDPOINTS: "false"
|
||||
METRICS_ENABLED: "true"
|
||||
|
||||
# Rate Limiting
|
||||
RATE_LIMIT_REQUESTS: "100"
|
||||
RATE_LIMIT_WINDOW: "60"
|
||||
|
||||
# CORS Configuration
|
||||
CORS_ORIGINS: "https://wifi-densepose.com,https://app.wifi-densepose.com"
|
||||
CORS_METHODS: "GET,POST,PUT,DELETE,OPTIONS"
|
||||
CORS_HEADERS: "Content-Type,Authorization,X-Requested-With"
|
||||
|
||||
# Database Configuration
|
||||
DATABASE_HOST: "postgres-service"
|
||||
DATABASE_PORT: "5432"
|
||||
DATABASE_NAME: "wifi_densepose"
|
||||
DATABASE_USER: "wifi_user"
|
||||
|
||||
# Redis Configuration
|
||||
REDIS_HOST: "redis-service"
|
||||
REDIS_PORT: "6379"
|
||||
REDIS_DB: "0"
|
||||
|
||||
# Hardware Configuration
|
||||
ROUTER_TIMEOUT: "30"
|
||||
CSI_BUFFER_SIZE: "1024"
|
||||
MAX_ROUTERS: "10"
|
||||
|
||||
# Model Configuration
|
||||
MODEL_PATH: "/app/models"
|
||||
MODEL_CACHE_SIZE: "3"
|
||||
INFERENCE_BATCH_SIZE: "8"
|
||||
|
||||
# Streaming Configuration
|
||||
MAX_WEBSOCKET_CONNECTIONS: "100"
|
||||
STREAM_BUFFER_SIZE: "1000"
|
||||
HEARTBEAT_INTERVAL: "30"
|
||||
|
||||
# Monitoring Configuration
|
||||
PROMETHEUS_PORT: "8080"
|
||||
METRICS_PATH: "/metrics"
|
||||
HEALTH_CHECK_PATH: "/health"
|
||||
|
||||
# Logging Configuration
|
||||
LOG_FORMAT: "json"
|
||||
LOG_FILE: "/app/logs/app.log"
|
||||
LOG_MAX_SIZE: "100MB"
|
||||
LOG_BACKUP_COUNT: "5"
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-config
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: nginx
|
||||
data:
|
||||
nginx.conf: |
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
use epoll;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for" '
|
||||
'rt=$request_time uct="$upstream_connect_time" '
|
||||
'uht="$upstream_header_time" urt="$upstream_response_time"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
client_max_body_size 10M;
|
||||
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/xml
|
||||
text/javascript
|
||||
application/json
|
||||
application/javascript
|
||||
application/xml+rss
|
||||
application/atom+xml
|
||||
image/svg+xml;
|
||||
|
||||
upstream wifi_densepose_backend {
|
||||
least_conn;
|
||||
server wifi-densepose-service:8000 max_fails=3 fail_timeout=30s;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name wifi-densepose.com;
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/tls.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/tls.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://wifi_densepose_backend;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
proxy_read_timeout 30s;
|
||||
}
|
||||
|
||||
location /ws {
|
||||
proxy_pass http://wifi_densepose_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 7d;
|
||||
proxy_send_timeout 7d;
|
||||
proxy_read_timeout 7d;
|
||||
}
|
||||
|
||||
location /health {
|
||||
access_log off;
|
||||
proxy_pass http://wifi_densepose_backend/health;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
location /metrics {
|
||||
access_log off;
|
||||
proxy_pass http://wifi_densepose_backend/metrics;
|
||||
proxy_set_header Host $host;
|
||||
allow 10.0.0.0/8;
|
||||
allow 172.16.0.0/12;
|
||||
allow 192.168.0.0/16;
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: postgres-init
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: postgres
|
||||
data:
|
||||
init-db.sql: |
|
||||
-- Create database if not exists
|
||||
CREATE DATABASE IF NOT EXISTS wifi_densepose;
|
||||
|
||||
-- Create user if not exists
|
||||
DO
|
||||
$do$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT FROM pg_catalog.pg_roles
|
||||
WHERE rolname = 'wifi_user') THEN
|
||||
|
||||
CREATE ROLE wifi_user LOGIN PASSWORD 'wifi_pass';
|
||||
END IF;
|
||||
END
|
||||
$do$;
|
||||
|
||||
-- Grant privileges
|
||||
GRANT ALL PRIVILEGES ON DATABASE wifi_densepose TO wifi_user;
|
||||
|
||||
-- Connect to the database
|
||||
\c wifi_densepose;
|
||||
|
||||
-- Create extensions
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
CREATE EXTENSION IF NOT EXISTS "pg_stat_statements";
|
||||
|
||||
-- Create tables
|
||||
CREATE TABLE IF NOT EXISTS pose_sessions (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
session_id VARCHAR(255) UNIQUE NOT NULL,
|
||||
router_id VARCHAR(255) NOT NULL,
|
||||
start_time TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
end_time TIMESTAMP WITH TIME ZONE,
|
||||
status VARCHAR(50) DEFAULT 'active',
|
||||
metadata JSONB,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS pose_data (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
session_id UUID REFERENCES pose_sessions(id),
|
||||
timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
pose_keypoints JSONB NOT NULL,
|
||||
confidence_scores JSONB,
|
||||
bounding_box JSONB,
|
||||
metadata JSONB,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS csi_data (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
session_id UUID REFERENCES pose_sessions(id),
|
||||
timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
router_id VARCHAR(255) NOT NULL,
|
||||
csi_matrix JSONB NOT NULL,
|
||||
phase_data JSONB,
|
||||
amplitude_data JSONB,
|
||||
metadata JSONB,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Create indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_pose_sessions_session_id ON pose_sessions(session_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_pose_sessions_router_id ON pose_sessions(router_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_pose_sessions_start_time ON pose_sessions(start_time);
|
||||
CREATE INDEX IF NOT EXISTS idx_pose_data_session_id ON pose_data(session_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_pose_data_timestamp ON pose_data(timestamp);
|
||||
CREATE INDEX IF NOT EXISTS idx_csi_data_session_id ON csi_data(session_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_csi_data_router_id ON csi_data(router_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_csi_data_timestamp ON csi_data(timestamp);
|
||||
|
||||
-- Grant table privileges
|
||||
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO wifi_user;
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO wifi_user;
|
||||
@@ -1,498 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: wifi-densepose
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: api
|
||||
version: v1
|
||||
spec:
|
||||
replicas: 3
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wifi-densepose
|
||||
component: api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: api
|
||||
version: v1
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "8080"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
serviceAccountName: wifi-densepose-sa
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: wifi-densepose
|
||||
image: wifi-densepose:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
name: http
|
||||
protocol: TCP
|
||||
- containerPort: 8080
|
||||
name: metrics
|
||||
protocol: TCP
|
||||
env:
|
||||
- name: ENVIRONMENT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: wifi-densepose-config
|
||||
key: ENVIRONMENT
|
||||
- name: LOG_LEVEL
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: wifi-densepose-config
|
||||
key: LOG_LEVEL
|
||||
- name: WORKERS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: wifi-densepose-config
|
||||
key: WORKERS
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: wifi-densepose-secrets
|
||||
key: DATABASE_URL
|
||||
- name: REDIS_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: wifi-densepose-secrets
|
||||
key: REDIS_URL
|
||||
- name: SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: wifi-densepose-secrets
|
||||
key: SECRET_KEY
|
||||
- name: JWT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: wifi-densepose-secrets
|
||||
key: JWT_SECRET
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: wifi-densepose-config
|
||||
resources:
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
limits:
|
||||
cpu: 2
|
||||
memory: 4Gi
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 30
|
||||
volumeMounts:
|
||||
- name: logs
|
||||
mountPath: /app/logs
|
||||
- name: data
|
||||
mountPath: /app/data
|
||||
- name: models
|
||||
mountPath: /app/models
|
||||
- name: config
|
||||
mountPath: /app/config
|
||||
readOnly: true
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
volumes:
|
||||
- name: logs
|
||||
emptyDir: {}
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: wifi-densepose-data-pvc
|
||||
- name: models
|
||||
persistentVolumeClaim:
|
||||
claimName: wifi-densepose-models-pvc
|
||||
- name: config
|
||||
configMap:
|
||||
name: wifi-densepose-config
|
||||
nodeSelector:
|
||||
kubernetes.io/os: linux
|
||||
tolerations:
|
||||
- key: "node.kubernetes.io/not-ready"
|
||||
operator: "Exists"
|
||||
effect: "NoExecute"
|
||||
tolerationSeconds: 300
|
||||
- key: "node.kubernetes.io/unreachable"
|
||||
operator: "Exists"
|
||||
effect: "NoExecute"
|
||||
tolerationSeconds: 300
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- wifi-densepose
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: postgres
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: postgres
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wifi-densepose
|
||||
component: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: postgres
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 999
|
||||
runAsGroup: 999
|
||||
fsGroup: 999
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:15-alpine
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
name: postgres
|
||||
env:
|
||||
- name: POSTGRES_DB
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secret
|
||||
key: POSTGRES_DB
|
||||
- name: POSTGRES_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secret
|
||||
key: POSTGRES_USER
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secret
|
||||
key: POSTGRES_PASSWORD
|
||||
- name: PGDATA
|
||||
value: /var/lib/postgresql/data/pgdata
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: 1
|
||||
memory: 2Gi
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- exec pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" -h 127.0.0.1 -p 5432
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- exec pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" -h 127.0.0.1 -p 5432
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
volumeMounts:
|
||||
- name: postgres-data
|
||||
mountPath: /var/lib/postgresql/data
|
||||
- name: postgres-init
|
||||
mountPath: /docker-entrypoint-initdb.d
|
||||
readOnly: true
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
volumes:
|
||||
- name: postgres-data
|
||||
persistentVolumeClaim:
|
||||
claimName: postgres-data-pvc
|
||||
- name: postgres-init
|
||||
configMap:
|
||||
name: postgres-init
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: redis
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: redis
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wifi-densepose
|
||||
component: redis
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: redis
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 999
|
||||
runAsGroup: 999
|
||||
fsGroup: 999
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7-alpine
|
||||
command:
|
||||
- redis-server
|
||||
- --appendonly
|
||||
- "yes"
|
||||
- --requirepass
|
||||
- "$(REDIS_PASSWORD)"
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
name: redis
|
||||
env:
|
||||
- name: REDIS_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: redis-secret
|
||||
key: REDIS_PASSWORD
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 1Gi
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- ping
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- redis-cli
|
||||
- ping
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
volumeMounts:
|
||||
- name: redis-data
|
||||
mountPath: /data
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
volumes:
|
||||
- name: redis-data
|
||||
persistentVolumeClaim:
|
||||
claimName: redis-data-pvc
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: nginx
|
||||
spec:
|
||||
replicas: 2
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wifi-densepose
|
||||
component: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: nginx
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 101
|
||||
runAsGroup: 101
|
||||
fsGroup: 101
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
- containerPort: 443
|
||||
name: https
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 80
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 80
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
volumeMounts:
|
||||
- name: nginx-config
|
||||
mountPath: /etc/nginx/nginx.conf
|
||||
subPath: nginx.conf
|
||||
readOnly: true
|
||||
- name: tls-certs
|
||||
mountPath: /etc/nginx/ssl
|
||||
readOnly: true
|
||||
- name: nginx-cache
|
||||
mountPath: /var/cache/nginx
|
||||
- name: nginx-run
|
||||
mountPath: /var/run
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- NET_BIND_SERVICE
|
||||
volumes:
|
||||
- name: nginx-config
|
||||
configMap:
|
||||
name: nginx-config
|
||||
- name: tls-certs
|
||||
secret:
|
||||
secretName: tls-secret
|
||||
- name: nginx-cache
|
||||
emptyDir: {}
|
||||
- name: nginx-run
|
||||
emptyDir: {}
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: component
|
||||
operator: In
|
||||
values:
|
||||
- nginx
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: wifi-densepose-sa
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
automountServiceAccountToken: true
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
namespace: wifi-densepose
|
||||
name: wifi-densepose-role
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods", "services", "endpoints"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps", "secrets"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: wifi-densepose-rolebinding
|
||||
namespace: wifi-densepose
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: wifi-densepose-sa
|
||||
namespace: wifi-densepose
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: wifi-densepose-role
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
324
k8s/hpa.yaml
324
k8s/hpa.yaml
@@ -1,324 +0,0 @@
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: wifi-densepose-hpa
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: autoscaler
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: wifi-densepose
|
||||
minReplicas: 3
|
||||
maxReplicas: 20
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 70
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 80
|
||||
- type: Pods
|
||||
pods:
|
||||
metric:
|
||||
name: websocket_connections_per_pod
|
||||
target:
|
||||
type: AverageValue
|
||||
averageValue: "50"
|
||||
- type: Object
|
||||
object:
|
||||
metric:
|
||||
name: nginx_ingress_controller_requests_rate
|
||||
describedObject:
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
name: nginx-service
|
||||
target:
|
||||
type: Value
|
||||
value: "1000"
|
||||
behavior:
|
||||
scaleDown:
|
||||
stabilizationWindowSeconds: 300
|
||||
policies:
|
||||
- type: Percent
|
||||
value: 10
|
||||
periodSeconds: 60
|
||||
- type: Pods
|
||||
value: 2
|
||||
periodSeconds: 60
|
||||
selectPolicy: Min
|
||||
scaleUp:
|
||||
stabilizationWindowSeconds: 60
|
||||
policies:
|
||||
- type: Percent
|
||||
value: 50
|
||||
periodSeconds: 60
|
||||
- type: Pods
|
||||
value: 4
|
||||
periodSeconds: 60
|
||||
selectPolicy: Max
|
||||
|
||||
---
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: nginx-hpa
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: nginx-autoscaler
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: nginx
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 60
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 70
|
||||
- type: Object
|
||||
object:
|
||||
metric:
|
||||
name: nginx_http_requests_per_second
|
||||
describedObject:
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
name: nginx-service
|
||||
target:
|
||||
type: Value
|
||||
value: "500"
|
||||
behavior:
|
||||
scaleDown:
|
||||
stabilizationWindowSeconds: 300
|
||||
policies:
|
||||
- type: Percent
|
||||
value: 20
|
||||
periodSeconds: 60
|
||||
selectPolicy: Min
|
||||
scaleUp:
|
||||
stabilizationWindowSeconds: 30
|
||||
policies:
|
||||
- type: Percent
|
||||
value: 100
|
||||
periodSeconds: 30
|
||||
- type: Pods
|
||||
value: 2
|
||||
periodSeconds: 30
|
||||
selectPolicy: Max
|
||||
|
||||
---
|
||||
# Vertical Pod Autoscaler for database optimization
|
||||
apiVersion: autoscaling.k8s.io/v1
|
||||
kind: VerticalPodAutoscaler
|
||||
metadata:
|
||||
name: postgres-vpa
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: postgres-vpa
|
||||
spec:
|
||||
targetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: postgres
|
||||
updatePolicy:
|
||||
updateMode: "Auto"
|
||||
resourcePolicy:
|
||||
containerPolicies:
|
||||
- containerName: postgres
|
||||
minAllowed:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
maxAllowed:
|
||||
cpu: 2
|
||||
memory: 4Gi
|
||||
controlledResources: ["cpu", "memory"]
|
||||
controlledValues: RequestsAndLimits
|
||||
|
||||
---
|
||||
apiVersion: autoscaling.k8s.io/v1
|
||||
kind: VerticalPodAutoscaler
|
||||
metadata:
|
||||
name: redis-vpa
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: redis-vpa
|
||||
spec:
|
||||
targetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: redis
|
||||
updatePolicy:
|
||||
updateMode: "Auto"
|
||||
resourcePolicy:
|
||||
containerPolicies:
|
||||
- containerName: redis
|
||||
minAllowed:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
maxAllowed:
|
||||
cpu: 1
|
||||
memory: 2Gi
|
||||
controlledResources: ["cpu", "memory"]
|
||||
controlledValues: RequestsAndLimits
|
||||
|
||||
---
|
||||
# Pod Disruption Budget for high availability
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: wifi-densepose-pdb
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: pdb
|
||||
spec:
|
||||
minAvailable: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wifi-densepose
|
||||
component: api
|
||||
|
||||
---
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: nginx-pdb
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: nginx-pdb
|
||||
spec:
|
||||
minAvailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wifi-densepose
|
||||
component: nginx
|
||||
|
||||
---
|
||||
# Custom Resource for advanced autoscaling (KEDA)
|
||||
apiVersion: keda.sh/v1alpha1
|
||||
kind: ScaledObject
|
||||
metadata:
|
||||
name: wifi-densepose-keda-scaler
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: keda-scaler
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
name: wifi-densepose
|
||||
pollingInterval: 30
|
||||
cooldownPeriod: 300
|
||||
idleReplicaCount: 3
|
||||
minReplicaCount: 3
|
||||
maxReplicaCount: 50
|
||||
fallback:
|
||||
failureThreshold: 3
|
||||
replicas: 6
|
||||
advanced:
|
||||
restoreToOriginalReplicaCount: true
|
||||
horizontalPodAutoscalerConfig:
|
||||
name: wifi-densepose-keda-hpa
|
||||
behavior:
|
||||
scaleDown:
|
||||
stabilizationWindowSeconds: 300
|
||||
policies:
|
||||
- type: Percent
|
||||
value: 10
|
||||
periodSeconds: 60
|
||||
scaleUp:
|
||||
stabilizationWindowSeconds: 60
|
||||
policies:
|
||||
- type: Percent
|
||||
value: 50
|
||||
periodSeconds: 60
|
||||
triggers:
|
||||
- type: prometheus
|
||||
metadata:
|
||||
serverAddress: http://prometheus-service.monitoring.svc.cluster.local:9090
|
||||
metricName: wifi_densepose_active_connections
|
||||
threshold: '80'
|
||||
query: sum(wifi_densepose_websocket_connections_active)
|
||||
- type: prometheus
|
||||
metadata:
|
||||
serverAddress: http://prometheus-service.monitoring.svc.cluster.local:9090
|
||||
metricName: wifi_densepose_request_rate
|
||||
threshold: '1000'
|
||||
query: sum(rate(http_requests_total{service="wifi-densepose"}[5m]))
|
||||
- type: prometheus
|
||||
metadata:
|
||||
serverAddress: http://prometheus-service.monitoring.svc.cluster.local:9090
|
||||
metricName: wifi_densepose_queue_length
|
||||
threshold: '100'
|
||||
query: sum(wifi_densepose_processing_queue_length)
|
||||
- type: redis
|
||||
metadata:
|
||||
address: redis-service.wifi-densepose.svc.cluster.local:6379
|
||||
listName: processing_queue
|
||||
listLength: '50'
|
||||
passwordFromEnv: REDIS_PASSWORD
|
||||
|
||||
---
|
||||
# Network Policy for autoscaling components
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: autoscaling-network-policy
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: autoscaling-network-policy
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: wifi-densepose
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: kube-system
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: monitoring
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
egress:
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: monitoring
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 9090
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
component: redis
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 6379
|
||||
280
k8s/ingress.yaml
280
k8s/ingress.yaml
@@ -1,280 +0,0 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: wifi-densepose-ingress
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: ingress
|
||||
annotations:
|
||||
# NGINX Ingress Controller annotations
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
|
||||
|
||||
# Rate limiting
|
||||
nginx.ingress.kubernetes.io/rate-limit: "100"
|
||||
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
|
||||
nginx.ingress.kubernetes.io/rate-limit-connections: "10"
|
||||
|
||||
# CORS configuration
|
||||
nginx.ingress.kubernetes.io/enable-cors: "true"
|
||||
nginx.ingress.kubernetes.io/cors-allow-origin: "https://wifi-densepose.com,https://app.wifi-densepose.com"
|
||||
nginx.ingress.kubernetes.io/cors-allow-methods: "GET,POST,PUT,DELETE,OPTIONS"
|
||||
nginx.ingress.kubernetes.io/cors-allow-headers: "Content-Type,Authorization,X-Requested-With"
|
||||
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
|
||||
|
||||
# Security headers
|
||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss: https:;" always;
|
||||
|
||||
# Load balancing
|
||||
nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"
|
||||
nginx.ingress.kubernetes.io/load-balance: "round_robin"
|
||||
|
||||
# Timeouts
|
||||
nginx.ingress.kubernetes.io/proxy-connect-timeout: "30"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "30"
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "30"
|
||||
|
||||
# Body size
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
|
||||
|
||||
# Certificate management (cert-manager)
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
cert-manager.io/acme-challenge-type: "http01"
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- wifi-densepose.com
|
||||
- api.wifi-densepose.com
|
||||
- app.wifi-densepose.com
|
||||
secretName: wifi-densepose-tls
|
||||
rules:
|
||||
- host: wifi-densepose.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-service
|
||||
port:
|
||||
number: 80
|
||||
- path: /health
|
||||
pathType: Exact
|
||||
backend:
|
||||
service:
|
||||
name: wifi-densepose-service
|
||||
port:
|
||||
number: 8000
|
||||
- host: api.wifi-densepose.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: wifi-densepose-service
|
||||
port:
|
||||
number: 8000
|
||||
- path: /api
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: wifi-densepose-service
|
||||
port:
|
||||
number: 8000
|
||||
- path: /docs
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: wifi-densepose-service
|
||||
port:
|
||||
number: 8000
|
||||
- path: /metrics
|
||||
pathType: Exact
|
||||
backend:
|
||||
service:
|
||||
name: wifi-densepose-service
|
||||
port:
|
||||
number: 8080
|
||||
- host: app.wifi-densepose.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
---
|
||||
# WebSocket Ingress (separate for sticky sessions)
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: wifi-densepose-websocket-ingress
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: websocket-ingress
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
|
||||
# WebSocket specific configuration
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-connect-timeout: "60"
|
||||
nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"
|
||||
nginx.ingress.kubernetes.io/affinity: "cookie"
|
||||
nginx.ingress.kubernetes.io/affinity-mode: "persistent"
|
||||
nginx.ingress.kubernetes.io/session-cookie-name: "wifi-densepose-ws"
|
||||
nginx.ingress.kubernetes.io/session-cookie-expires: "3600"
|
||||
nginx.ingress.kubernetes.io/session-cookie-max-age: "3600"
|
||||
nginx.ingress.kubernetes.io/session-cookie-path: "/ws"
|
||||
|
||||
# WebSocket upgrade headers
|
||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- ws.wifi-densepose.com
|
||||
secretName: wifi-densepose-ws-tls
|
||||
rules:
|
||||
- host: ws.wifi-densepose.com
|
||||
http:
|
||||
paths:
|
||||
- path: /ws
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: wifi-densepose-websocket
|
||||
port:
|
||||
number: 8000
|
||||
|
||||
---
|
||||
# Internal Ingress for monitoring and admin access
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: wifi-densepose-internal-ingress
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: internal-ingress
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
|
||||
# IP whitelist for internal access
|
||||
nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
|
||||
|
||||
# Basic auth for additional security
|
||||
nginx.ingress.kubernetes.io/auth-type: "basic"
|
||||
nginx.ingress.kubernetes.io/auth-secret: "wifi-densepose-basic-auth"
|
||||
nginx.ingress.kubernetes.io/auth-realm: "WiFi-DensePose Internal Access"
|
||||
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- internal.wifi-densepose.com
|
||||
secretName: wifi-densepose-internal-tls
|
||||
rules:
|
||||
- host: internal.wifi-densepose.com
|
||||
http:
|
||||
paths:
|
||||
- path: /metrics
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: wifi-densepose-internal
|
||||
port:
|
||||
number: 8080
|
||||
- path: /health
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: wifi-densepose-internal
|
||||
port:
|
||||
number: 8000
|
||||
- path: /api/v1/status
|
||||
pathType: Exact
|
||||
backend:
|
||||
service:
|
||||
name: wifi-densepose-internal
|
||||
port:
|
||||
number: 8000
|
||||
|
||||
---
|
||||
# Certificate Issuer for Let's Encrypt
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-prod
|
||||
spec:
|
||||
acme:
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
email: admin@wifi-densepose.com
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-prod
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
- dns01:
|
||||
cloudflare:
|
||||
email: admin@wifi-densepose.com
|
||||
apiTokenSecretRef:
|
||||
name: cloudflare-api-token
|
||||
key: api-token
|
||||
|
||||
---
|
||||
# Staging Certificate Issuer for testing
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-staging
|
||||
spec:
|
||||
acme:
|
||||
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
email: admin@wifi-densepose.com
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-staging
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
|
||||
---
|
||||
# Basic Auth Secret for internal access
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: wifi-densepose-basic-auth
|
||||
namespace: wifi-densepose
|
||||
type: Opaque
|
||||
data:
|
||||
# Generated with: htpasswd -nb admin password | base64
|
||||
# Default: admin:password (change in production)
|
||||
auth: YWRtaW46JGFwcjEkSDY1dnFkNDAkWGJBTHZGdmJQSVcuL1pLLkNPeS4wLwo=
|
||||
@@ -1,90 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: wifi-densepose
|
||||
labels:
|
||||
name: wifi-densepose
|
||||
app: wifi-densepose
|
||||
environment: production
|
||||
version: v1
|
||||
annotations:
|
||||
description: "WiFi-DensePose application namespace"
|
||||
contact: "devops@wifi-densepose.com"
|
||||
created-by: "kubernetes-deployment"
|
||||
spec:
|
||||
finalizers:
|
||||
- kubernetes
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ResourceQuota
|
||||
metadata:
|
||||
name: wifi-densepose-quota
|
||||
namespace: wifi-densepose
|
||||
spec:
|
||||
hard:
|
||||
requests.cpu: "8"
|
||||
requests.memory: 16Gi
|
||||
limits.cpu: "16"
|
||||
limits.memory: 32Gi
|
||||
persistentvolumeclaims: "10"
|
||||
pods: "20"
|
||||
services: "10"
|
||||
secrets: "20"
|
||||
configmaps: "20"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: LimitRange
|
||||
metadata:
|
||||
name: wifi-densepose-limits
|
||||
namespace: wifi-densepose
|
||||
spec:
|
||||
limits:
|
||||
- default:
|
||||
cpu: "1"
|
||||
memory: "2Gi"
|
||||
defaultRequest:
|
||||
cpu: "100m"
|
||||
memory: "256Mi"
|
||||
type: Container
|
||||
- default:
|
||||
storage: "10Gi"
|
||||
type: PersistentVolumeClaim
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: wifi-densepose-network-policy
|
||||
namespace: wifi-densepose
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: wifi-densepose
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: monitoring
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: ingress-nginx
|
||||
egress:
|
||||
- to: []
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 53
|
||||
- protocol: UDP
|
||||
port: 53
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: wifi-densepose
|
||||
- to: []
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
180
k8s/secrets.yaml
180
k8s/secrets.yaml
@@ -1,180 +0,0 @@
|
||||
# IMPORTANT: This is a template file for secrets configuration
|
||||
# DO NOT commit actual secret values to version control
|
||||
# Use kubectl create secret or external secret management tools
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: wifi-densepose-secrets
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: secrets
|
||||
type: Opaque
|
||||
data:
|
||||
# Database credentials (base64 encoded)
|
||||
# Example: echo -n "your_password" | base64
|
||||
DATABASE_PASSWORD: <BASE64_ENCODED_DB_PASSWORD>
|
||||
DATABASE_URL: <BASE64_ENCODED_DATABASE_URL>
|
||||
|
||||
# Redis credentials
|
||||
REDIS_PASSWORD: <BASE64_ENCODED_REDIS_PASSWORD>
|
||||
REDIS_URL: <BASE64_ENCODED_REDIS_URL>
|
||||
|
||||
# JWT and API secrets
|
||||
SECRET_KEY: <BASE64_ENCODED_SECRET_KEY>
|
||||
JWT_SECRET: <BASE64_ENCODED_JWT_SECRET>
|
||||
API_KEY: <BASE64_ENCODED_API_KEY>
|
||||
|
||||
# External service credentials
|
||||
ROUTER_SSH_KEY: <BASE64_ENCODED_SSH_PRIVATE_KEY>
|
||||
ROUTER_PASSWORD: <BASE64_ENCODED_ROUTER_PASSWORD>
|
||||
|
||||
# Monitoring credentials
|
||||
GRAFANA_ADMIN_PASSWORD: <BASE64_ENCODED_GRAFANA_PASSWORD>
|
||||
PROMETHEUS_PASSWORD: <BASE64_ENCODED_PROMETHEUS_PASSWORD>
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: postgres-secret
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: postgres
|
||||
type: Opaque
|
||||
data:
|
||||
# PostgreSQL credentials
|
||||
POSTGRES_USER: <BASE64_ENCODED_POSTGRES_USER>
|
||||
POSTGRES_PASSWORD: <BASE64_ENCODED_POSTGRES_PASSWORD>
|
||||
POSTGRES_DB: <BASE64_ENCODED_POSTGRES_DB>
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: redis-secret
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: redis
|
||||
type: Opaque
|
||||
data:
|
||||
# Redis credentials
|
||||
REDIS_PASSWORD: <BASE64_ENCODED_REDIS_PASSWORD>
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: tls-secret
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: tls
|
||||
type: kubernetes.io/tls
|
||||
data:
|
||||
# TLS certificate and key (base64 encoded)
|
||||
tls.crt: <BASE64_ENCODED_TLS_CERTIFICATE>
|
||||
tls.key: <BASE64_ENCODED_TLS_PRIVATE_KEY>
|
||||
|
||||
---
|
||||
# Example script to create secrets from environment variables
|
||||
# Save this as create-secrets.sh and run with proper environment variables set
|
||||
|
||||
# #!/bin/bash
|
||||
#
|
||||
# # Ensure namespace exists
|
||||
# kubectl create namespace wifi-densepose --dry-run=client -o yaml | kubectl apply -f -
|
||||
#
|
||||
# # Create main application secrets
|
||||
# kubectl create secret generic wifi-densepose-secrets \
|
||||
# --namespace=wifi-densepose \
|
||||
# --from-literal=DATABASE_PASSWORD="${DATABASE_PASSWORD}" \
|
||||
# --from-literal=DATABASE_URL="${DATABASE_URL}" \
|
||||
# --from-literal=REDIS_PASSWORD="${REDIS_PASSWORD}" \
|
||||
# --from-literal=REDIS_URL="${REDIS_URL}" \
|
||||
# --from-literal=SECRET_KEY="${SECRET_KEY}" \
|
||||
# --from-literal=JWT_SECRET="${JWT_SECRET}" \
|
||||
# --from-literal=API_KEY="${API_KEY}" \
|
||||
# --from-literal=ROUTER_SSH_KEY="${ROUTER_SSH_KEY}" \
|
||||
# --from-literal=ROUTER_PASSWORD="${ROUTER_PASSWORD}" \
|
||||
# --from-literal=GRAFANA_ADMIN_PASSWORD="${GRAFANA_ADMIN_PASSWORD}" \
|
||||
# --from-literal=PROMETHEUS_PASSWORD="${PROMETHEUS_PASSWORD}" \
|
||||
# --dry-run=client -o yaml | kubectl apply -f -
|
||||
#
|
||||
# # Create PostgreSQL secrets
|
||||
# kubectl create secret generic postgres-secret \
|
||||
# --namespace=wifi-densepose \
|
||||
# --from-literal=POSTGRES_USER="${POSTGRES_USER}" \
|
||||
# --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \
|
||||
# --from-literal=POSTGRES_DB="${POSTGRES_DB}" \
|
||||
# --dry-run=client -o yaml | kubectl apply -f -
|
||||
#
|
||||
# # Create Redis secrets
|
||||
# kubectl create secret generic redis-secret \
|
||||
# --namespace=wifi-densepose \
|
||||
# --from-literal=REDIS_PASSWORD="${REDIS_PASSWORD}" \
|
||||
# --dry-run=client -o yaml | kubectl apply -f -
|
||||
#
|
||||
# # Create TLS secrets from certificate files
|
||||
# kubectl create secret tls tls-secret \
|
||||
# --namespace=wifi-densepose \
|
||||
# --cert=path/to/tls.crt \
|
||||
# --key=path/to/tls.key \
|
||||
# --dry-run=client -o yaml | kubectl apply -f -
|
||||
#
|
||||
# echo "Secrets created successfully!"
|
||||
|
||||
---
|
||||
# External Secrets Operator configuration (if using external secret management)
|
||||
apiVersion: external-secrets.io/v1beta1
|
||||
kind: SecretStore
|
||||
metadata:
|
||||
name: vault-secret-store
|
||||
namespace: wifi-densepose
|
||||
spec:
|
||||
provider:
|
||||
vault:
|
||||
server: "https://vault.example.com"
|
||||
path: "secret"
|
||||
version: "v2"
|
||||
auth:
|
||||
kubernetes:
|
||||
mountPath: "kubernetes"
|
||||
role: "wifi-densepose"
|
||||
serviceAccountRef:
|
||||
name: "wifi-densepose-sa"
|
||||
|
||||
---
|
||||
apiVersion: external-secrets.io/v1beta1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: wifi-densepose-external-secrets
|
||||
namespace: wifi-densepose
|
||||
spec:
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
name: vault-secret-store
|
||||
kind: SecretStore
|
||||
target:
|
||||
name: wifi-densepose-secrets
|
||||
creationPolicy: Owner
|
||||
data:
|
||||
- secretKey: DATABASE_PASSWORD
|
||||
remoteRef:
|
||||
key: wifi-densepose/database
|
||||
property: password
|
||||
- secretKey: REDIS_PASSWORD
|
||||
remoteRef:
|
||||
key: wifi-densepose/redis
|
||||
property: password
|
||||
- secretKey: JWT_SECRET
|
||||
remoteRef:
|
||||
key: wifi-densepose/auth
|
||||
property: jwt_secret
|
||||
- secretKey: API_KEY
|
||||
remoteRef:
|
||||
key: wifi-densepose/auth
|
||||
property: api_key
|
||||
225
k8s/service.yaml
225
k8s/service.yaml
@@ -1,225 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: wifi-densepose-service
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: api
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "8080"
|
||||
prometheus.io/path: "/metrics"
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 8000
|
||||
targetPort: 8000
|
||||
protocol: TCP
|
||||
name: http
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: metrics
|
||||
selector:
|
||||
app: wifi-densepose
|
||||
component: api
|
||||
sessionAffinity: None
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: postgres-service
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: postgres
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 5432
|
||||
targetPort: 5432
|
||||
protocol: TCP
|
||||
name: postgres
|
||||
selector:
|
||||
app: wifi-densepose
|
||||
component: postgres
|
||||
sessionAffinity: None
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: redis-service
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: redis
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 6379
|
||||
targetPort: 6379
|
||||
protocol: TCP
|
||||
name: redis
|
||||
selector:
|
||||
app: wifi-densepose
|
||||
component: redis
|
||||
sessionAffinity: None
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-service
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: nginx
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: http
|
||||
- port: 443
|
||||
targetPort: 443
|
||||
protocol: TCP
|
||||
name: https
|
||||
selector:
|
||||
app: wifi-densepose
|
||||
component: nginx
|
||||
sessionAffinity: None
|
||||
loadBalancerSourceRanges:
|
||||
- 0.0.0.0/0
|
||||
|
||||
---
|
||||
# Headless service for StatefulSet (if needed for database clustering)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: postgres-headless
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: postgres
|
||||
spec:
|
||||
type: ClusterIP
|
||||
clusterIP: None
|
||||
ports:
|
||||
- port: 5432
|
||||
targetPort: 5432
|
||||
protocol: TCP
|
||||
name: postgres
|
||||
selector:
|
||||
app: wifi-densepose
|
||||
component: postgres
|
||||
|
||||
---
|
||||
# Internal service for monitoring
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: wifi-densepose-internal
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: internal
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: metrics
|
||||
- port: 8000
|
||||
targetPort: 8000
|
||||
protocol: TCP
|
||||
name: health
|
||||
selector:
|
||||
app: wifi-densepose
|
||||
component: api
|
||||
sessionAffinity: None
|
||||
|
||||
---
|
||||
# Service for WebSocket connections
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: wifi-densepose-websocket
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: websocket
|
||||
annotations:
|
||||
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "tcp"
|
||||
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "3600"
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 8000
|
||||
targetPort: 8000
|
||||
protocol: TCP
|
||||
name: websocket
|
||||
selector:
|
||||
app: wifi-densepose
|
||||
component: api
|
||||
sessionAffinity: ClientIP
|
||||
sessionAffinityConfig:
|
||||
clientIP:
|
||||
timeoutSeconds: 3600
|
||||
|
||||
---
|
||||
# Service Monitor for Prometheus (if using Prometheus Operator)
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: wifi-densepose-monitor
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: monitoring
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wifi-densepose
|
||||
component: api
|
||||
endpoints:
|
||||
- port: metrics
|
||||
interval: 30s
|
||||
path: /metrics
|
||||
scheme: http
|
||||
- port: http
|
||||
interval: 60s
|
||||
path: /health
|
||||
scheme: http
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- wifi-densepose
|
||||
|
||||
---
|
||||
# Pod Monitor for additional pod-level metrics
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PodMonitor
|
||||
metadata:
|
||||
name: wifi-densepose-pod-monitor
|
||||
namespace: wifi-densepose
|
||||
labels:
|
||||
app: wifi-densepose
|
||||
component: monitoring
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: wifi-densepose
|
||||
podMetricsEndpoints:
|
||||
- port: metrics
|
||||
interval: 30s
|
||||
path: /metrics
|
||||
- port: http
|
||||
interval: 60s
|
||||
path: /api/v1/status
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- wifi-densepose
|
||||
88
rust-port/wifi-densepose-rs/Cargo.lock
generated
88
rust-port/wifi-densepose-rs/Cargo.lock
generated
@@ -206,6 +206,7 @@ checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
"axum-macros",
|
||||
"base64",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
@@ -256,6 +257,17 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-macros"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
@@ -1451,6 +1463,12 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-range-header"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c"
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.10.1"
|
||||
@@ -1709,6 +1727,16 @@ version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "2.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
|
||||
dependencies = [
|
||||
"mime",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minicov"
|
||||
version = "0.3.8"
|
||||
@@ -3417,6 +3445,19 @@ dependencies = [
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.23"
|
||||
@@ -3486,6 +3527,31 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"http-range-header",
|
||||
"httpdate",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-layer"
|
||||
version = "0.3.3"
|
||||
@@ -3619,6 +3685,12 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
@@ -4028,6 +4100,22 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wifi-densepose-sensing-server"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"chrono",
|
||||
"clap",
|
||||
"futures-util",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wifi-densepose-signal"
|
||||
version = "0.1.0"
|
||||
|
||||
@@ -12,6 +12,7 @@ members = [
|
||||
"crates/wifi-densepose-cli",
|
||||
"crates/wifi-densepose-mat",
|
||||
"crates/wifi-densepose-train",
|
||||
"crates/wifi-densepose-sensing-server",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
[package]
|
||||
name = "wifi-densepose-sensing-server"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
description = "Lightweight Axum server for WiFi sensing UI with RuVector signal processing"
|
||||
license.workspace = true
|
||||
|
||||
[[bin]]
|
||||
name = "sensing-server"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
# Web framework
|
||||
axum = { workspace = true }
|
||||
tower-http = { version = "0.5", features = ["fs", "cors", "set-header"] }
|
||||
tokio = { workspace = true, features = ["full", "process"] }
|
||||
futures-util = "0.3"
|
||||
|
||||
# Serialization
|
||||
serde = { workspace = true }
|
||||
serde_json.workspace = true
|
||||
|
||||
# Logging
|
||||
tracing.workspace = true
|
||||
tracing-subscriber = { workspace = true }
|
||||
|
||||
# Time
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
|
||||
# CLI
|
||||
clap = { workspace = true }
|
||||
File diff suppressed because it is too large
Load Diff
23
ui/app.js
23
ui/app.js
@@ -65,18 +65,15 @@ class WiFiDensePoseApp {
|
||||
// Show notification to user
|
||||
this.showBackendStatus('Mock server active - testing mode', 'warning');
|
||||
} else {
|
||||
console.log('🔌 Initializing with real backend');
|
||||
console.log('🔌 Connecting to backend...');
|
||||
|
||||
// Verify backend is actually working
|
||||
try {
|
||||
const health = await healthService.checkLiveness();
|
||||
console.log('✅ Backend is available and responding:', health);
|
||||
this.showBackendStatus('Connected to real backend', 'success');
|
||||
console.log('✅ Backend responding:', health);
|
||||
this.showBackendStatus('Connected to Rust sensing server', 'success');
|
||||
} catch (error) {
|
||||
// DensePose API backend not running — sensing-only mode
|
||||
backendDetector.sensingOnlyMode = true;
|
||||
console.log('ℹ️ DensePose API not running — sensing-only mode via WebSocket on :8765');
|
||||
this.showBackendStatus('Sensing mode — live WiFi data via WebSocket', 'success');
|
||||
console.warn('⚠️ Backend not available:', error.message);
|
||||
this.showBackendStatus('Backend unavailable — start sensing-server', 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,36 +96,32 @@ class WiFiDensePoseApp {
|
||||
this.components.tabManager.onTabChange((newTab, oldTab) => {
|
||||
this.handleTabChange(newTab, oldTab);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Initialize individual tab components
|
||||
initializeTabComponents() {
|
||||
// Skip DensePose-dependent tabs in sensing-only mode
|
||||
const sensingOnly = backendDetector.sensingOnlyMode;
|
||||
|
||||
// Dashboard tab
|
||||
const dashboardContainer = document.getElementById('dashboard');
|
||||
if (dashboardContainer) {
|
||||
this.components.dashboard = new DashboardTab(dashboardContainer);
|
||||
if (!sensingOnly) {
|
||||
this.components.dashboard.init().catch(error => {
|
||||
console.error('Failed to initialize dashboard:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Hardware tab
|
||||
const hardwareContainer = document.getElementById('hardware');
|
||||
if (hardwareContainer) {
|
||||
this.components.hardware = new HardwareTab(hardwareContainer);
|
||||
if (!sensingOnly) this.components.hardware.init();
|
||||
this.components.hardware.init();
|
||||
}
|
||||
|
||||
// Live demo tab
|
||||
const demoContainer = document.getElementById('demo');
|
||||
if (demoContainer) {
|
||||
this.components.demo = new LiveDemoTab(demoContainer);
|
||||
if (!sensingOnly) this.components.demo.init();
|
||||
this.components.demo.init();
|
||||
}
|
||||
|
||||
// Sensing tab
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// API Configuration for WiFi-DensePose UI
|
||||
|
||||
export const API_CONFIG = {
|
||||
BASE_URL: 'http://localhost:8000', // FastAPI backend port
|
||||
BASE_URL: 'http://localhost:8080', // Rust sensing server port
|
||||
API_VERSION: '/api/v1',
|
||||
WS_PREFIX: 'ws://',
|
||||
WSS_PREFIX: 'wss://',
|
||||
@@ -111,8 +111,8 @@ export function buildWsUrl(endpoint, params = {}) {
|
||||
? API_CONFIG.WSS_PREFIX
|
||||
: API_CONFIG.WS_PREFIX;
|
||||
|
||||
// Use localhost:8000 for WebSocket connections to match FastAPI backend
|
||||
const host = 'localhost:8000';
|
||||
// Match Rust sensing server port
|
||||
const host = 'localhost:8080';
|
||||
let url = `${protocol}${host}${endpoint}`;
|
||||
|
||||
// Add query parameters
|
||||
|
||||
@@ -67,11 +67,6 @@ export class ApiService {
|
||||
// Generic request method
|
||||
async request(url, options = {}) {
|
||||
try {
|
||||
// In sensing-only mode, skip all DensePose API calls
|
||||
if (backendDetector.sensingOnlyMode) {
|
||||
throw new Error('DensePose API unavailable (sensing-only mode)');
|
||||
}
|
||||
|
||||
// Process request through interceptors
|
||||
const processed = await this.processRequest(url, options);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* always shows something.
|
||||
*/
|
||||
|
||||
const SENSING_WS_URL = 'ws://localhost:8765';
|
||||
const SENSING_WS_URL = 'ws://localhost:8765/ws/sensing';
|
||||
const RECONNECT_DELAYS = [1000, 2000, 4000, 8000, 16000];
|
||||
const MAX_RECONNECT_ATTEMPTS = 10;
|
||||
const SIMULATION_INTERVAL = 500; // ms
|
||||
|
||||
@@ -309,8 +309,11 @@ export class WebSocketService {
|
||||
clearTimeout(connection.reconnectTimer);
|
||||
}
|
||||
|
||||
// Clear ping interval
|
||||
this.clearPingInterval(connection.url);
|
||||
// Clear heartbeat timer
|
||||
if (connection.heartbeatTimer) {
|
||||
clearInterval(connection.heartbeatTimer);
|
||||
connection.heartbeatTimer = null;
|
||||
}
|
||||
|
||||
// Close WebSocket
|
||||
if (connection.ws.readyState === WebSocket.OPEN) {
|
||||
|
||||
Reference in New Issue
Block a user