terraform-style-guide

Par hashicorp · agent-skills

Génère du code Terraform HCL en suivant les conventions de style officielles de HashiCorp et les bonnes pratiques. À utiliser lors de l'écriture, de la révision ou de la génération de configurations Terraform.

npx skills add https://github.com/hashicorp/agent-skills --skill terraform-style-guide

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 :

  1. Commencez par la configuration du provider et les contraintes de version
  2. Créez les data sources avant les ressources dépendantes
  3. Construisez les ressources dans l'ordre des dépendances
  4. Ajoutez des outputs pour les attributs clés des ressources
  5. 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 main pour 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 .tfvars contenant 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 pratiques
  • checkov / 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

Skills similaires