Aller au contenu
English
Cloud medium

Ce que feint prouve, et ce qu'il ne prouve pas

Read this page in English

14 min de lecture

Un émulateur qui laisserait croire à ce qu'il ne vérifie pas serait pire qu'inutile. Cette page répond à une seule question, avant que vous n'installiez quoi que ce soit : que puis-je raisonnablement tester contre feint ? En résumé, le contrat d'API, le cycle de vie Terraform et le comportement de votre client sont testables ; les prix, les quotas, la capacité réelle et les permissions IAM ne le sont pas.

À la fin de cette page, vous saurez décider si un test donné a un sens ici, dire ce qui établit chaque verdict plutôt que de vous fier à une promesse, et reconnaître la limite qui peut coûter de l'argent.

  • Lire la matrice ligne par ligne, dans votre vocabulaire.
  • Distinguer un « oui » d'un « oui, avec un runtime ».
  • Identifier la limite la plus dangereuse, celle qui laisse fuir du trafic.
  • Comprendre pourquoi aucun pourcentage de couverture n'est publié.

Chaque ligne porte son verdict et ce qui l'établit. Un « non » n'est pas un trou en attente de comblement : c'est une décision assumée, avec une raison écrite et une date.

Ce que vous voulez validerVerdictCe qui l'établit, ou la limite
Syntaxe, plan et cycle de vie Terraform ou OpenTofuouila suite de conformité : apply, second plan vide, destroy
Un parcours complet avec scw, octl ou exoouila même exécution pilote les trois clients sur un seul émulateur
La forme des requêtes et des réponses, champ par champoui, avec un plafond énoncéchaque réponse est vérifiée contre la description d'API du fournisseur
Que votre client lit un champ que le vrai cloud renvoieoui, là où un enregistrement existeles enregistrements de formes arbitrent ; l'angle mort est compté
L'ordre des dépendances : ce qui refuse d'être suppriméoui, tant que la relation est synchroneles assertions de refus de chaque suite
Que votre code décode un refusouichaque suite exige des refus et échoue s'il n'y en a pas
Cloud-init, une connexion SSH, un pare-feu qui filtreavec un runtimedépend de la capacité firewall déclarée par l'hôte
Deux VPC qui ne peuvent pas se joindreOVN seulementdépend de la capacité isolation, jamais d'un nom de mode
Un répartiteur de charge qui distribue vraimentOVN, et selon le packil faut que le runtime sache et que le pack délègue
Qu'une machine annoncée running existe sur l'hôteOVN, par fournisseurune suite lit les affirmations de l'API puis les vérifie avec incus
Atteindre une adresse privée depuis l'hôteselon le modedépend de la capacité private_from_host
Un test au niveau du noyau : sysctl, modules, démarrageavec un runtime VMun conteneur partage le noyau de l'hôte
Le retry et le backoff face à un 429, un 5xx ou une panneoui, sur les opérations que vous armezl'injection de fautes, déterministe et éteinte par défaut
Qu'un identifiant d'image ou de type erroné soit rejetéoui, sur demande--strict-catalog refuse ce qui sort du catalogue que vous déclarez
Les quotas, la capacité réelle, les prixnonle catalogue est une liste blanche mesurée
L'authentification et les permissions IAMnonl'authentification est acceptée, jamais vérifiée
Une ressource qui reste en provisioning un momentoui, sur demande--consistency eventual fait avancer les états, une transition par lecture
Le stockage objet, et tout ce qui s'adresse en s3.<région>nonnon émulé, et le trafic part vraiment
Terraform contre Exoscaleoui, depuis le provider 0.71.0les versions antérieures sont refusées par agent utilisateur
Le multi-zone ou le multi-région chez Exoscalenonune zone par processus, et la raison vient du client
Du trafic qui traverse réellement une passerelle ou du NATnonles enregistrements bougent, les paquets non

« oui » signifie qu'un vrai client a piloté cette opération dans l'exécution de référence, et que la suite a affirmé quelque chose de la réponse. Cela ne veut pas dire que chaque champ de chaque réponse est correct : deux défauts sont restés des mois derrière un axe pourtant vert, et c'est exactement pourquoi le projet publie sept axes indépendants sans jamais les additionner.

« avec un runtime » signifie que le plan de contrôle répond sans lui, et que l'affirmation ne tient que si les machines sont réelles. La bonne façon de savoir est de demander à l'émulateur plutôt que de deviner :

Fenêtre de terminal
curl -s localhost:4599/_feint/health | jq .capabilities
{
"machines": false,
"addresses": false,
"firewall": false,
"isolation": false,
"own_kernel": false,
"balancing": false,
"private_from_host": false
}

Une capacité que personne ne déclare est lue comme absente, délibérément : un contrôle se saute lui-même plutôt que d'affirmer ce qu'aucun pilote n'a promis. Ce que chaque mode livre est détaillé dans Faire tourner de vraies machines.

« non » est une décision avec une raison, pas un oubli. Plusieurs de ces lignes changeraient si quelqu'un faisait le travail correspondant, et ce sont alors des tickets ouverts, pas des omissions.

La limite la plus importante : une exécution locale peut joindre le vrai cloud

Section intitulée « La limite la plus importante : une exécution locale peut joindre le vrai cloud »

C'est la seule limite de cette page qui peut vous coûter de l'argent. feint sert des API en local ; un client peut composer lui-même l'adresse d'un produit hors de ce périmètre, et ses requêtes repartent alors là où elles allaient.

Le cas mesuré est le stockage objet. Sur une configuration réelle, le même apply a créé son adresse IP sur l'émulateur puis a poursuivi vers s3.fr-par.scw.cloud, parce que le provider Terraform code cette adresse en dur pour ce produit. Seule une réponse 403 sur des identifiants factices a rendu l'opération inoffensive ce jour-là.

Ces cinq lignes reviennent le plus souvent, et chacune est un arbitrage explicite plutôt qu'un travail non fait.

Les identifiants ne sont vérifiés contre rien, sauf si vous le demandez. Par défaut, une création qui nomme une image ou un type de machine inexistant réussit : Scaleway répond 201 pour un UUID d'image qui n'existe nulle part, Outscale accepte ami-99999999. Les vrais clouds refusent les trois. Ce défaut n'est pas une négligence : l'émulateur n'a pas d'inventaire, donc les seuls identifiants qu'il pourrait reconnaître sont ceux qu'il invente, et une configuration qui code en dur un identifiant de production échouerait alors sur la seule chose qui n'a rien à voir avec ce qu'elle teste.

Le coût était réel, et la 0.13.0 donne de quoi le supprimer quand il gêne : --strict-catalog prend un fichier JSON où vous déclarez, par fournisseur, les images, gabarits et types de machines que votre projet autorise.

{
"scaleway": {"images": ["ubuntu_jammy"], "types": ["DEV1-S"]},
"outscale": {"images": ["ami-fe1a7001"], "types": ["tinav6.c1r1p2"]},
"exoscale": {"templates": ["Linux Ubuntu 22.04 LTS 64-bit"], "types": ["standard.medium"]}
}

Une création qui en sort est alors refusée dans la forme d'erreur propre à chaque cloud, pas dans un format maison : votre client rend son message habituel de ressource introuvable.

{"Errors":[{"Code":"5023","Details":"The ImageId 'ami-99999999' doesn't exist.","Type":"InvalidResource"}]}

Sans l'option, rien ne bouge : le mode de compatibilité est identique octet pour octet, et la phrase du dessus reste vraie mot pour mot. Un fournisseur que le fichier ne mentionne pas n'est pas contrôlé.

L'authentification est acceptée, jamais vérifiée. Aucune signature n'est contrôlée, sur aucun fournisseur. Les identifiants doivent seulement être bien formés, parce que les SDK en valident la forme côté client avant d'envoyer quoi que ce soit. La conséquence est directe : n'exposez jamais feint sur un réseau que vous ne contrôlez pas. C'est un outil de développement qui accorde tout à tout le monde, par construction.

Le catalogue est une liste blanche mesurée. Les types de machines, les images et leurs attributs viennent de valeurs relevées chez le fournisseur, pas d'un inventaire vivant. Les quotas, la capacité réelle et les prix n'y figurent donc pas, et aucun test de dépassement de quota n'a de sens ici.

Les transitions de cycle de vie sont immédiates. Un serveur passe de stopped à running pendant l'appel. Les états que les clients vérifient sont préservés, par exemple le refus de supprimer un serveur en cours de transition dont Terraform dépend. Mais un refus qui n'existerait que pendant un état transitoire ne peut pas se produire : sur un vrai compte Outscale, un instantané demandé avant qu'un volume ne se stabilise est refusé, alors qu'ici le volume est disponible tout de suite. Un script qui enchaîne les deux réussit en local et peut échouer sur le vrai cloud.

Le trafic ne traverse pas les passerelles. Chez Outscale, une passerelle ou du NAT déplacent des enregistrements, pas des paquets. La configuration s'applique, se replanifie à vide et se détruit ; ce qui n'existe pas, c'est le chemin réseau derrière.

Le plancher de version qui vous protège : Terraform et Exoscale

Section intitulée « Le plancher de version qui vous protège : Terraform et Exoscale »

Terraform pilote Exoscale depuis la version 0.71.0 du provider, et les versions antérieures sont refusées. Ce n'est pas une lubie : jusqu'à cette version, le provider publié construisait deux clients et un seul honorait la variable EXOSCALE_API_ENDPOINT, si bien qu'un apply ou un destroy se scindait entre l'émulateur et un compte facturé.

Ce n'était pas une crainte théorique. Un feint down lancé dans le répertoire de la stack d'exemple a envoyé cinq requêtes signées vers les serveurs d'Exoscale. L'émulateur a donc refusé ce client pendant dix jours, du 26 août au 5 septembre 2026, le temps que le correctif arrive en amont.

Depuis, le refus s'est transformé en plancher. Un provider plus ancien que 0.71.0 est reconnu à son agent utilisateur et reçoit un 400 qui nomme la version à épingler ; à partir de 0.71.0, l'apply passe. Deux conséquences concrètes pour qui suivait l'ancienne procédure : feint up ne s'arrête plus au seuil, et la variable FEINT_EXOSCALE_ALLOW_TERRAFORM a disparu, faute d'avoir encore quelque chose à lever. Le CLI exo, lui, n'a jamais été concerné et pilote ce fournisseur de bout en bout.

C'est un choix de méthode, et il explique la forme de toute cette page. Un chiffre unique laisse une affirmation faible profiter d'une forte. Dire « 94 % de couverture » mélangerait des opérations dont le comportement est démontré avec d'autres qui répondent seulement quelque chose de bien formé.

Le projet publie donc, pour la 0.13.0, deux nombres qui ne s'additionnent pas : 395 opérations montées, dont 375 pilotées par un vrai client dans l'exécution de référence. Les 20 restantes déclarent, à leur route, pourquoi aucun client officiel ne les atteint. La différence entre « monté », « sondé » et « piloté » est développée dans Mesurer la fidélité.

  • Le contrat d'API et le cycle de vie sont testables ; les prix, quotas et permissions ne le sont pas.
  • Un « non » est une décision datée, avec une raison écrite, jamais un oubli.
  • Une exécution locale peut joindre le vrai cloud : le stockage objet en est le cas mesuré.
  • Les identifiants ne sont pas vérifiés : une faute de frappe passe ici et casse en production.
  • L'authentification n'est jamais contrôlée, donc l'émulateur ne s'expose pas sur un réseau ouvert.
  • Les transitions sont immédiates, donc un refus propre à un état transitoire ne peut pas se reproduire.
  • Aucun pourcentage n'est publié, parce qu'un chiffre unique masquerait les affirmations faibles.

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