Fournisseurs, ressources et sources de données
Pourquoi
Jusqu'ici, le cours a travaillé avec des fournisseurs qui ne sortent pas de votre poste : random tire des valeurs au hasard, local écrit des fichiers. C'était voulu, pour apprendre le cycle plan, apply, destroy sans risque ni facture. Mais l'équipe de Signalements n'a pas besoin de fichiers locaux : elle a besoin d'un réseau privé, d'instances, d'une base, d'un bucket chez Scaleway. Pour cela, Terraform doit savoir parler à l'API de Scaleway, et c'est le rôle du fournisseur Scaleway.
Le passage aux fournisseurs réels pose trois questions que l'on évite à ses dépens.
- Quelle version du fournisseur ? Le fournisseur Scaleway publie une version presque chaque semaine. Si chaque personne de l'équipe, et le pipeline, en téléchargent une différente, le même code produit des plans différents. Une nouvelle version peut renommer un attribut, changer une valeur par défaut, corriger un bogue dont votre code dépendait.
- D'où vient ce binaire ? Un fournisseur est un programme que vous exécutez avec vos identifiants cloud. Un fournisseur piégé pourrait les exfiltrer, ou créer des ressources à votre insu. Savoir vérifier ce que l'on télécharge est une question de sécurité, pas de confort.
- Avec quels identifiants ? La tentation d'écrire la clé d'API dans le code « pour que ça marche » est réelle, et elle finit dans Git.
Cette leçon répond à ces trois questions, puis écrit les premières vraies ressources de Signalements : le réseau privé pn-signalements et le bucket des pièces jointes.
Les concepts
Le cœur et les fournisseurs
Terraform est en réalité deux programmes. Le cœur (Terraform Core, le binaire terraform ou tofu) lit la configuration, construit le graphe des dépendances, compare l'état voulu à l'état connu, calcule le plan et orchestre son exécution. Il ne sait rien de Scaleway, d'AWS ou de PostgreSQL.
Les fournisseurs (providers) sont des programmes séparés, un par plateforme, qui savent traduire « créer un réseau privé » en appels d'API. La documentation de HashiCorp résume le partage : les fournisseurs sont « des binaires exécutables invoqués par Terraform Core par RPC », et ils sont responsables de l'initialisation des bibliothèques d'accès à l'API, de l'authentification auprès de la plateforme, et de la définition des ressources et sources de données qu'ils proposent.
flowchart LR
subgraph poste["Votre poste ou l'agent de CI"]
core["terraform<br/>(cœur)"]
p1["terraform-provider-scaleway<br/>(processus fils)"]
p2["terraform-provider-random<br/>(processus fils)"]
core <-->|"gRPC"| p1
core <-->|"gRPC"| p2
end
p1 -->|"HTTPS + X-Auth-Token"| api["API Scaleway"]
Le cœur lance chaque fournisseur comme un processus fils, et dialogue avec lui en gRPC. Chaque fournisseur expose un schéma : la liste de ses ressources, de leurs arguments et de leurs attributs, avec leur type et leur caractère obligatoire, facultatif ou calculé. C'est ce schéma qui permet au cœur de vérifier votre configuration (terraform validate) sans appeler l'API.
On peut voir ce découpage à l'œuvre. Pendant un terraform apply qui dure quelques secondes (ici avec la ressource time_sleep du fournisseur time), la liste des processus fils de terraform montre le fournisseur :
$ ps -o pid,ppid,args --ppid $(pgrep -x terraform)
PID PPID COMMAND
890390 890274 .terraform/providers/registry.terraform.io/hashicorp/time/0.14.2/linux_amd64/terraform-provider-time_v0.
Le binaire vit dans .terraform/providers/, rangé par registre, espace de noms, nom, version et plateforme. Son nom se termine par _x5 : le numéro de la version du protocole de plugin qu'il parle.
L'adresse source d'un fournisseur
Un fournisseur est identifié par une adresse source en trois parties : nom-d-hôte/espace-de-noms/type. Pour celui de Scaleway, registry.terraform.io/scaleway/scaleway : le registre public de HashiCorp, l'espace de noms scaleway (l'éditeur), le type scaleway. Le nom d'hôte se sous-entend : on écrit scaleway/scaleway.
C'est ici que Terraform et OpenTofu divergent sans bruit. Pour Terraform, le nom d'hôte implicite est registry.terraform.io. Pour OpenTofu, sa documentation est explicite : il vaut registry.opentofu.org. La même ligne source = "scaleway/scaleway" désigne donc deux registres différents selon l'outil. Les fournisseurs publiés y sont les mêmes binaires, mais le fichier de verrouillage enregistre l'adresse complète : un dépôt utilisé alternativement par terraform et par tofu verra son fichier de verrouillage changer. On en reparle plus bas.
Les fournisseurs se rangent en trois catégories chez HashiCorp, qui apparaissent au téléchargement :
| Catégorie | Qui le maintient | Exemples |
|---|---|---|
| Officiel | HashiCorp | hashicorp/random, hashicorp/local, hashicorp/aws |
| Partenaire | L'éditeur de la plateforme, vérifié par HashiCorp | scaleway/scaleway, ovh/ovh |
| Communautaire | N'importe qui | Des milliers de fournisseurs de qualité très variable |
Les contraintes de version
Le bloc required_providers, dans le bloc terraform, déclare chaque fournisseur utilisé, son adresse source, et une contrainte de version : l'ensemble des versions acceptables. La syntaxe est commune à Terraform et OpenTofu :
| Opérateur | Signification | Exemple |
|---|---|---|
= ou rien | Exactement cette version | = 2.84.0 |
!= | Toutes sauf celle-ci | != 2.80.0 |
>, >=, <, <= | Comparaison | >= 2.60, < 3.0 |
~> | Seul le dernier composant écrit peut augmenter | ~> 2.84 |
L'opérateur ~> (« pessimiste ») trompe souvent. La documentation le formule ainsi : il autorise seulement le composant le plus à droite à augmenter. Donc :
~> 2.84accepte2.84.0,2.85.3,2.99.0, mais pas3.0.0;~> 2.84.0accepte2.84.1,2.84.7, mais pas2.85.0.
Les versions de préversion (3.0.0-beta1) ne sont jamais choisies par un opérateur de comparaison : il faut les nommer exactement avec =.
La recommandation de HashiCorp distingue deux cas, et elle est bonne. Dans la configuration racine, celle que l'on applique (ici le dépôt signalements-iac), on borne des deux côtés avec ~>, pour ne jamais recevoir une version majeure par surprise. Dans un module réutilisable (cours Terraform avancé : modules, tests, état), on ne met qu'un minimum (>= 2.60), pour ne pas empêcher ceux qui l'utilisent de monter de version.
Le bloc terraform accepte aussi required_version, une contrainte sur la version du cœur lui-même : >= 1.10 refuse de travailler avec une version trop ancienne, qui ne comprendrait pas certaines constructions.
Le fichier de verrouillage
Une contrainte décrit un ensemble de versions acceptables. Mais pour que tout le monde utilise la même version, il faut se souvenir du choix : c'est le rôle du fichier .terraform.lock.hcl, un fichier de verrouillage au sens où l'entendent tous les gestionnaires de dépendances. terraform init le crée au premier passage, et l'utilise ensuite : tant qu'une version enregistrée satisfait la contrainte, c'est elle qui est installée, même si une plus récente existe.
Il enregistre trois choses par fournisseur : la version choisie, la contrainte qui a servi au choix, et des sommes de contrôle du paquet. Deux formats de sommes coexistent :
zh:(zip hash) : la somme SHA-256 de l'archive.zipofficielle publiée par le registre, pour chaque plateforme. Ce format ne sait pas vérifier un fournisseur déjà décompressé.h1:(hash scheme 1) : une somme calculée sur le contenu du paquet, indépendante de la forme d'archive. C'est le format préféré.
Si un paquet téléchargé ne correspond à aucune somme enregistrée, terraform init refuse de l'installer, avec un message qui le dit : le paquet actuel ne correspond à aucune des sommes de contrôle enregistrées précédemment. C'est un modèle de confiance au premier usage : le premier init fait confiance au registre, les suivants vérifient qu'on reçoit la même chose.
Important
Le fichier .terraform.lock.hcl se versionne avec le code. Le répertoire .terraform/, lui, ne se versionne jamais : il contient les binaires téléchargés (45 Mo pour le seul fournisseur Scaleway) et, on le verra, parfois des informations sur l'état.
Pour monter de version, on change la contrainte si nécessaire, puis on lance terraform init -upgrade, qui ignore le choix enregistré et prend la version la plus récente satisfaisant la contrainte. La mise à jour du fichier de verrouillage passe alors par une demande de fusion relue, comme n'importe quelle montée de dépendance.
Les modules, eux, ne sont pas verrouillés : la documentation le précise, Terraform sélectionne toujours la version la plus récente qui satisfait la contrainte. On y reviendra dans le cours avancé.
Ressources, arguments et attributs
Une ressource est un objet que Terraform gère de bout en bout : il le crée, le met à jour, le détruit. Elle se déclare par un bloc resource "type" "nom". Le type (scaleway_vpc_private_network) vient du fournisseur : son préfixe avant le premier tiret bas désigne le fournisseur. Le nom (signalements) est local à votre configuration ; il ne sert qu'à y faire référence, et n'a aucun lien avec le nom de l'objet chez Scaleway.
Le schéma d'une ressource sépare ses champs en trois familles, et il est utile de savoir les lire :
| Famille | Qui fournit la valeur | Exemple sur scaleway_vpc_private_network |
|---|---|---|
| Argument obligatoire | Vous | (aucun pour cette ressource) |
| Argument facultatif | Vous, ou le fournisseur par défaut | name, vpc_id, tags, region |
| Attribut calculé | Le fournisseur, après création | id, created_at, organization_id |
Certains champs sont à la fois facultatifs et calculés : si vous ne donnez pas de region, le fournisseur utilise sa région par défaut et la rend visible dans l'état. On lit ce schéma dans la documentation de chaque ressource, ou directement depuis le fournisseur, avec terraform providers schema -json.
L'attribut id mérite une remarque : chez Scaleway, il contient en général la localisation et l'identifiant, sous la forme fr-par/11111111-... pour une ressource régionale, ou fr-par-1/... pour une ressource zonale. C'est ce qu'il faut passer aux autres ressources qui y font référence.
Les sources de données
Une source de données (data source) lit un objet sans le gérer : Terraform ne le crée, ne le modifie ni ne le détruit jamais. Elle se déclare par un bloc data. Trois usages reviennent sans cesse :
- retrouver un objet créé ailleurs, à la main ou par une autre équipe : le projet Scaleway
signalements, créé au premier cours cloud, avecdata "scaleway_account_project"; - interroger un catalogue : l'identifiant de l'image Ubuntu 24.04 dans une zone, avec
data "scaleway_marketplace_image"; - lire une information d'environnement : le projet par défaut, l'adresse IP de l'agent de CI.
Une source de données est lue pendant le plan, sauf si l'un de ses arguments dépend d'une valeur encore inconnue (un attribut calculé d'une ressource pas encore créée) : la lecture est alors repoussée à l'application.
Tip
Une source de données qui ne trouve rien fait échouer le plan. C'est souvent ce que l'on veut : mieux vaut s'arrêter que créer des ressources dans le mauvais projet parce que le nom a changé.
Les alias de fournisseur
Un bloc provider configure une instance du fournisseur : une région, une zone, un projet par défaut. Pour viser deux régions dans la même configuration, on déclare un second bloc avec un alias, et chaque ressource qui doit l'utiliser le désigne par l'argument provider :
provider "scaleway" {
alias = "amsterdam"
region = "nl-ams"
zone = "nl-ams-1"
}
resource "scaleway_object_bucket" "copies" {
provider = scaleway.amsterdam
name = "signalements-copies-exemple"
}Le bloc sans alias reste la configuration par défaut, utilisée par toutes les ressources qui ne disent rien. Chez Scaleway, la plupart des ressources acceptent aussi directement un argument region ou zone : l'alias devient utile quand toute une partie de la configuration vise ailleurs, ou quand il faut un autre profil d'identifiants (un autre projet, une autre organisation).
En pratique
On part du dépôt signalements-iac des leçons précédentes. Créez un répertoire scaleway/ pour cette leçon : la configuration y sera lue par terraform validate, et vous pourrez lancer plan avec vos identifiants si vous voulez voir ce qu'elle créerait.
Déclarer le fournisseur
Fichier versions.tf :
terraform {
required_version = ">= 1.10"
required_providers {
scaleway = {
source = "scaleway/scaleway"
version = "~> 2.84"
}
}
}Puis l'initialisation, dont voici la sortie réelle :
$ terraform init -no-color
Initializing the backend...
Initializing provider plugins...
- Finding scaleway/scaleway versions matching "~> 2.84"...
- Installing scaleway/scaleway v2.84.0...
- Installed scaleway/scaleway v2.84.0 (signed by a HashiCorp partner, key ID F5BF26CADF6F9614)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://developer.hashicorp.com/terraform/cli/plugins/signing
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
La version installée est la plus récente qui satisfait la contrainte : 2.84.0 au 5 octobre 2026. Trois lignes comptent :
Finding ... matching: Terraform a interrogé le registre pour la liste des versions, puis a appliqué la contrainte.signed by a HashiCorp partner, key ID ...: la liste des sommes de contrôle publiée avec le fournisseur est signée par une clé GPG de l'éditeur, enregistrée auprès du registre ; Terraform a vérifié cette signature, puis la somme de l'archive téléchargée.Terraform has created a lock file: le choix est désormais enregistré.
Le fichier créé :
$ cat .terraform.lock.hcl
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/scaleway/scaleway" {
version = "2.84.0"
constraints = "~> 2.84"
hashes = [
"h1:8ovPEDIEIbhp3puR8V26i07Gb99gBxr5AU71HemFRJ4=",
"zh:08d18a6e946a4d578324a6c2667537df6cd2292ad5044af5f4ae2eed51b51e77",
"zh:7197a12f04984af58bc6242b619f303aaf7a3badf93e35251d48699265f146f9",
...
]
}
Une seule somme h1: : celle de la plateforme du poste (linux_amd64), calculée sur le paquet effectivement installé. Les sommes zh:, elles, couvrent toutes les plateformes publiées (treize ici), parce qu'elles viennent de la liste signée du registre.
Préparer le fichier pour toute l'équipe
Si une collègue travaille sur un Mac à processeur Apple, son terraform init ajoutera une somme h1: pour darwin_arm64, et le fichier changera dans sa prochaine demande de fusion. Pour éviter ces modifications au fil de l'eau, on enregistre d'emblée les plateformes de l'équipe et de la CI :
$ terraform providers lock -no-color -platform=linux_amd64 -platform=darwin_arm64 -platform=windows_amd64
- Retrieved scaleway/scaleway 2.84.0 for darwin_arm64 (signed by a HashiCorp partner, key ID F5BF26CADF6F9614)
- Fetching scaleway/scaleway 2.84.0 for windows_amd64...
- Retrieved scaleway/scaleway 2.84.0 for windows_amd64 (signed by a HashiCorp partner, key ID F5BF26CADF6F9614)
- Obtained scaleway/scaleway checksums for linux_amd64; All checksums for this platform were already tracked in the lock file
- Obtained scaleway/scaleway checksums for darwin_arm64; Additional checksums for this platform are now tracked in the lock file
- Obtained scaleway/scaleway checksums for windows_amd64; Additional checksums for this platform are now tracked in the lock file
Success! Terraform has updated the lock file.
La commande télécharge le paquet officiel de chaque plateforme demandée, vérifie sa signature, et ajoute sa somme h1: : le fichier en compte maintenant trois. Versionnez-le.
Configurer le fournisseur sans clé dans le code
Le fichier providers.tf ne contient que des valeurs non secrètes :
provider "scaleway" {
region = "fr-par"
zone = "fr-par-1"
}Où le fournisseur trouve-t-il alors sa clé ? Sa documentation décrit trois méthodes, dans cet ordre de priorité :
- les variables d'environnement
SCW_ACCESS_KEYetSCW_SECRET_KEY; - les arguments
access_keyetsecret_keyécrits dans le blocprovider; - le fichier de configuration partagé de la CLI
scw,~/.config/scw/config.yaml(ou le chemin deSCW_CONFIG_PATH), avec son profil actif ou celui désigné par l'argumentprofile.
Le premier point surprend : une variable d'environnement l'emporte sur une valeur écrite dans le code. Les autres réglages suivent la même logique, avec leurs variables : SCW_DEFAULT_PROJECT_ID, SCW_DEFAULT_ORGANIZATION_ID, SCW_DEFAULT_REGION (fr-par si rien n'est précisé) et SCW_DEFAULT_ZONE (fr-par-1).
En pratique : sur votre poste, le fichier de la CLI configuré au premier cours cloud suffit, et le fournisseur lit le même profil que scw. En CI, le pipeline reçoit SCW_ACCESS_KEY et SCW_SECRET_KEY par ses secrets (leçon 12). Le code ne contient jamais de clé.
Retrouver le projet et une image
Fichier donnees.tf :
data "scaleway_account_project" "signalements" {
name = "signalements"
}
data "scaleway_marketplace_image" "ubuntu" {
label = "ubuntu_noble"
instance_type = "PRO2-XXS"
}scaleway_account_projectretrouve le projet par son nom ; son attributidsera passé aux ressources, pour qu'elles soient créées dans ce projet quel que soit le projet par défaut de la personne qui applique. C'est une protection contre l'erreur du premier cours : une ressource créée dans le mauvais projet parce que le profil actif n'était pas le bon.scaleway_marketplace_imagetraduit le libelléubuntu_nobleen identifiant d'image dans la zone par défaut ;instance_typesélectionne la variante compatible avec ce type d'instance. Les instances de la leçon 10 l'utiliseront.
Le réseau privé et le bucket
Fichier reseau.tf :
resource "scaleway_vpc" "signalements" {
name = "vpc-signalements"
project_id = data.scaleway_account_project.signalements.id
tags = ["app=signalements", "geree-par=terraform"]
}
resource "scaleway_vpc_private_network" "signalements" {
name = "pn-signalements"
vpc_id = scaleway_vpc.signalements.id
project_id = data.scaleway_account_project.signalements.id
tags = ["app=signalements", "geree-par=terraform"]
ipv4_subnet {
subnet = "172.16.20.0/22"
}
}Fichier stockage.tf :
resource "scaleway_object_bucket" "pieces_jointes" {
name = "signalements-pj-exemple"
project_id = data.scaleway_account_project.signalements.id
tags = {
app = "signalements"
geree-par = "terraform"
}
versioning {
enabled = true
}
timeouts {
default = "10m"
}
}Quelques détails, tous lus dans le schéma du fournisseur 2.84 :
- Les étiquettes sont une liste de chaînes sur le VPC et le réseau privé, mais une table (
map) sur le bucket. C'est le reflet des API sous-jacentes (les étiquettes d'Object Storage suivent le modèle S3). Une erreur de type est signalée parterraform validate. ipv4_subnetest un bloc imbriqué : son attributsubnetest facultatif et calculé (Scaleway choisit une plage si vous n'en donnez pas, ce que la leçon réseau du cours cloud déconseillait).versioningest un bloc imbriqué à une seule occurrence au plus. Le nom du bucket doit être unique dans la région : remplacezexemplepar votre suffixe (la leçon 5 le générera).- Le bloc
timeoutsfixe la durée maximale d'attente de l'opération ; seules les ressources dont le schéma le prévoit l'acceptent (le bucket acceptedefault, l'instance acceptecreate,read,update,deleteetdefault; le réseau privé n'en a pas).
Vérifier sans rien créer
$ terraform fmt
$ terraform validate -no-color
Success! The configuration is valid.
terraform validate charge le schéma du fournisseur et vérifie la configuration : noms d'arguments, types, blocs autorisés, références existantes. Il n'appelle pas l'API et n'a besoin d'aucun identifiant. Il ne sait donc pas si le nom du bucket est déjà pris, ni si le projet signalements existe : ce sont des erreurs de plan ou d'application.
Avec vos identifiants configurés, terraform plan irait plus loin : il lirait les deux sources de données (et échouerait si le projet n'existait pas), puis annoncerait la création de trois ressources, avec pour chaque attribut calculé, comme id ou created_at, la mention (known after apply), que vous avez rencontrée à la leçon 2 sur random_pet. Si vous lancez ce plan, ne l'appliquez qu'en connaissant le coût : un VPC et un réseau privé sont gratuits, un bucket vide aussi, mais la suite du cours ajoute des ressources payantes.
Une seconde région
Pour une copie des pièces jointes hors de Paris, le fichier providers.tf reçoit un second bloc :
provider "scaleway" {
alias = "amsterdam"
region = "nl-ams"
zone = "nl-ams-1"
}et le bucket de copie le désigne :
resource "scaleway_object_bucket" "copies" {
provider = scaleway.amsterdam
name = "signalements-copies-exemple"
project_id = data.scaleway_account_project.signalements.id
}terraform validate accepte l'ensemble. terraform providers résume les fournisseurs requis :
$ terraform providers -no-color
Providers required by configuration:
.
└── provider[registry.terraform.io/scaleway/scaleway] ~> 2.84
Une seule ligne : l'alias n'est pas un second fournisseur, mais une seconde configuration du même. Un seul binaire est téléchargé ; il sera lancé deux fois, une par configuration.
Sous le capot
Le cycle d'un appel. Pour planifier une ressource, le cœur envoie au fournisseur, par gRPC, la configuration déclarée et l'état précédent, et lui demande ce qu'il compte faire (PlanResourceChange). Le fournisseur répond avec l'état prévu, en marquant inconnues les valeurs qu'il ne connaîtra qu'après création. À l'application, le cœur demande l'exécution (ApplyResourceChange) ; le fournisseur appelle l'API de Scaleway, attend que la ressource soit prête (les opérations du cloud sont asynchrones, comme le montrait le premier cours), et renvoie l'état final, que le cœur écrit dans l'état. C'est pour cette attente que le bloc timeouts existe.
La vérification de signature. Le registre publie, pour chaque version, une liste de sommes SHA-256 (une par plateforme) et une signature GPG de cette liste. Terraform vérifie la signature avec la clé publique de l'éditeur déclarée au registre, puis vérifie que l'archive téléchargée a bien la somme annoncée, puis compare au fichier de verrouillage. La chaîne de confiance est donc : le registre, puis la clé de l'éditeur, puis le premier init. OpenTofu suit le même principe avec son propre registre, mais sa documentation admet une exception provisoire : la vérification GPG est sautée quand la clé de l'éditeur n'est pas encore publiée dans le registre d'OpenTofu, en attendant que toutes les clés y soient.
Le cache des fournisseurs. Chaque répertoire de travail télécharge ses fournisseurs dans son propre .terraform/. Pour ne pas retélécharger 45 Mo à chaque projet, la variable TF_PLUGIN_CACHE_DIR (ou l'option plugin_cache_dir du fichier de configuration de la CLI) désigne un cache partagé. Le fichier de verrouillage reste la référence : un paquet du cache n'est utilisé que si sa somme correspond.
Terraform et OpenTofu face au même dépôt. Le fichier de verrouillage commence par provider "registry.terraform.io/scaleway/scaleway". Un tofu init sur ce dépôt cherche par défaut registry.opentofu.org/scaleway/scaleway, une autre adresse : il ajoute une seconde entrée. Une équipe choisit un outil pour un dépôt donné, et le pipeline utilise le même.
Pièges courants
Oublier de versionner le fichier de verrouillage, ou l'ajouter au .gitignore par habitude. Chacun obtient alors la version la plus récente du moment, et le pipeline n'applique pas ce qui a été planifié sur le poste.
Le message « doesn't match any of the checksums previously recorded ». Trois causes : le fichier a été généré sur une autre plateforme sans sa somme h1: (corriger avec terraform providers lock -platform=...), un miroir ou un proxy sert un paquet recompressé, ou, plus rarement, un paquet a réellement changé. Dans le doute, on ne supprime pas le fichier : on comprend d'abord.
Une contrainte trop lâche ou trop serrée. >= 2.0 sans borne haute accepte un jour la version 3 et ses changements incompatibles. = 2.84.0 bloque même les correctifs de sécurité. ~> 2.84 dans la configuration racine, plus le fichier de verrouillage, est le bon compromis.
Confondre le nom local et le nom réel. Renommer resource "scaleway_vpc_private_network" "signalements" en "principal" ne renomme rien chez Scaleway, mais Terraform y voit la destruction d'une ressource et la création d'une autre. La leçon 6 montre pourquoi, et la leçon 11 comment renommer proprement.
Un alias oublié. Une ressource sans argument provider utilise la configuration par défaut. Si le bucket de copie oublie provider = scaleway.amsterdam, il est créé à Paris, sans aucune erreur.
Une source de données qui dépend d'une ressource à créer. Sa lecture est repoussée à l'application, et toutes les valeurs qui en dépendent deviennent inconnues au plan : le plan devient beaucoup moins lisible. Ne faites dépendre une source de données que de valeurs connues.
Les erreurs d'authentification au plan. Si le fournisseur ne trouve aucune clé (ni environnement, ni code, ni fichier), le plan échoue dès la première lecture d'API. Vérifiez scw config info : le fournisseur lit le même fichier, avec le même profil actif.
Sécurité
- Jamais de clé dans le code. La documentation du fournisseur Scaleway l'écrit elle-même : coder les identifiants en dur dans une configuration « n'est pas recommandé » et expose à une fuite si le fichier est publié. Environnement en CI, fichier de la CLI aux droits
600sur le poste. - Une clé par usage, aux droits limités. La clé que lit le fournisseur peut tout ce que son porteur peut faire. Le pipeline utilise une application IAM limitée au projet, comme
sig-deploiementau cours cloud ; la leçon 12 y revient. - Le fournisseur est du code que vous exécutez avec vos identifiants. Préférez les fournisseurs officiels et partenaires ; pour un fournisseur communautaire, regardez qui le maintient, son activité, son code. Une faute de frappe dans l'adresse source (
scalewey/scaleway) peut télécharger tout autre chose : relisez les adresses dans les demandes de fusion. - Le fichier de verrouillage est une protection. Ses sommes garantissent que la CI exécute exactement le binaire choisi et relu. Une demande de fusion qui le modifie mérite une relecture : quelle version, pourquoi, quelles notes de version.
- Le journal de débogage peut contenir des secrets.
TF_LOG=DEBUGetSCW_DEBUG=1affichent les requêtes ; ne les activez pas dans un pipeline dont les journaux sont lisibles par d'autres.
En production
- Un outil par dépôt, Terraform ou OpenTofu, et la même version partout : en local, en CI, dans la documentation.
required_versionle rappelle à qui l'oublie. - Les montées de version sont des changements comme les autres :
terraform init -upgradesur une branche, lecture des notes de version du fournisseur (le fournisseur Scaleway publie les siennes sur GitHub), plan sur chaque environnement, puis fusion. Des outils comme Dependabot ou Renovate savent proposer ces demandes de fusion automatiquement. - Un cache de fournisseurs en CI évite de retélécharger les binaires à chaque exécution ; le fichier de verrouillage garantit qu'il ne sert que les bons paquets.
- Plusieurs configurations du fournisseur (alias) restent lisibles tant qu'elles sont peu nombreuses. Au-delà, ou pour plusieurs projets aux droits différents, on découpe en plusieurs configurations racines, une par périmètre : c'est un sujet du cours avancé.
- Chez Lyneko, les applications tournent sur un cluster Kapsule et leurs images vivent dans le registre de Scaleway : les mêmes ressources se décrivent avec ce fournisseur, et la même discipline (fichier de verrouillage versionné, clés en secret de CI) s'y applique.
Exercices
1. Lire des contraintes (niveau 100). Pour chaque contrainte, dites si la version 2.85.1 est acceptée, puis si 3.0.0 l'est : (a) ~> 2.84, (b) ~> 2.84.0, (c) >= 2.80, < 3.0, (d) != 2.85.1, ~> 2.
Solution
(a) 2.85.1 oui, 3.0.0 non : seul le composant mineur peut augmenter. (b) 2.85.1 non : seul le correctif peut augmenter, la version doit commencer par 2.84.. 3.0.0 non. (c) 2.85.1 oui, 3.0.0 non (borne stricte). (d) 2.85.1 non, exclue explicitement. 3.0.0 non plus : Terraform complète ~> 2 en ~> 2.0 (on le voit à l'init, qui affiche Finding ... versions matching "~> 2.0"), ce qui revient à >= 2.0, < 3.0. Dans le doute, écrivez la forme explicite.
2. Lire un schéma (niveau 200). Avec le fournisseur Scaleway initialisé, extrayez de terraform providers schema -json les arguments obligatoires de la ressource scaleway_rdb_instance, et les attributs marqués sensitive. Donnez la commande jq.
Solution
$ terraform providers schema -json | jq -r '
.provider_schemas["registry.terraform.io/scaleway/scaleway"]
.resource_schemas.scaleway_rdb_instance.block.attributes
| to_entries[]
| select(.value.required or .value.sensitive)
| "\(.key) required=\(.value.required // false) sensitive=\(.value.sensitive // false)"'
Avec le fournisseur 2.84, node_type est le seul argument obligatoire, et password est sensible. Vous verrez aussi password_wo, marqué write_only : un argument en écriture seule, que la leçon 5 explique, et qui n'est jamais enregistré dans l'état.
3. Deux régions (niveau 200). Ajoutez à la configuration un réseau privé pn-signalements-ams dans la région nl-ams, sans changer la région par défaut, de deux façons : avec l'alias, puis avec l'argument region de la ressource. Validez chaque version. Laquelle préférez-vous, et quand l'autre devient-elle nécessaire ?
Solution
Avec l'alias : provider = scaleway.amsterdam dans la ressource. Avec l'argument : region = "nl-ams", que le schéma de scaleway_vpc_private_network accepte (facultatif et calculé). Pour une ressource isolée, l'argument est plus simple et plus lisible. L'alias devient nécessaire quand de nombreuses ressources visent la même autre région, ou quand il faut d'autres identifiants (argument profile ou project_id du fournisseur), ce qu'un argument de ressource ne permet pas.
4. Un fichier de verrouillage refusé (niveau 200). Un collègue sous macOS (Apple Silicon) obtient au terraform init une erreur indiquant que le paquet ne correspond à aucune somme enregistrée. Le fichier a été créé sur un poste Linux. Diagnostic et correction, sans supprimer le fichier.
Solution
Le fichier ne contient que la somme h1: de linux_amd64 ; selon la façon dont le paquet est obtenu (miroir, cache, paquet déjà décompressé), seule une somme h1: peut le vérifier. Correction depuis n'importe quel poste : terraform providers lock -platform=linux_amd64 -platform=darwin_arm64 (plus les plateformes de la CI), relecture du différentiel, demande de fusion. On ne supprime pas le fichier, ce qui reviendrait à refaire confiance au premier usage, et à accepter silencieusement une autre version.
Récapitulatif
- Terraform se compose d'un cœur, qui planifie et orchestre, et de fournisseurs, des processus fils qui parlent aux API ; ils dialoguent en gRPC et le fournisseur expose un schéma.
- Un fournisseur s'identifie par son adresse source (
scaleway/scaleway), dont le registre implicite estregistry.terraform.iopour Terraform etregistry.opentofu.orgpour OpenTofu. - La contrainte de version borne les versions acceptables ;
~>laisse augmenter le dernier composant écrit. Dans la configuration racine :~> 2.84. - Le fichier de verrouillage
.terraform.lock.hclenregistre version et sommes de contrôle (h1:,zh:) ; il se versionne.init -upgradechange de version,providers lock -platformprépare les autres plateformes. - Le fournisseur Scaleway cherche ses identifiants dans l'environnement, puis dans le code, puis dans le fichier de la CLI ; on n'en met jamais dans le code.
- Une ressource est gérée, une source de données est seulement lue ; arguments obligatoires, facultatifs, attributs calculés (
known after apply). - Un alias donne une seconde configuration au même fournisseur.
Pour aller plus loin
- La page Dependency lock file de la documentation de Terraform, pour le détail des schémas de sommes et des cas de miroirs.
- La documentation du fournisseur Scaleway, en particulier son guide sur les régions et les zones, et le dépôt
scaleway/terraform-provider-scalewaypour les notes de version. - La leçon suivante, qui remplace les valeurs écrites en dur (nom du bucket, plage d'adresses, environnement) par des variables, et expose les résultats par des sorties.
Sources
- HashiCorp, How Terraform works with plugins
- HashiCorp, Provider requirements
- HashiCorp, Version constraints
- HashiCorp, Dependency lock file
- HashiCorp, Provider signing
- OpenTofu, Provider requirements
- OpenTofu, Provider signing
- scaleway/terraform-provider-scaleway, docs/index.md (authentification et ordre de priorité)
- Yevgeniy Brikman, Terraform: Up & Running (3e éd., O'Reilly, 2022), chapitre 2