Aller au contenu
Cloud medium

feint : mesurer ce que l'émulateur sert et ce qu'un client attend

9 min de lecture

feint ne se contente pas de répondre : il dit ce qu'il a servi, ce qu'un client a réellement piloté, et ce qu'un vrai cloud renverrait à sa place. Ces trois mécanismes servent le même objectif, savoir si un test prouve quelque chose : une page d'introspection servie par le binaire, un proxy d'enregistrement qui mesure au lieu de deviner, et des snapshots pour rejouer un jeu de données autant de fois que nécessaire.

  • Lire la page que l'émulateur sert sur lui-même, et ses trois compteurs.
  • Distinguer une route montée, une route sondée et une route pilotée.
  • Enregistrer ce qu'un client officiel envoie, sans qu'un identifiant fuite.
  • Revenir à un état de test connu, autant de fois qu'il le faut.

Comment voir ce que l'émulateur a réellement servi

Section intitulée « Comment voir ce que l'émulateur a réellement servi »

feint ui ouvre une page que le binaire sert sur lui-même, à http://127.0.0.1:4599/_feint/ui. Pas de second port, pas de second processus, pas d'étape de construction : trois fichiers embarqués dans le binaire. Elle répond à la question que ni les journaux ni status ne traitent complètement : qu'est-ce qui a été monté, exercé, et par quoi.

Fenêtre de terminal
feint ui

La page de feint 0.7.3 : 175 routes montées, 13 pilotées par un vrai client, et l'inventaire des ressources créées par fournisseur

Le haut de la page est un compteur qui ne s'additionne pas, et c'est volontaire. Les trois nombres restent séparés parce qu'ils ne valent pas la même chose : une route montée existe, une route sondée répond correctement au protocole, une route pilotée par un vrai client est la seule dont le comportement soit démontré. La barre affiche la part sondée en hachuré plutôt qu'en plein, pour la même raison.

Le reste de la page montre l'inventaire de la session, lu depuis le magasin interne et non depuis une API de fournisseur, avec les attributs complets et une recherche ; l'écart avec la surface amont, produit par produit, où chaque opération refusée porte sa raison écrite ; et un journal des appels qui signale deux choses qu'aucun autre outil ne remonte : les champs qu'un client a envoyés et qu'aucun gestionnaire n'a lus, et ceux qu'une réponse a portés sans que la description d'API du fournisseur les définisse.

La page est en lecture seule et servie sur la boucle locale uniquement. Hors loopback elle n'est pas cachée, elle n'existe pas. Il n'y a aucune authentification, et c'est un choix argumenté plutôt qu'un oubli : un mot de passe protégerait la mauvaise frontière, puisque le risque est une page malveillante ouverte dans le navigateur de l'opérateur, laquelle hériterait de tout secret détenu par ce même navigateur.

Le même anneau d'événements est lisible par un script, ce qui en fait un mécanisme et pas seulement un écran :

Fenêtre de terminal
curl -s localhost:4599/_feint/trace \
| jq -r '.exchanges[] | "\(.method) \(.path) \(.status) \(.operation // "aucune route")"'
GET /v2/instance-type 200 exoscale/v2.list-instance-types
GET /v2/zone 200 exoscale/v2.list-zones
GET /v2/quota 200 exoscale/v2.list-quotas

Trois autres points d'entrée complètent l'ensemble pour l'outillage : /_feint/conformance porte le détail par opération, /_feint/resources publie l'inventaire, et /_feint/health répond l'état et les capacités du mode courant.

feint snapshot nomme l'état d'un émulateur en cours et permet d'y revenir. C'est le mécanisme qui rend un jeu de données de test atteignable une fois puis rejouable autant de fois que nécessaire.

Fenêtre de terminal
feint snapshot save etat-de-reference
feint snapshot list
saved 21 resources to /home/bob/.local/state/feint/snapshots/etat-de-reference.json
NAME RESOURCES BYTES SAVED
etat-de-reference 21 26472 2026-07-30T09:43:40Z

Après avoir supprimé toutes les ressources, feint snapshot load etat-de-reference répond loaded etat-de-reference: the emulator now holds 21 resources et l'inventaire est reconstitué. Le chargement remplace l'état, il ne fusionne pas : un jeu de test ne doit pas dépendre de ce que la session a fait avant lui.

feint proxy s'intercale entre un client officiel et un cloud, et écrit chaque échange dans un fichier ; feint transcript relit ce fichier par verbes. Le couple répond à une question que la documentation d'un fournisseur ne tranche pas : ce que le client appelle réellement, et la forme exacte des réponses qu'il reçoit.

L'usage prévu est un vrai compte, en lecture seule. La démonstration ci-dessous pointe le proxy sur l'émulateur lui-même, ce qui montre la mécanique sans facture ; seule l'adresse amont change dans le cas réel.

Fenêtre de terminal
feint proxy --upstream http://127.0.0.1:4599 --record enregistrement.jsonl --provider scaleway
eval "$(feint env scaleway --endpoint http://127.0.0.1:4600)"
scw instance server create name=via-proxy type=DEV1-S image=ubuntu_jammy zone=fr-par-1

feint transcript en tire une file de travail classée par nombre d'appels, c'est-à-dire les opérations qu'un client réclame et que personne n'a encore servies :

Fenêtre de terminal
feint transcript enregistrement.jsonl
already served, and exercised here (6):
2 1888 200,201 instance/v1/API.CreateServer
1 4734 200 instance/v1/API.ListServersTypes
1 506 200 instance/v1/API.GetImage
1 303 201 instance/v1/API.CreateIP

Le drapeau --shape donne l'arbre des champs réellement renvoyé, qui n'est pas ce que le SDK déclare pouvoir renvoyer, et --against compare cet arbre avec celui de l'émulateur pour lister les champs manquants ou mal typés.

response shape of instance/v1/API.ListServersTypes, as the real cloud returned it:
object servers
object servers.DEV1-L
string servers.DEV1-L.arch
bool servers.DEV1-L.capabilities.block_storage

Aucun identifiant n'atteint le fichier : la caviardage est une propriété du type enregistré, pas une étape qu'un appelant pourrait oublier. Les en-têtes suivent une liste d'autorisation, les corps une liste d'exclusion, parce qu'un corps est la mesure recherchée alors qu'un en-tête ne l'est pas. Le proxy n'écoute que sur la boucle locale, sauf --expose-to-network : chaque requête qui le traverse porte un identifiant valide.

feint shapes prolonge la logique côté vérification : il enregistre l'arbre des champs d'un vrai cloud, sans valeurs ni identifiants, ce qui rend le fichier publiable là où une transcription ne l'est pas, puis feint shapes --check compare l'émulateur à cet enregistrement hors ligne et sans identifiant.

  • La page est servie par le binaire, sur la boucle locale, en lecture seule et sans authentification par choix argumenté.
  • Servi, sondé et piloté ne s'additionnent pas : seule la dernière catégorie démontre un comportement.
  • feint proxy mesure au lieu de deviner ce qu'un client envoie, et caviarde les identifiants par construction.
  • feint transcript répond par verbes : quoi servir ensuite, quelle forme doit avoir la réponse, quels champs manquent.
  • Un snapshot remplace l'état, il ne le fusionne pas : un jeu de test ne dépend pas de ce qui l'a précédé.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn