14 – Admin API
Version : 4.0.0 Date : 2025-12-09
1. Introduction
L’Admin API expose des endpoints REST pour l’administration et le monitoring du Socle V4.
Endpoints principaux
| Endpoint | Description |
|---|---|
/admin/health |
État de santé |
/admin/workers |
État des workers |
/admin/config |
Configuration |
/admin/registry |
SharedDataRegistry |
/admin/metrics |
Métriques |
2. Configuration
2.1 application.yml
socle:
admin:
enabled: ${ADMIN_ENABLED:true}
path-prefix: ${ADMIN_PATH_PREFIX:/admin}
auth:
enabled: ${ADMIN_AUTH_ENABLED:false}
username: ${ADMIN_USERNAME:admin}
password: ${ADMIN_PASSWORD:}
2.2 Variables d’environnement
| Variable | Description | Défaut |
|---|---|---|
ADMIN_ENABLED |
Activer l’API admin | true |
ADMIN_PATH_PREFIX |
Préfixe des endpoints | /admin |
ADMIN_AUTH_ENABLED |
Activer l’authentification | false |
ADMIN_USERNAME |
Utilisateur admin | admin |
ADMIN_PASSWORD |
Mot de passe admin | – |
3. Endpoints Health
3.1 GET /admin/health
État de santé global de l’application.
Réponse :
{
"status": "HEALTHY",
"timestamp": "2025-12-09T10:30:00Z",
"uptime": "2h 30m 15s",
"unhealthyWorkers": [],
"components": {
"database": "UP",
"redis": "UP",
"techdb": "UP"
}
}
Codes HTTP :
200: HEALTHY503: UNHEALTHY ou DEGRADED
3.2 GET /admin/health/live
Liveness probe pour Kubernetes.
{
"status": "UP"
}
3.3 GET /admin/health/ready
Readiness probe pour Kubernetes.
{
"status": "READY",
"checks": {
"workers": "OK",
"database": "OK"
}
}
4. Endpoints Workers
4.1 GET /admin/workers
Liste tous les workers et leur état.
{
"workers": [
{
"name": "kafka-consumer",
"status": "RUNNING",
"lastHeartbeat": "2025-12-09T10:29:55Z",
"healthy": true,
"stats": {
"processed": 12345,
"errors": 2
}
},
{
"name": "order-processor",
"status": "RUNNING",
"lastHeartbeat": "2025-12-09T10:29:58Z",
"healthy": true,
"stats": {
"ordersProcessed": 567
}
}
],
"total": 2,
"healthy": 2,
"unhealthy": 0
}
4.2 GET /admin/workers/{name}
Détails d’un worker spécifique.
{
"name": "kafka-consumer",
"status": "RUNNING",
"healthy": true,
"startPriority": 10,
"stopPriority": 90,
"scheduled": false,
"passive": false,
"cycleIntervalMs": 1000,
"lastHeartbeat": "2025-12-09T10:29:55Z",
"stats": {
"processed": 12345,
"errors": 2,
"lastOffset": 98765
}
}
4.3 POST /admin/workers/{name}/stop
Arrête un worker spécifique.
curl -X POST http://localhost:8080/admin/workers/kafka-consumer/stop
4.4 POST /admin/workers/{name}/start
Redémarre un worker arrêté.
curl -X POST http://localhost:8080/admin/workers/kafka-consumer/start
5. Endpoints Configuration
5.1 GET /admin/config
Configuration actuelle (sans secrets).
{
"appName": "socle-v4",
"envName": "PROD",
"region": "MTQ",
"version": "4.0.0",
"execId": "socle-v4-abc123",
"kvbus": {
"mode": "redis"
},
"techdb": {
"enabled": true
},
"logging": {
"forwarder": {
"enabled": true,
"transportMode": "http"
}
}
}
5.2 GET /admin/config/env
Variables d’environnement (filtrées).
{
"APP_NAME": "socle-v4",
"ENV_NAME": "PROD",
"REGION": "MTQ",
"HTTP_PORT": "8080",
"KVBUS_MODE": "redis"
}
6. Endpoints Registry
6.1 GET /admin/registry
Contenu du SharedDataRegistry.
{
"database.connected": true,
"metrics.requests.total": 12345,
"metrics.errors.total": 23,
"batch.current.id": "batch-001",
"worker.kafka.offset": 98765
}
6.2 GET /admin/registry/{key}
Valeur d’une clé spécifique.
{
"key": "metrics.requests.total",
"value": 12345,
"healthLevel": "NORMAL"
}
6.3 GET /admin/registry/health
Clés avec leur niveau de santé.
{
"database.connected": "CRITICAL",
"cache.available": "IMPORTANT",
"metrics.requests.total": "INFO"
}
6.4 GET /admin/registry/unhealthy
Clés en état unhealthy.
[
{
"key": "external.api.available",
"value": false,
"healthLevel": "CRITICAL"
}
]
7. Endpoints TechDB (V4)
7.1 GET /admin/techdb/offsets
Tous les offsets stockés.
{
"offsets": [
{
"sourceName": "kafka",
"partitionKey": "orders-topic-0",
"lastSequence": 123456,
"lastUpdated": "2025-12-09T10:30:00Z"
},
{
"sourceName": "nats",
"partitionKey": "events.orders",
"lastSequence": 789012,
"lastUpdated": "2025-12-09T10:29:55Z"
}
]
}
7.2 GET /admin/techdb/workers
État des workers persisté.
{
"workers": [
{
"workerId": "kafka-consumer-001",
"status": "RUNNING",
"lastHeartbeat": "2025-12-09T10:30:00Z",
"metadata": {
"messagesPerMinute": 523
}
}
]
}
7.3 GET /admin/techdb/events
Événements techniques récents.
{
"events": [
{
"id": 123,
"createdAt": "2025-12-09T10:25:00Z",
"type": "PIPELINE_ERROR",
"payload": {
"pipeline": "order-processing",
"error": "Connection timeout"
}
}
]
}
8. Endpoints Resilience
8.1 GET /admin/resilience/circuits
État des circuit breakers.
{
"circuits": {
"payment-gateway": "CLOSED",
"inventory-api": "HALF_OPEN",
"notification-service": "OPEN"
}
}
8.2 POST /admin/resilience/circuits/{name}/reset
Reset un circuit breaker.
curl -X POST http://localhost:8080/admin/resilience/circuits/notification-service/reset
9. Endpoints Scheduler
9.1 GET /admin/scheduler/jobs
Jobs schedulés.
{
"jobs": [
{
"jobId": "worker:daily-report",
"type": "cron",
"schedule": "0 0 6 * * ?",
"scheduledAt": "2025-12-09T06:00:00Z"
},
{
"jobId": "worker:health-check",
"type": "interval",
"intervalMs": 30000,
"scheduledAt": "2025-12-09T10:00:00Z"
}
]
}
9.2 POST /admin/scheduler/jobs/{jobId}/trigger
Déclenche un job immédiatement.
curl -X POST http://localhost:8080/admin/scheduler/jobs/worker:daily-report/trigger
10. Endpoints LogForwarder (V4)
10.1 GET /admin/logforwarder/status
État du LogForwarder.
{
"enabled": true,
"transportMode": "http",
"queueSize": 23,
"queueCapacity": 10000,
"fallbackCount": 0,
"lastFlush": "2025-12-09T10:29:55Z"
}
10.2 POST /admin/logforwarder/flush
Force le flush des logs.
curl -X POST http://localhost:8080/admin/logforwarder/flush
10.3 POST /admin/logforwarder/replay
Rejoue les logs en fallback.
curl -X POST http://localhost:8080/admin/logforwarder/replay
11. Implémentation
package eu.lmvi.socle.admin;
@RestController
@RequestMapping("${socle.admin.path-prefix:/admin}")
public class AdminRestApi {
@Autowired private Supervisor supervisor;
@Autowired private SharedDataRegistry registry;
@Autowired private SocleConfiguration config;
@Autowired(required = false) private TechDbManager techDb;
@Autowired(required = false) private Scheduler scheduler;
// === Health ===
@GetMapping("/health")
public ResponseEntity<HealthResponse> health() {
HealthStatus status = supervisor.getGlobalHealth();
HttpStatus httpStatus = status == HealthStatus.HEALTHY
? HttpStatus.OK
: HttpStatus.SERVICE_UNAVAILABLE;
return ResponseEntity.status(httpStatus).body(new HealthResponse(
status,
Instant.now(),
getUptime(),
supervisor.getUnhealthyWorkers()
));
}
@GetMapping("/health/live")
public ResponseEntity<Map<String, String>> live() {
return ResponseEntity.ok(Map.of("status", "UP"));
}
@GetMapping("/health/ready")
public ResponseEntity<Map<String, Object>> ready() {
HealthStatus status = supervisor.getGlobalHealth();
if (status != HealthStatus.HEALTHY) {
return ResponseEntity.status(503).body(Map.of(
"status", "NOT_READY",
"unhealthy", supervisor.getUnhealthyWorkers()
));
}
return ResponseEntity.ok(Map.of("status", "READY"));
}
// === Workers ===
@GetMapping("/workers")
public Map<String, Object> workers() {
Map<String, WorkerState> states = supervisor.getAllWorkerStates();
return Map.of(
"workers", states.values(),
"total", states.size(),
"healthy", states.values().stream().filter(WorkerState::isHealthy).count(),
"unhealthy", states.values().stream().filter(s -> !s.isHealthy()).count()
);
}
@GetMapping("/workers/{name}")
public ResponseEntity<WorkerState> worker(@PathVariable String name) {
WorkerState state = supervisor.getWorkerState(name);
return state != null
? ResponseEntity.ok(state)
: ResponseEntity.notFound().build();
}
// === Config ===
@GetMapping("/config")
public Map<String, Object> config() {
return Map.of(
"appName", config.getApp_name(),
"envName", config.getEnv_name(),
"region", config.getRegion(),
"version", config.getVersion(),
"execId", config.getExec_id()
);
}
// === Registry ===
@GetMapping("/registry")
public Map<String, Object> registry() {
return registry.getAll();
}
@GetMapping("/registry/{key}")
public ResponseEntity<Map<String, Object>> registryKey(@PathVariable String key) {
return registry.get(key)
.map(v -> ResponseEntity.ok(Map.of(
"key", key,
"value", v,
"healthLevel", registry.getHealthLevel(key)
)))
.orElse(ResponseEntity.notFound().build());
}
// ... autres endpoints
}
12. Sécurité
12.1 Authentification Basic
# Avec authentification
curl -u admin:secret http://localhost:8080/admin/workers
# En-tête Authorization
curl -H "Authorization: Basic YWRtaW46c2VjcmV0" http://localhost:8080/admin/workers
12.2 Endpoints publics
Les endpoints suivants sont accessibles sans authentification :
/admin/health/admin/health/live/admin/health/ready
13. Bonnes pratiques
DO
- Activer l’authentification en production
- Utiliser HTTPS pour l’API admin
- Limiter l’accès réseau à l’API admin
- Monitorer les accès à l’API admin
DON’T
- Ne pas exposer l’API admin publiquement
- Ne pas désactiver l’authentification en production
- Ne pas logger les credentials
14. Références
- 08-SUPERVISOR – Supervision
- 10-SECURITY – Sécurité
- 15-METRICS – Métriques

Laisser un commentaire