Recherche Terraform et Import en Masse
Découvrez les ressources cloud existantes à l'aide de requêtes déclaratives et générez une configuration pour importer en masse dans l'état Terraform.
Références :
Quand l'utiliser
- Placer des ressources non gérées sous contrôle Terraform
- Auditer l'infrastructure cloud existante
- Migrer de l'approvisionnement manuel vers l'IaC
- Découvrir des ressources sur plusieurs régions/comptes
IMPORTANT : Vérifier le Support du Provider en Premier
AVANT de commencer, vous DEVEZ vérifier que le type de ressource cible est supporté :
# Vérifier quelles ressources list sont disponibles
./scripts/list_resources.sh aws # Provider spécifique
./scripts/list_resources.sh # Tous les providers configurés
Arbre de Décision
-
Identifier le type de ressource cible (ex. aws_s3_bucket, aws_instance)
-
Vérifier si supporté : Exécuter
./scripts/list_resources.sh <provider> -
Choisir le workflow :
- Si supporté : Vérifier la version Terraform disponible.
- Si la version Terraform est supérieure à 1.14.0 : Utiliser le workflow Terraform Search (ci-dessous)
- Si non supporté ou version Terraform inférieure à 1.14.0 : Utiliser le workflow Découverte Manuelle (voir references/MANUAL-IMPORT.md)
Note : La liste des ressources supportées s'étend rapidement. Toujours vérifier le support actuel avant d'utiliser l'import manuel.
Prérequis
Avant d'écrire des requêtes, vérifiez que le provider supporte les ressources list pour votre type de ressource cible.
Découvrir les Ressources List Disponibles
Exécutez le script helper pour extraire les ressources list supportées de votre provider :
# Depuis un répertoire avec configuration provider (lance terraform init si nécessaire)
./scripts/list_resources.sh aws # Provider spécifique
./scripts/list_resources.sh # Tous les providers configurés
Ou interrogez manuellement le schéma du provider :
terraform providers schema -json | jq '.provider_schemas | to_entries | map({key: (.key | split("/")[-1]), value: (.value.list_resource_schemas // {} | keys)})'
Terraform Search nécessite un répertoire de travail initialisé. Assurez-vous d'avoir une configuration avec le provider requis avant d'exécuter les requêtes :
# terraform.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
Exécutez terraform init pour télécharger le provider, puis procédez aux requêtes.
Workflow Terraform Search (Ressources Supportées Uniquement)
- Créer des fichiers
.tfquery.hclavec des blocslistdéfinissant les requêtes de recherche - Exécuter
terraform querypour découvrir les ressources correspondantes - Générer la configuration avec
-generate-config-out=<file> - Examiner et affiner les blocs
resourceetimportgénérés - Exécuter
terraform planetterraform applypour importer
Structure du Fichier de Requête
Les fichiers de requête utilisent l'extension .tfquery.hcl et supportent :
- Les blocs
providerpour l'authentification - Les blocs
listpour la découverte de ressources - Les blocs
variableetlocalspour la paramétrisation
# discovery.tfquery.hcl
provider "aws" {
region = "us-west-2"
}
list "aws_instance" "all" {
provider = aws
}
Syntaxe du Bloc List
list "<list_type>" "<symbolic_name>" {
provider = <provider_reference> # Requis
# Optionnel : configuration de filtre (spécifique au provider)
# Le schéma du bloc `config` est spécifique au provider. Découvrez les options disponibles avec `terraform providers schema -json | jq '.provider_schemas."registry.terraform.io/hashicorp/<provider>".list_resource_schemas."<resource_type>"'`
config {
filter {
name = "<filter_name>"
values = ["<value1>", "<value2>"]
}
region = "<region>" # Spécifique à AWS
}
# Optionnel : limiter les résultats
limit = 100
}
Ressources List Supportées
Le support du provider pour les ressources list varie selon la version. Vérifiez toujours ce qui est disponible pour votre version de provider spécifique en utilisant le script de découverte.
Exemples de Requêtes
Découverte Basique
# Trouver toutes les instances EC2 dans la région configurée
list "aws_instance" "all" {
provider = aws
}
Découverte Filtrée
# Trouver les instances par tag
list "aws_instance" "production" {
provider = aws
config {
filter {
name = "tag:Environment"
values = ["production"]
}
}
}
# Trouver les instances par type
list "aws_instance" "large" {
provider = aws
config {
filter {
name = "instance-type"
values = ["t3.large", "t3.xlarge"]
}
}
}
Découverte Multi-Régions
provider "aws" {
region = "us-west-2"
}
locals {
regions = ["us-west-2", "us-east-1", "eu-west-1"]
}
list "aws_instance" "all_regions" {
for_each = toset(local.regions)
provider = aws
config {
region = each.value
}
}
Requêtes Paramétrées
variable "target_environment" {
type = string
default = "staging"
}
list "aws_instance" "by_env" {
provider = aws
config {
filter {
name = "tag:Environment"
values = [var.target_environment]
}
}
}
Exécuter les Requêtes
# Exécuter les requêtes et afficher les résultats
terraform query
# Générer un fichier de configuration
terraform query -generate-config-out=imported.tf
# Passer des variables
terraform query -var='target_environment=production'
Format de Sortie des Requêtes
list.aws_instance.all account_id=123456789012,id=i-0abc123,region=us-west-2 web-server
Colonnes : <query_address> <identity_attributes> <name_tag>
Configuration Générée
Le flag -generate-config-out crée :
# __generated__ by Terraform
resource "aws_instance" "all_0" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
# ... tous les attributs
}
import {
to = aws_instance.all_0
provider = aws
identity = {
account_id = "123456789012"
id = "i-0abc123"
region = "us-west-2"
}
}
Nettoyage Post-Génération
La configuration générée inclut tous les attributs. Nettoyez en :
- Supprimer les attributs calculés/lecture seule
- Remplacer les valeurs en dur par des variables
- Ajouter des noms de ressources appropriés
- Organiser dans les fichiers appropriés
# Avant : généré
resource "aws_instance" "all_0" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
arn = "arn:aws:ec2:..." # Supprimer - calculé
id = "i-0abc123" # Supprimer - calculé
# ... beaucoup d'autres attributs
}
# Après : nettoyé
resource "aws_instance" "web_server" {
ami = var.ami_id
instance_type = var.instance_type
subnet_id = var.subnet_id
tags = {
Name = "web-server"
Environment = var.environment
}
}
Import par Identité
Les imports générés utilisent l'import basé sur l'identité (Terraform 1.12+) :
import {
to = aws_instance.web
provider = aws
identity = {
account_id = "123456789012"
id = "i-0abc123"
region = "us-west-2"
}
}
Vérifier l'État Importé
Après avoir exécuté terraform apply pour importer les ressources, vérifiez ce qui s'est réellement retrouvé dans l'état.
Préférez les commandes documentées, stables et plus efficaces en tokens que de lire le fichier d'état brut :
# Confirmer que les ressources sont désormais gérées (confirme aussi les adresses)
terraform state list
# Inspecter les valeurs d'attribut résolues pour les ressources importées
terraform show -json | jq '.values.root_module.resources[] | {address, type, name}'
terraform show -json nécessite que les providers soient installés (terraform init), car il restitue les valeurs selon les schémas du provider. Retombez sur l'état brut (terraform state pull / terraform.tfstate) uniquement quand les providers ne sont pas disponibles et que init ne peut pas s'exécuter, vous n'avez besoin que d'informations générales (adresses, outputs, serial/lineage), ou vous devez éviter d'exécuter Terraform. Évitez de parser le format d'état version-4 brut comme interface stable. Note : l'état contient des valeurs sensibles en texte brut dans tous les formats — ne jamais afficher le contenu de l'état dans les logs ou la sortie.
Bonnes Pratiques
Conception des Requêtes
- Commencer large, puis ajouter des filtres pour affiner les résultats
- Utiliser
limitpour éviter une sortie accablante - Tester les requêtes avant de générer la configuration
Gestion de la Configuration
- Examiner tout le code généré avant d'appliquer
- Supprimer les valeurs par défaut inutiles
- Utiliser des conventions de nommage cohérentes
- Ajouter une abstraction appropriée des variables
Dépannage
| Problème | Solution |
|---|---|
| « Aucune ressource list trouvée » | Vérifier que la version du provider supporte les ressources list |
| La requête retourne vide | Vérifier la région et les valeurs de filtre |
| La configuration générée a des erreurs | Supprimer les attributs calculés, corriger les arguments dépréciés |
| L'import échoue | S'assurer que la ressource n'est pas déjà dans l'état |
Exemple Complet
# main.tf - Initialiser le provider
terraform {
required_version = ">= 1.14"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0" # Toujours utiliser la dernière version
}
}
}
# discovery.tfquery.hcl - Définir les requêtes
provider "aws" {
region = "us-west-2"
}
list "aws_instance" "team_instances" {
provider = aws
config {
filter {
name = "tag:Owner"
values = ["platform"]
}
filter {
name = "instance-state-name"
values = ["running"]
}
}
limit = 50
}
# Exécuter le workflow
terraform init
terraform query
terraform query -generate-config-out=generated.tf
# Examiner et nettoyer generated.tf
terraform plan
terraform apply