Socle V004 – API Administration

Socle V004 - API Administration

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 : HEALTHY
  • 503 : 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

Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *