
Un provider est le plugin qui traduit vos ressources en appels d'API. On le
déclare dans required_providers, on le configure dans un bloc provider, et
tout semble simple, jusqu'à ce qu'un module s'en mêle. Deux confusions dominent :
l'adresse source (le préfixe hashicorp/ implicite est en réalité
déconseillé) et la différence entre nom local et alias.
Ce guide traite l'adresse source complète, le nom local face à l'alias, les contraintes de version selon le contexte, la place des providers dans un module, et la preuve par le plan JSON. Les comportements ont été vérifiés sur Terraform v1.15.4.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- L'adresse source complète, et pourquoi l'implicite est déconseillé
- La différence entre nom local et alias
- Les contraintes de version selon le contexte (racine ou module)
- Pourquoi un module réutilisable ne contient pas de bloc
provider configuration_aliases,providers = {}, et la preuve par le plan JSON
Prérequis
Section intitulée « Prérequis »- Un projet Terraform initialisé (installer Terraform)
- Les contraintes de version (version constraints)
L'adresse source : toujours explicite
Section intitulée « L'adresse source : toujours explicite »Depuis Terraform 0.13, source est requis dans required_providers. On
lit souvent qu'il est « implicite » pour les providers HashiCorp : c'est vrai
techniquement, mais la doc le classe comme une rétro-compatibilité et
recommande l'inverse : « use explicit source addresses for all providers ».
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }}L'adresse complète est [HOSTNAME/]NAMESPACE/TYPE. hashicorp/aws est en
fait registry.terraform.io/hashicorp/aws : le hostname, souvent omis, est
la porte d'entrée des registres privés et des miroirs. L'omettre revient
à câbler le registre public par défaut.
Nom local et alias : deux notions distinctes
Section intitulée « Nom local et alias : deux notions distinctes »C'est la confusion la plus fréquente, et le guide d'origine la mélangeait. Ce sont deux mécanismes différents :
- Le nom local (la clé dans
required_providers) identifie le provider dans le module. C'est lui qui rattache un type de ressource à un provider, par son préfixe :aws_instanceva au provider de nom localaws. Un nom local différent du type impose unprovider = <nom_local>sur chaque ressource. - L'alias crée une configuration supplémentaire du même provider, pour cibler par exemple deux régions.
provider "aws" { region = "eu-west-3"}
provider "aws" { alias = "us" region = "us-east-1"}
resource "aws_instance" "paris" { # provider par defaut}
resource "aws_instance" "virginie" { provider = aws.us}Le plan JSON le confirme : configuration.provider_config liste chaque
configuration avec son full_name, son alias éventuel, et chaque ressource
porte un provider_config_key (aws ou aws.us).
Les contraintes de version dépendent du contexte
Section intitulée « Les contraintes de version dépendent du contexte »Une même règle ne vaut pas partout, et c'est un point d'examen :
- Module racine : bornez haut et bas, typiquement
~> 5.0, « to avoid accidental upgrades to incompatible new versions ». - Module réutilisable : ne contraignez que le minimum, et n'utilisez
pas
~>: « reusable modules should constrain only their minimum allowed versions », sans quoi le module « forces users to update many modules simultaneously ».
Terraform ne fait pas correspondre les pré-releases aux opérateurs de
plage, et un bloc provider {} n'accepte que des valeurs connues avant
l'apply : jamais un attribut calculé d'une ressource.
Les providers et les modules
Section intitulée « Les providers et les modules »Voici le cœur du sujet, et ce que l'examen interroge. Un module destiné à être
appelé ne doit contenir aucun bloc provider : « A module intended to be
called by one or more other modules must not contain any provider blocks. » La
configuration du provider vit dans le module racine, et traverse la
frontière.
Trois mécanismes gouvernent ce passage :
- L'héritage implicite : un module enfant hérite des configurations par
défaut du parent, mais pas des exigences de
sourceet deversion, que chaque module doit redéclarer dans son proprerequired_providers. configuration_aliases: dans sonrequired_providers, un module enfant déclare qu'il attend une configuration aliasée (configuration_aliases = [aws.us]).providers = { ... }: le meta-argument du blocmodulepasse une configuration (aliasée ou non) au module enfant.
module "reseau" { source = "./modules/reseau" providers = { aws = aws.us }}Diagnostic : le schéma et la sélection
Section intitulée « Diagnostic : le schéma et la sélection »Deux outils machine, souvent ignorés :
terraform providers schema -jsondécrit le schéma complet de chaque provider (attributs, types,write_only) : c'est l'outil de référence quand un argument semble manquant.terraform version -jsonexposeprovider_selections, l'adresse complète vers la version réellement retenue :
terraform version -json | jq '.provider_selections'Pour la CI, terraform init -lockfile=readonly vérifie les empreintes du lock
sans le réécrire ; il est incompatible avec -upgrade.
Dépannage
Section intitulée « Dépannage »Ces symptômes touchent à la source, à l'alias ou aux modules.
| Symptôme | Cause | Solution |
|---|---|---|
| Une ressource va au mauvais provider | Son préfixe ne correspond pas au nom local attendu | Poser provider = <nom_local> sur la ressource |
provider configuration not present | Un module attend une config aliasée non passée | La passer via providers = { aws = aws.us } |
provider blocks are not allowed (module) | Un bloc provider dans un module appelé | Le remonter au module racine, passer par providers |
Avertissement de dépréciation sur version | version dans un bloc provider {} | Déplacer la contrainte dans required_providers |
count/for_each refusés sur un module | Le module hérite d'un bloc provider | Passer la config explicitement, sans bloc dans l'enfant |
À retenir
Section intitulée « À retenir »sourceest requis et doit être explicite ; l'adresse est[HOSTNAME/]NAMESPACE/TYPE.- Nom local ≠ alias : le nom local rattache les ressources, l'alias ajoute une configuration du même provider.
- La contrainte va dans
required_providers, pas dansprovider {}(oùversionest déprécié). - Module racine : borné (
~> 5.0). Module réutilisable : minimum seul, pas de~>. - Un module appelé ne contient aucun bloc
provider; il hérite des configs par défaut, redéclaresource/version, et reçoit les alias parconfiguration_aliases+providers = {}. - Un provider hérité casse
count/for_each/depends_on. version -jsonetproviders schema -jsonsont les preuves machine.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous reprennent les confusions les plus fréquentes sur les providers : l'adresse source, la différence nom local / alias, et les providers dans les modules.
Explicite, toujours
source est requis depuis Terraform 0.13. L'écrire de façon implicite pour les providers HashiCorp est une rétro-compatibilité ; la doc recommande l'inverse : « use explicit source addresses for all providers ».aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
Le hostname
L'adresse complète est[HOSTNAME/]NAMESPACE/TYPE : hashicorp/aws est registry.terraform.io/hashicorp/aws. Le hostname, souvent omis, est la porte des registres privés et des miroirs.Deux mécanismes distincts
- Le nom local (clé de
required_providers) identifie le provider dans le module.aws_instanceva au provider de nom localaws. Un nom local différent du type imposeprovider = <nom_local>sur chaque ressource. - L'alias crée une configuration supplémentaire du même provider :
provider "aws" {
alias = "us"
region = "us-east-1"
}
resource "aws_instance" "virginie" {
provider = aws.us
}
Pas de bloc provider dans un module appelé
« A module intended to be called by one or more other modules must not contain anyprovider blocks. » La configuration du provider vit dans le module racine.Pourquoi
Un module qui hérite d'un blocprovider devient incompatible avec count, for_each et depends_on, et ne peut pas être détruit proprement (la config du provider doit survivre à ses ressources). On passe la config explicitement, jamais par un bloc dans l'enfant.Deux côtés
- Côté enfant, dans
required_providers:configuration_aliases = [aws.us]. - Côté appelant, dans le bloc
module:
module "reseau" {
source = "./modules/reseau"
providers = {
aws = aws.us
}
}
L'héritage implicite
Un module enfant hérite des configs par défaut du parent, mais pas des exigences desource et version : chaque module redéclare son required_providers.version dans provider {} : déprécié
« Theversion argument in provider configurations is deprecated, and Terraform will remove it in a future version. »La contrainte de version va dans required_providers :required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
Autre limite
Un blocprovider {} n'accepte que des valeurs connues avant l'apply : jamais un attribut calculé d'une ressource.Le contexte décide
- Module racine : borné haut et bas,
~> 5.0, « to avoid accidental upgrades to incompatible new versions ». - Module réutilisable : le minimum seul, sans
~>: « reusable modules should constrain only their minimum allowed versions », sinon le module « forces users to update many modules simultaneously ».
À noter
required_version ne couvre que le CLI, pas les providers ; et l'argument version d'un bloc module ne marche qu'avec une source de registre.Le plan JSON
terraform show -json tfplan | jq '.configuration.provider_config'
Chaque config a un full_name (adresse complète), un alias éventuel, et chaque ressource un provider_config_key (aws ou aws.us).La sélection
terraform version -json | jq '.provider_selections'
Expose l'adresse complète de chaque provider vers la version retenue. Et terraform providers schema -json décrit le schéma complet quand un argument semble manquant.Pour aller plus loin
Section intitulée « Pour aller plus loin »- Les data sources Terraform : La lecture d'objets existants par le provider que vous venez de configurer.
- Fonctions définies par les providers : Les fonctions livrées par le provider lui-même, en plus des fonctions du langage.
- Contraintes de version Terraform : Les opérateurs et le lock file qui stabilisent la version de chaque provider.