Guide de Style Terraform
Générez et maintenez du code Terraform en suivant les conventions de style officielles de HashiCorp et les meilleures pratiques.
Référence : HashiCorp Terraform Style Guide
Stratégie de Génération de Code
Lors de la génération de code Terraform :
- Commencez par la configuration du provider et les contraintes de version
- Créez les data sources avant les ressources dépendantes
- Construisez les ressources dans l'ordre des dépendances
- Ajoutez des outputs pour les attributs clés des ressources
- Utilisez des variables pour toutes les valeurs configurables
Organisation des Fichiers
| Fichier | Objectif |
|---|---|
terraform.tf |
Exigences de version Terraform et du provider |
providers.tf |
Configurations du provider |
main.tf |
Ressources et data sources principales |
variables.tf |
Déclarations de variables d'entrée (ordre alphabétique) |
outputs.tf |
Déclarations de valeurs de sortie (ordre alphabétique) |
locals.tf |
Déclarations de valeurs locales |
Exemple de Structure
# terraform.tf
terraform {
required_version = ">= 1.14"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
# variables.tf
variable "environment" {
description = "Target deployment environment"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
# locals.tf
locals {
common_tags = {
Environment = var.environment
ManagedBy = "Terraform"
}
}
# main.tf
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
tags = merge(local.common_tags, {
Name = "${var.project_name}-${var.environment}-vpc"
})
}
# outputs.tf
output "vpc_id" {
description = "ID of the created VPC"
value = aws_vpc.main.id
}
Formatage du Code
Indentation et Alignement
- Utilisez deux espaces par niveau d'imbrication (pas de tabulations)
- Alignez les signes égaux pour les arguments consécutifs
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = "subnet-12345678"
tags = {
Name = "web-server"
Environment = "production"
}
}
Organisation des Blocs
Les arguments précèdent les blocs, avec les méta-arguments en premier :
resource "aws_instance" "example" {
# Meta-arguments
count = 3
# Arguments
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
# Blocks
root_block_device {
volume_size = 20
}
# Lifecycle last
lifecycle {
create_before_destroy = true
}
}
Conventions de Nommage
- Utilisez minuscules avec underscores pour tous les noms
- Utilisez noms descriptifs excluant le type de ressource
- Soyez spécifique et significatif
- Les noms de ressources doivent être au singulier, non au pluriel
- Par défaut, utilisez
mainpour les ressources où un nom descriptif spécifique est redondant ou indisponible, sauf s'il existe plusieurs instances
# Mauvais
resource "aws_instance" "webAPI-aws-instance" {}
resource "aws_instance" "web_apis" {}
variable "name" {}
# Bon
resource "aws_instance" "web_api" {}
resource "aws_vpc" "main" {}
variable "application_name" {}
Variables
Chaque variable doit inclure type et description :
variable "instance_type" {
description = "EC2 instance type for the web server"
type = string
default = "t2.micro"
validation {
condition = contains(["t2.micro", "t2.small", "t2.medium"], var.instance_type)
error_message = "Instance type must be t2.micro, t2.small, or t2.medium."
}
}
variable "database_password" {
description = "Password for the database admin user"
type = string
sensitive = true
}
Outputs
Chaque output doit inclure une description :
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.web.id
}
output "database_password" {
description = "Database administrator password"
value = aws_db_instance.main.password
sensitive = true
}
Création Dynamique de Ressources
Préférez for_each à count
# Mauvais - count pour plusieurs ressources
resource "aws_instance" "web" {
count = var.instance_count
tags = { Name = "web-${count.index}" }
}
# Bon - for_each avec instances nommées
variable "instance_names" {
type = set(string)
default = ["web-1", "web-2", "web-3"]
}
resource "aws_instance" "web" {
for_each = var.instance_names
tags = { Name = each.key }
}
count pour la Création Conditionnelle
resource "aws_cloudwatch_metric_alarm" "cpu" {
count = var.enable_monitoring ? 1 : 0
alarm_name = "high-cpu-usage"
threshold = 80
}
Meilleures Pratiques de Sécurité
Consultez SECURITY.md. Il inclut des conseils sur le chiffrement des ressources, l'évitement des données sensibles dans l'état et les configurations sécurisées.
Épinglage de Version
terraform {
required_version = ">= 1.14"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
Utilisez la dernière version majeure de chaque provider et la dernière version mineure de Terraform, sauf si elle est autrement limitée par un fichier de verrouillage des dépendances ou par d'autres modules utilisés par la configuration.
Opérateurs de contrainte de version :
= 1.0.0- Version exacte>= 1.0.0- Supérieur ou égal~> 1.0- Autoriser l'incrémentation du composant le plus à droite>= 1.0, < 2.0- Plage de versions
Configuration du Provider
provider "aws" {
region = "us-west-2"
default_tags {
tags = {
ManagedBy = "Terraform"
Project = var.project_name
}
}
}
# Provider aliasé pour multi-région
provider "aws" {
alias = "east"
region = "us-east-1"
}
Contrôle de Version
Ne commitez jamais :
terraform.tfstate,terraform.tfstate.backup- Répertoire
.terraform/ *.tfplan- Fichiers
.tfvarscontenant des données sensibles
Commitez toujours :
- Tous les fichiers de configuration
.tf .terraform.lock.hcl(fichier de verrouillage des dépendances)
Outils de Validation
Exécutez avant de committer :
terraform fmt -recursive
terraform validate
Outils supplémentaires :
tflint- Linting et meilleures pratiquescheckov/tfsec- Analyse de sécurité
Liste de Contrôle de Révision de Code
- [ ] Code formaté avec
terraform fmt - [ ] Configuration validée avec
terraform validate - [ ] Fichiers organisés selon la structure standard
- [ ] Toutes les variables ont un type et une description
- [ ] Tous les outputs ont des descriptions
- [ ] Les noms de ressources utilisent des noms descriptifs avec underscores
- [ ] Contraintes de version épinglées explicitement
- [ ] Valeurs sensibles marquées avec
sensitive = true - [ ] Aucune information d'identification ou secret en dur
- [ ] Meilleures pratiques de sécurité appliquées
Basé sur : HashiCorp Terraform Style Guide