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 l'import 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érifiez d'abord le Support du Provider
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écutez
./scripts/list_resources.sh <provider> -
Choisir un workflow :
- Si supporté : Vérifiez 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. Vérifiez toujours 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 d'aide pour extraire les ressources list supportées de votre provider :
# Depuis un répertoire avec configuration provider (exécute 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 des 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 :
- Des blocs
providerpour l'authentification - Des blocs
listpour la découverte de ressources - Des 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 à l'aide de `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 spécifique du provider à l'aide du 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 le 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
L'option -generate-config-out crée :
# __generated__ par 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/en lecture seule
- Remplacer les valeurs codées en dur par des variables
- Ajouter un nommage approprié des ressources
- 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 plus d'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"
}
}
Bonnes Pratiques
Conception de Requêtes
- Commencer largement, puis ajouter des filtres pour affiner les résultats
- Utiliser
limitpour éviter une sortie écrasante - Tester les requêtes avant de générer la configuration
Gestion de Configuration
- Examiner tout code généré avant d'appliquer
- Supprimer les valeurs par défaut inutiles
- Utiliser des conventions de nommage cohérentes
- Ajouter une abstraction variable appropriée
Dépannage
| Problème | Solution |
|---|---|
| « Aucune ressource list trouvée » | Vérifiez que la version du provider supporte les ressources list |
| La requête ne retourne rien | Vérifiez 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 obsolètes |
| L'import échoue | Assurez-vous 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