Aller au contenu
Cloud medium

feint : émuler Scaleway, Outscale et Exoscale en local

Read this page in English

30 min de lecture

Logo feint

feint est un émulateur local des API cloud européennes : il répond à la place de Scaleway, Outscale et Exoscale sur 127.0.0.1:4599, et vos clients officiels ne font pas la différence. Un binaire Go statique, un port, aucun compte et aucune facture. Ce guide montre comment l'installer en vérifiant ce que vous exécutez, brancher scw, oapi-cli, exo et Terraform dessus, puis obtenir de vraies machines derrière l'API. Public visé : développeurs et équipes plateforme qui testent du code cloud sans vouloir payer un compte pour chaque exécution.

  • Installer feint en vérifiant la signature Sigstore et la provenance du binaire.
  • Diagnostiquer l'hôte avant de démarrer, avec feint doctor.
  • Savoir quand une nouvelle version est publiée, sans appel réseau imposé.
  • Lire ce que l'émulateur a servi, sur la page qu'il expose lui-même.
  • Mesurer ce qu'un vrai client attend, avec le proxy d'enregistrement.
  • Brancher les trois CLI officiels sans copier une variable à la main.
  • Appliquer une configuration Terraform contre l'émulateur.
  • Faire tourner de vraies machines qui portent l'adresse publiée par l'API.
  • Ouvrir une session SSH sur une machine émulée, chez les trois fournisseurs.
  • Installer Incus et OVN sur Debian 13, câblage compris.
  • Situer la couverture réelle de chaque provider avant de vous appuyer dessus.

Pourquoi les clouds européens n'avaient pas d'émulateur

Section intitulée « Pourquoi les clouds européens n'avaient pas d'émulateur »

AWS a LocalStack, Azure a Azurite, et les clouds européens n'avaient rien. Concrètement, une équipe qui écrit du Terraform Scaleway ou du code SDK Outscale teste contre un compte payant, ou ne teste pas. Le premier choix transforme chaque exécution de CI en ligne de facture et chaque développeur en propriétaire de ressources oubliées ; le second laisse les erreurs remonter en production.

Un émulateur répond à ce besoin précis : il rejoue le protocole du fournisseur pour que le client officiel, celui que vous utiliserez vraiment, fonctionne sans quitter votre machine. Le site couvre déjà l'équivalent côté AWS avec Floci : la logique est la même, seul le périmètre change.

feint sert pour le moment trois fournisseurs sur un seul port. Les espaces d'URL ne se chevauchent pas, ce qui rend la cohabitation possible : Scaleway sert /<produit>/v<N>/…, Outscale répond en POST /api/v1/<Action>, Exoscale expose /v2/<ressource>. Un seul multiplexeur HTTP les héberge tous les trois, et le serveur refuse de démarrer si deux paquets revendiquent la même route.

  • Une machine Linux ou macOS en x86-64 ou ARM64.
  • cosign et jq pour la vérification d'installation, gh en option.
  • Les CLI officiels que vous voulez piloter : scw, oapi-cli, exo, Terraform ou OpenTofu.
  • Incus 6.0.4 minimum (7.2 recommandé) uniquement pour le mode machines réelles ; la procédure Debian 13, OVN compris, figure dans ce guide.

Rien de tout cela n'est nécessaire pour la partie principale : l'émulateur est un binaire statique sans dépendance, il tient son état en mémoire et n'a besoin d'aucun démon.

Comment installer feint et vérifier ce qu'on exécute

Section intitulée « Comment installer feint et vérifier ce qu'on exécute »

Téléchargez le binaire de la version, vérifiez qui l'a publié, puis vérifiez les octets. L'ordre compte : une somme de contrôle ne prouve rien si vous ne savez pas qui a produit la liste qui la contient. La release v0.8.0 publie les binaires, un fichier checksums.txt, sa signature Sigstore et une attestation de provenance SLSA.

  1. Récupérer les artefacts de la version.

    Fenêtre de terminal
    base=https://github.com/stephrobert/feint/releases/download/v0.8.0
    curl -fsSLO "$base/feint-linux-amd64"
    curl -fsSLO "$base/checksums.txt"
    curl -fsSLO "$base/checksums.txt.cosign.bundle"
  2. Vérifier la signature de la liste de sommes, avant de faire confiance à une seule ligne de son contenu.

    Fenêtre de terminal
    cosign verify-blob --bundle checksums.txt.cosign.bundle \
    --certificate-identity-regexp '^https://github\.com/stephrobert/feint/\.github/workflows/release\.yml@refs/tags/v' \
    --certificate-oidc-issuer https://token.actions.githubusercontent.com \
    checksums.txt

    La sortie attendue tient en deux mots : Verified OK. Toute autre réponse doit arrêter l'installation. Notez la précision du motif d'identité : il nomme le workflow de publication et le préfixe de tag, là où un motif large accepterait n'importe quel workflow du dépôt. Un dépôt compromis dont un workflow secondaire signerait un binaire ne passerait pas ce contrôle.

  3. Vérifier les octets contre la liste signée.

    Fenêtre de terminal
    sha256sum -c checksums.txt --ignore-missing

    Le résultat attendu est feint-linux-amd64: OK. Sans --ignore-missing, la commande échoue sur toutes les plateformes que vous n'avez pas téléchargées, ce qui ressemble à tort à un binaire corrompu.

  4. Installer le binaire et confirmer la version.

    Fenêtre de terminal
    install -m 0755 feint-linux-amd64 ~/.local/bin/feint
    feint version

    La sortie doit afficher v0.8.0.

Si vous préférez la provenance à la signature, gh vérifie quel workflow et quel commit ont produit le binaire :

Fenêtre de terminal
gh attestation verify feint-linux-amd64 --repo stephrobert/feint

Une image est publiée à chaque version, et elle sert le plan de contrôle seul. C'est la façon la plus courte de brancher l'émulateur sur un pipeline : un service, un port, aucun binaire à installer sur le runner.

Fenêtre de terminal
docker run --rm -p 127.0.0.1:4599:4599 \
ghcr.io/stephrobert/feint:v0.8.0@sha256:f19c61d60cfbd57e654d530c2c1d06090a4670ad7d26932bb9ff21a06b3f2fc3
curl -s http://127.0.0.1:4599/_feint/health | jq -c '{status, machines}'
{"status":"ok","machines":"none"}

L'image ne fait pas tourner de machines, et elle le dit : elle exécute feint serve --vm off, parce que les machines réelles restent une propriété du binaire sur un hôte Incus. Une image qui prétendrait le contraire serait précisément la demi-vérité que ce projet refuse ailleurs. Pour les vraies machines, voyez la page machines réelles.

Dans un pipeline, l'image se déclare comme un service ordinaire :

services:
feint:
image: ghcr.io/stephrobert/feint:v0.8.0@sha256:f19c61d60cfbd57e654d530c2c1d06090a4670ad7d26932bb9ff21a06b3f2fc3
ports:
- 4599:4599

Le runner retient les étapes jusqu'à ce que le contrôle de santé de l'image réponde, donc la première étape peut parler à l'émulateur immédiatement.

L'image se vérifie comme les binaires, avec la même identité de workflow :

Fenêtre de terminal
cosign verify ghcr.io/stephrobert/feint:v0.8.0 \
--certificate-identity-regexp '^https://github\.com/stephrobert/feint/\.github/workflows/release\.yml@refs/tags/v' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com

feint doctor inspecte la machine avant que vous ne perdiez du temps. Il contrôle le port, le runtime de machines disponible et ce qu'il peut prouver, la présence des clients officiels, et il signale les pièges connus de l'environnement.

Fenêtre de terminal
feint doctor

Sortie de feint doctor : port libre, runtime Incus détecté, clients officiels trouvés, avertissements sur les contrats et sur ProxyJump

La lecture est directe : ok valide un point, warn signale quelque chose qui n'empêche pas de travailler. Sur la capture ci-dessus, deux avertissements méritent une explication. Le premier, no contracts/ directory here, indique que les réponses ne seront pas confrontées aux descriptions d'API des fournisseurs, ce qui n'arrive que si vous lancez feint depuis le dépôt cloné. Le second, le ProxyJump sur 10.*, est un piège réel : cette plage est celle des réseaux privés émulés, et une règle SSH trop large fait échouer la connexion avec timed out during banner exchange alors que le serveur SSH écoute normalement.

Un avertissement ne fait jamais échouer doctor. Seul un élément cassé produit un code retour non nul, ce qui rend la commande utilisable telle quelle dans un script d'amorçage.

feint start détache le processus lui-même, attend qu'il réponde et indique où sont les journaux. Aucun &, aucun conteneur, aucun gestionnaire de services : un binaire Go statique sait se mettre en arrière-plan, là où un émulateur écrit en Java ou en Python délègue cette tâche à docker run -d.

Fenêtre de terminal
feint start
feint listening on 127.0.0.1:4599 (pid 1155265)
logs: /run/user/1000/feint/127.0.0.1_4599/feint.log

L'état se lit avec feint status, qui répond ce qui tourne, ce qui est monté et ce qu'un client a réellement piloté depuis le démarrage :

Fenêtre de terminal
feint status
running on 127.0.0.1:4599 (pid 2667884, since 2026-08-10T19:35:43Z)
resources 12
machines none
provider routes driven by a client
outscale 72 3
scaleway 57 7
exoscale 46 3

La colonne driven by a client est plus utile qu'elle n'en a l'air : elle distingue une route montée d'une route exercée, donc elle vous dit ce que votre test a vraiment traversé. Ici, sept routes Scaleway ont été traversées par les commandes scw de la section suivante, sur les 57 servies. Les autres verbes du cycle de vie sont feint stop, feint restart, feint logs et feint wait. Ce dernier interroge l'émulateur jusqu'à ce qu'il réponde : c'est le verbe de CI, celui qui remplace la boucle curl que chaque équipe finissait par écrire.

Quand un runtime de machines est actif, la ligne machines porte en plus ce que le mode sait prouver, incus-ovn (isolation: true) par exemple, ce qui évite d'aller lire l'API de santé pour une information qu'on veut d'un coup d'œil.

Le binaire porte vingt-et-un verbes, dont la moitié sert au quotidien et l'autre à mesurer l'émulateur lui-même. Le tableau les sépare selon cet usage, pour savoir tout de suite lesquels vous concernent.

CommandeCe qu'elle faitUsage
feint serveSert les trois clouds au premier plancourant
feint start / stop / restartMême chose en arrière-plan, et l'arrêtcourant
feint waitInterroge jusqu'à ce qu'il répondeCI
feint statusCe qui tourne, ce qui est monté, ce qu'un client a pilotécourant
feint logsLe journal de l'exécution détachéecourant
feint uiOuvre la page de l'émulateur, en lecture seulecourant
feint env <fournisseur>L'environnement d'un client officiel, pour evalcourant
feint doctorDiagnostique l'hôte : port, runtime, clients, piège SSHcourant
feint snapshotsave, load, list, rm de l'état courantcourant
feint cleanRetire machines, réseaux et règles créés par l'émulateurcourant
feint versionAffiche la version, --check compare à la dernièrecourant
feint catalogImprime l'inventaire émulé qu'un client lit avant de créerinspection
feint probePilote chaque route montée depuis sa description d'APIinspection
feint coverageCompare la surface amont à ce que les paquets serventmesure
feint proxyS'intercale entre un client et un cloud, et enregistremesure
feint transcriptRelit un enregistrement par verbesmesure
feint shapesEnregistre et vérifie l'arbre des champs d'un vrai cloudmesure
feint evidenceÉcrit l'artefact de couverture que la CI conserveprojet
feint docsRégénère les tableaux de couverture du dépôtprojet

feint env scaleway produit l'environnement dont le client officiel a besoin. La commande n'écrit que des lignes export sur la sortie standard, ce qui rend eval sûr ; les remarques et avertissements partent sur la sortie d'erreur.

Fenêtre de terminal
eval "$(feint env scaleway)"
scw instance server create name=web-01 type=DEV1-S image=ubuntu_jammy zone=fr-par-1
scw instance server list zone=fr-par-1

Le CLI Scaleway officiel pilote l'émulateur : création puis liste d'un serveur DEV1-S

Les variables produites pointent SCW_API_URL sur http://127.0.0.1:4599 et fournissent des identifiants bien formés mais fictifs. C'est suffisant : les SDK valident la forme des identifiants côté client avant d'émettre quoi que ce soit, et l'émulateur ne vérifie aucune signature.

Le serveur créé apparaît immédiatement en running dans la liste, alors que le protocole renvoie bien stopped à la création. L'explication n'est pas dans l'émulateur : scw instance server create envoie une action de démarrage juste après la création. Interrogé directement, l'émulateur répond ce que répondrait Scaleway :

Fenêtre de terminal
curl -s -X POST "http://127.0.0.1:4599/instance/v1/zones/fr-par-1/servers" \
-H 'Content-Type: application/json' \
-d '{"name":"etat-initial","commercial_type":"DEV1-S","image":"ubuntu_jammy"}' \
| jq -c '{name: .server.name, state: .server.state}'
{"name":"etat-initial","state":"stopped"}

Depuis la 0.8.0, Scaleway sert aussi block, soit les volumes, leurs instantanés et le catalogue de types. Le volume se crée avec le client officiel, et deux détails de forme méritent d'être connus parce qu'ils font échouer la commande avant même d'atteindre l'émulateur.

Fenêtre de terminal
scw block volume create name=donnees from-empty.size=10G perf-iops=5000 zone=fr-par-1
{"name":"donnees","type":"sbs","size":10000000000,"class":"sbs","iops":5000,"status":"available"}

La taille se note en 10G, un nombre d'octets étant refusé par le CLI là où la commande instance l'accepte, et perf-iops est obligatoire. Un détail d'implémentation vaut d'être signalé pour qui écrit un script : scw interroge /block/v1alpha1 quand le provider Terraform interroge /block/v1. Les deux orthographes répondent, ce qui évite d'avoir à choisir entre deux clients officiels du même cloud.

La séquence d'image dorée est servie de bout en bout : un instantané du volume, une image taillée dans cet instantané, puis la suppression dans l'ordre que l'API impose.

Fenêtre de terminal
snap=$(scw instance snapshot create name=snap-source volume-id="$vol" zone=fr-par-1 -o json | jq -r .id)
img=$(scw instance image create name=image-doree snapshot-id="$snap" arch=x86_64 zone=fr-par-1 -o json | jq -r .id)
scw instance image list zone=fr-par-1
["image-doree","ubuntu_jammy","debian_bookworm","debian_trixie","alpine","ubuntu_noble"]

L'image que vous créez apparaît à côté du catalogue figé, et l'ordre de suppression est celui du vrai cloud : tant que l'image existe, l'instantané dont elle est tirée refuse de partir, avec un message qui nomme le coupable.

{"precondition":"resource_still_in_use","resource":"snapshot",
"help_message":"the image 7f1db7e3-… is cut from this snapshot"}

C'est exactement l'ordre que Terraform parcourt quand un même plan retire les deux, ce qui rend ce refus utile plutôt que gênant. Une image taillée ici ne démarre toutefois rien : les octets d'un disque sont la seule chose qu'un émulateur ne peut pas fournir, et la limite est signalée au démarrage plutôt qu'à la création.

Les deux autres fournisseurs se branchent de la même façon, avec une nuance par client. feint env la signale sur la sortie d'erreur au lieu de vous laisser la découvrir.

Le client oapi-cli lit un profil JSON plutôt que l'environnement. La remarque affichée par feint env outscale le précise : il faut lui passer --config avec endpoints.api sur http://127.0.0.1:4599, le client ajoutant /api/v1 de lui-même.

Fenêtre de terminal
eval "$(feint env outscale)"
oapi-cli CreateNet --IpRange 10.0.0.0/16
oapi-cli ReadNets
{
"Nets":[
{
"IpRange":"10.0.0.0/16",
"NetId":"vpc-3a31b260",
"State":"available",
"Tags":[],
"Tenancy":"default"
}
],
"ResponseContext":{"RequestId":"3b25f637-a288-4839-b4aa-c3b1a709f6bb"}
}

Terraform et OpenTofu s'appliquent contre l'émulateur sur Scaleway et Outscale, et le provider Exoscale est refusé volontairement pour éviter un apply à cheval sur un compte facturé. Scaleway se détourne avec api_url, Outscale avec un bloc api dont le chemin porte /api/v1, et le cycle complet passe, second plan vide compris.

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

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

Le binaire sert sa propre page, à http://127.0.0.1:4599/_feint/ui, ouverte par feint ui. Elle montre côte à côte ce qui est monté, ce qui a été sondé et ce qu'un vrai client a piloté, sans jamais les additionner, plus l'inventaire de la session et un journal des appels. Le même anneau d'événements se lit par script sur /_feint/trace, et feint proxy enregistre ce qu'un client envoie à un vrai cloud.

Comment obtenir de vraies machines derrière l'API

Section intitulée « Comment obtenir de vraies machines derrière l'API »

Avec un runtime Incus, un serveur créé par l'API devient une machine réelle qui porte l'adresse publiée, applique les groupes de sécurité et accepte une session SSH. Quatre modes existent et ne délivrent pas la même chose : seul --vm incus-ovn isole deux VPC, au prix d'une adresse privée que l'hôte ne joint plus.

feint version --check demande à GitHub si une version plus récente existe, et affiche la commande pour l'installer. Deux principes gouvernent cette commande, et ils méritent d'être connus avant de la lancer : rien ne part sur le réseau tant que le drapeau n'est pas tapé, et le binaire ne se met jamais à jour tout seul.

Fenêtre de terminal
feint version --check

Trois réponses sont possibles selon ce que vous exécutez. Quand une version plus récente est publiée, la sortie donne la commande d'installation épinglée sur cette version précise :

a newer release is available: v0.8.0
base=https://github.com/stephrobert/feint/releases/download/v0.8.0
curl -fsSLO "$base/feint-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')"
curl -fsSLO "$base/checksums.txt"
sha256sum -c checksums.txt --ignore-missing
release notes: https://github.com/stephrobert/feint/releases/tag/v0.8.0

La commande proposée nomme la version, jamais latest. La raison est la même que dans la procédure d'installation plus haut : une référence mutable télécharge ce qui est le plus récent au moment de l'appel, et ce contenu ne peut plus être confronté à la somme de contrôle écrite juste en dessous.

Si vous êtes déjà à jour, la commande rappelle d'abord votre version, puis conclut en une ligne :

v0.8.0
this is the latest release

Le troisième cas concerne les binaires construits localement :

the latest release is v0.8.0 (this build reports "dev", which is not a released version)
https://github.com/stephrobert/feint/releases/tag/v0.8.0

Un binaire compilé depuis les sources porte dev, et une installation par go install porte une pseudo-version horodatée. Ni l'un ni l'autre ne se compare à une étiquette de version, donc l'outil annonce la dernière release sans prétendre que votre exemplaire est périmé.

La couverture est partielle, et elle est mesurée plutôt qu'annoncée. En v0.8.0, 220 routes sont montées au total. Le tableau reprend la maturité déclarée par le projet et la façon dont chaque fournisseur découpe la surface que son API publie :

FournisseurRoutes montéesServiDéclinéNon triéMaturitéProuvé par, en CI
Scaleway10232 %67 %0 %utilisableTerraform, OpenTofu, scw
Outscale7227 %65 %6 %démarrageTerraform, OpenTofu, oapi-cli
Exoscale4612 %67 %20 %démarrageexo

Les trois colonnes de pourcentage se lisent ensemble, et la troisième est celle qui compte. Décliné est une décision écrite : une opération que personne n'a l'intention d'émuler, avec sa raison dans le code. Non trié désigne ce sur quoi personne n'a encore statué, et Scaleway y est à zéro : chaque opération de sa surface a reçu un verdict. Une opération qui apparaît dans cette colonne fait échouer l'intégration continue tant qu'un humain n'a pas tranché.

Les dénominateurs diffèrent d'un fournisseur à l'autre, 315 opérations publiées côté Scaleway contre 263 côté Outscale et 374 côté Exoscale : comparer les pourcentages entre colonnes d'une même ligne a du sens, les comparer d'une ligne à l'autre beaucoup moins. Servi et non mesuré est l'état le moins défendable pour une route, c'est la logique du projet.

Lisez « prouvé par » au sens strict : ce sont les clients qu'un workflow pilote à chaque proposition de modification. Une suite qui existe dans le dépôt mais que l'intégration continue n'exécute pas n'y figure pas, la colonne étant désormais générée depuis le fichier de workflow lui-même.

Utilisable signifie qu'une configuration réaliste s'applique et se détruit. Démarrage veut dire que le protocole est juste et qu'un vrai client mène une charge de travail réelle, mais que la surface reste mince. Concrètement, Scaleway et Outscale supportent aujourd'hui un cycle Terraform complet, et Exoscale se pilote au CLI exo, le partage d'appels de son provider Terraform étant décrit plus haut. Les trois ouvrent une session SSH sur une machine réelle.

Cinq limites méritent d'être connues avant de vous appuyer sur l'outil. Elles sont toutes vérifiables en quelques commandes.

Les identifiants ne sont validés contre rien. Une création qui nomme une image inexistante réussit, là où le vrai cloud refuserait :

Fenêtre de terminal
scw instance server create name=fantome type=DEV1-S \
image=00000000-dead-beef-0000-000000000000 zone=fr-par-1

C'est délibéré, parce que l'émulateur n'a pas d'inventaire : refuser les identifiants inconnus casserait toute configuration qui référence une image de production. Le coût est réel : une faute de frappe dans un identifiant d'image passera ici et sera rattrapée en production.

En revanche, le démarrage refuse. Avec un runtime de machines, un identifiant que nul catalogue ne connaît ne fait plus booter une image de substitution : le serveur reste stopped et le journal nomme l'identifiant en cause.

level=ERROR msg="refusing to boot: the image identifier resolves to nothing this
emulator can run" provider=scaleway image=00000000-dead-beef-0000-000000000000
reason="the identifier is in no catalogue"

La distinction est celle qui compte pour un test : la création reste permise pour ne pas casser une configuration réelle, mais l'émulateur refuse de faire passer pour Ubuntu une image que vous n'avez pas demandée.

Le catalogue est une fiction. Types de serveurs, prix, images et zones forment une petite table figée. Elle existe parce que les clients la lisent avant de créer quoi que ce soit, mais toute réponse de capacité, de prix ou de disponibilité est décorative.

L'authentification est acceptée, jamais vérifiée. Aucune signature n'est contrôlée, sur aucun fournisseur :

Fenêtre de terminal
curl -s -o /dev/null -w '%{http_code}\n' \
"http://127.0.0.1:4599/instance/v1/zones/fr-par-1/servers"

La réponse est 200, sans le moindre jeton. feint ne doit donc jamais être exposé sur un réseau que vous ne maîtrisez pas : c'est un outil de développement qui accorde tout à tout le monde, par construction.

L'outil ne se contente d'ailleurs pas d'écouter sur 127.0.0.1 par défaut : feint serve refuse une adresse hors boucle locale tant que --expose-to-network n'est pas passé explicitement. La raison est mécanique plutôt que morale : hors loopback, la protection contre le détournement de DNS local ne peut plus distinguer ce qui est local, donc elle cesse de protéger quoi que ce soit. Avec un runtime de machines actif, ce qui devient alors joignable depuis le réseau est un moteur de conteneurs.

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 en revanche préservés : supprimer un serveur démarré est refusé avec {"type":"transient_state"}, parce que Terraform s'appuie sur cette erreur.

Le stockage objet n'est pas émulé. Le provider Terraform Scaleway construit l'adresse S3 en dur dans son code, donc la détourner demanderait une interception DNS et un certificat TLS accepté par le provider. Le CLI et les SDK, eux, honorent SCW_S3_ENDPOINT et peuvent déjà pointer vers un MinIO local.

SymptômeCauseSolution
404 Not Found sur scw instance server-type listLe CLI interroge /product-catalog/v2alpha1/, une API récente que l'émulateur ne monte pasUtiliser scw marketplace local-image list, ou consulter curl -s localhost:4599/_feint/routes
Feint does not serve /marketplace/v2/imagesLa route demandée n'existe pas dans le paquet ; le message le dit explicitementVérifier la route dans /_feint/routes avant d'insister
feint: no contract under contracts sur feint probeprobe a besoin des descriptions d'API livrées avec le dépôtLancer depuis le dépôt cloné, ou passer --contracts <répertoire>
warn no contracts/ directory here dans doctorMême cause, en avertissementSans effet si vous ne validez pas les réponses contre les contrats
gh attestation verify ne renvoie rienHors terminal interactif, la commande ne s'exprime que par son code retourContrôler echo $? ou ajouter --format json
timed out during banner exchange en SSH vers une machineUn ProxyJump du fichier ~/.ssh/config capture la plage 10.* des réseaux émulésRestreindre le motif Host, ou utiliser ssh -F /dev/null
Multiple variable sources detected avec TerraformUn profil Scaleway existe déjà sur le posteLire la colonne Currently using : le bloc provider l'emporte
Un mode --vm ne sépare pas deux VPCLe mode pont ne fournit pas l'isolationLire capabilities.isolation dans /_feint/health, et passer en --vm incus-ovn
the Exoscale Terraform provider only honours… en 400Ce provider partage ses appels entre l'émulateur et le vrai cloudUtiliser le CLI exo, ou assumer le partage avec FEINT_EXOSCALE_ALLOW_TERRAFORM=1
Terraform Outscale réessaie pendant six minutes puis expireLe endpoint du bloc api ne porte pas le segment /api/v1Écrire http://127.0.0.1:4599/api/v1, version comprise
feint serve refuse l'adresse demandéeUne adresse hors boucle locale est refusée par défautRester sur 127.0.0.1, ou passer --expose-to-network en connaissance de cause
REMOTE HOST IDENTIFICATION HAS CHANGED en SSHLes adresses sont réattribuées depuis le début du bloc à chaque labAjouter -o UserKnownHostsFile=/dev/null, ou purger l'entrée avec ssh-keygen -R <adresse>
Une adresse privée ne répond pas depuis l'hôteLe routeur OVN traduit les connexions venues de l'hôteLire capabilities.private_from_host, ou passer par l'adresse publique
La page /_feint/ui répond 404Elle n'est montée que sur la boucle localeL'ouvrir depuis la machine qui exécute l'émulateur
  • feint émule Scaleway, Outscale et Exoscale sur un seul port, 127.0.0.1:4599, sans compte ni facture.
  • Une image de conteneur signée branche l'émulateur sur une CI en trois lignes, plan de contrôle seul.
  • Un binaire Go statique qui se détache seul : ni Docker, ni démon, ni dépendance externe.
  • Les CLI officiels fonctionnent tels quels : feint env <fournisseur> produit l'environnement attendu, eval suffit.
  • Terraform pilote Scaleway et Outscale de bout en bout, apply, second plan vide et destroy compris.
  • Le provider Terraform Exoscale est refusé en 400 : il partagerait l'apply entre l'émulateur et un compte facturé.
  • feint ui sert une page depuis le binaire : servi contre piloté contre sondé, jamais additionnés, en lecture seule et sur la boucle locale.
  • feint proxy et feint transcript mesurent ce qu'un vrai client appelle et la forme exacte des réponses, identifiants caviardés.
  • Le mode machines est réel : le conteneur porte l'adresse publiée par l'API, et feint clean ne retire que ce que l'émulateur a créé.
  • On ouvre une session SSH sur une machine émulée chez les trois fournisseurs, à l'adresse que l'API publie.
  • Seul --vm incus-ovn isole deux VPC, au prix d'une adresse privée que l'hôte ne joint plus ; interrogez capabilities plutôt que de supposer.
  • feint version --check signale une nouvelle version et donne la commande épinglée ; FEINT_NO_UPDATE_CHECK=1 coupe tout appel réseau.
  • La couverture est partielle et assumée : 220 routes montées, 32 % de la surface Scaleway servie, 27 % chez Outscale, 12 % chez Exoscale.
  • La surface non triée est mesurée : 0 % en attente de décision chez Scaleway, 6 % chez Outscale, 20 % chez Exoscale.
  • Aucune signature n'est vérifiée, et feint serve refuse une adresse hors boucle locale sans --expose-to-network.

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