Modèle asynchrone et codes de retour#

Toute création et toute suppression sont asynchrones. C’est le point qui surprend le plus souvent à l’intégration : un 202 ne dit pas que la ressource existe, il dit que la demande a été acceptée et enregistrée.

Les deux temps d’une requête#

        sequenceDiagram
  participant C as Appelant
  participant A as API
  participant W as Worker
  C->>A: POST /subnets
  A->>A: Prepare — valide, écrit "creating"
  A-->>C: 202 + ressource en creating
  A->>W: Dispatch (file d'attente)
  W->>W: Execute — netns, netif, dhcp
  W->>W: état → running (ou error)
  C->>A: GET /subnets/<name>
  A-->>C: 200 + state
    

Prepare est synchrone, dans le handler HTTP : il valide l’état, écrit l’état initial en base et répond. Execute est asynchrone : il fait le travail réseau réel, puis positionne l’état final.

Conséquence directe : un échec d”Execute ne peut pas être remonté dans la réponse HTTP. Il se lit dans l’état de la ressource, qui passe à error.

Attendre correctement#

Il n’y a pas de webhook ni de long-polling : l’appelant interroge GET /<type>/<name> jusqu’à un état stable.

until [ "$(curl -sf http://127.0.0.1:8080/subnets/sn-000001 | jq -r .state)" = running ]; do
  sleep 2
done

Trois règles pour un appelant robuste :

  • Toujours borner l’attente. Côté agent, dispatcher.timeout_seconds (300 s par défaut) borne les opérations qui attendent une transition ; l’appelant doit avoir sa propre borne.

  • Traiter ``error`` comme terminal, pas comme un échec transitoire. Un Execute en échec ne se rejoue pas tout seul.

  • Ne pas enchaîner sans vérifier. Créer un subnet dont le VPC est encore en creating échoue en 422 ; démarrer une VM sur un subnet en creating ou running est en revanche accepté.

Codes de retour#

Code

Signification

202

demande acceptée et enregistrée ; l’état passera à running ou error

200

lecture réussie (GET)

400

champ obligatoire manquant, corps invalide, iface_type inconnu, base64 invalide

404

ressource inexistante

409

conflit d’existence ou d’état : ressource déjà créée, ou suppression depuis un état qui ne l’autorise pas ; pour un VPC, subnets encore présents

422

dépendance absente ou pas prête : VPC parent d’un subnet, subnet d’une VM

500

erreur interne

Le corps d’erreur est uniforme : {"error": "…"}.

Idempotence#

Les créations ne sont pas idempotentes : recréer une ressource existante donne 409, pas 202. Un appelant qui rejoue une requête après un timeout réseau doit donc traiter 409 comme « déjà fait », après avoir vérifié l’état par un GET.

Les suppressions depuis l’état error sont acceptées mais best-effort : les ressources système peuvent n’avoir été créées que partiellement, et il n’y a pas de rollback — voir Cycle de vie des ressources.