Principes de design de modules
Un bon module Terraform suit ces principes :
- Single responsibility — Un module fait une seule chose bien
- Encapsulation — Les details d'implementation sont caches
- Composabilite — Les modules peuvent se combiner
- Reusabilite — Le module fonctionne dans differents contextes
Structure standard d'un module
modules/vpc/
main.tf # Ressources principales
variables.tf # Variables d'entree
outputs.tf # Valeurs de sortie
versions.tf # Contraintes de version
README.md # Documentation
Module avec validation des variables
variable "environment" {
type = string
description = "Environnement de deploiement"
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "L'environnement doit etre dev, staging ou production."
}
}
variable "cidr_block" {
type = string
description = "CIDR du VPC"
validation {
condition = can(cidrhost(var.cidr_block, 0))
error_message = "Le CIDR doit etre valide (ex: 10.0.0.0/16)."
}
}
Composition de modules
# Root module qui compose des sous-modules
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
environment = var.environment
}
module "eks" {
source = "./modules/eks"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnet_ids
depends_on = [module.vpc]
}
module "rds" {
source = "./modules/rds"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.database_subnet_ids
}
Module generique avec for_each et dynamic
variable "security_rules" {
type = list(object({
port = number
protocol = string
cidr_blocks = list(string)
}))
}
resource "aws_security_group" "this" {
name = var.name
vpc_id = var.vpc_id
dynamic "ingress" {
for_each = var.security_rules
content {
from_port = ingress.value.port
to_port = ingress.value.port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
}
Bonne pratique : Utilisez des types complexes (object, map) avec des validations pour rendre vos modules robustes et auto-documentes.