Aller au contenu

TP 31 : Publier et versionner un module

À l’issue de ce TP, vous serez capable de :

  • structurer un module réutilisable selon les conventions standard ;
  • documenter ses entrées, sorties et exemples ;
  • ajouter des tests au module ;
  • publier le module via un dépôt Git et le versionner par tags ;
  • consommer le module en épinglant une version précise avec ?ref=.
  • Terraform >= 1.7 (pour les tests).
  • Git et un dépôt distant (GitHub, GitLab ou Gitea).

Plusieurs équipes d’InfraBank réécrivent la même logique de bucket S3 chiffré. On la factorise en un module versionné, documenté et testé, consommé partout avec une version figée.

terraform-aws-secure-bucket/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
├── README.md
├── examples/
│ └── complet/
│ ├── main.tf
│ └── versions.tf
└── tests/
└── defaults.tftest.hcl

Convention de nommage d’un module publié : terraform-<provider>-<nom> (ici terraform-aws-secure-bucket).

versions.tf
terraform {
required_version = ">= 1.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.60"
}
}
}
variables.tf
variable "name" {
type = string
description = "Nom logique du bucket (préfixe)."
}
variable "versioning_enabled" {
type = string
description = "Active le versioning du bucket."
default = true
}
variable "tags" {
type = map(string)
description = "Tags additionnels."
default = {}
}
main.tf
resource "aws_s3_bucket" "this" {
bucket = var.name
tags = var.tags
}
resource "aws_s3_bucket_versioning" "this" {
bucket = aws_s3_bucket.this.id
versioning_configuration {
status = var.versioning_enabled ? "Enabled" : "Suspended"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "this" {
bucket = aws_s3_bucket.this.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
}
}
resource "aws_s3_bucket_public_access_block" "this" {
bucket = aws_s3_bucket.this.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
outputs.tf
output "bucket_id" {
description = "Identifiant du bucket."
value = aws_s3_bucket.this.id
}
output "bucket_arn" {
description = "ARN du bucket."
value = aws_s3_bucket.this.arn
}

Un module publié se documente. Décrivez le but, les entrées, les sorties et fournissez un exemple exécutable. Le TP 35 montrera comment générer les tableaux d’entrées/sorties automatiquement avec terraform-docs ; ici, posez au moins l’exemple :

examples/complet/versions.tf
terraform {
required_version = ">= 1.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.60"
}
}
}
provider "aws" {
region = "eu-west-3"
}
examples/complet/main.tf
module "bucket" {
source = "../../"
name = "infrabank-demo-secure"
versioning_enabled = true
tags = {
team = "plateforme"
}
}
output "bucket_arn" {
value = module.bucket.bucket_arn
}

Un exemple sous examples/ sert à la fois de documentation vivante et de cible de test.

tests/defaults.tftest.hcl
mock_provider "aws" {}
run "chiffrement_et_blocage_public" {
command = plan
variables {
name = "infrabank-test"
}
assert {
condition = aws_s3_bucket_public_access_block.this.block_public_acls == true
error_message = "Le blocage des ACL publiques doit être activé."
}
assert {
condition = aws_s3_bucket_versioning.this.versioning_configuration[0].status == "Enabled"
error_message = "Le versioning doit être activé par défaut."
}
}
Fenêtre de terminal
cd terraform-aws-secure-bucket
terraform init
terraform test

La convention est le versionnage sémantique (vMAJEUR.MINEUR.CORRECTIF).

Fenêtre de terminal
git init
git add .
git commit -m "feat: module secure-bucket initial"
git tag v1.0.0
git remote add origin git@github.com:infrabank/terraform-aws-secure-bucket.git
git push origin main --tags

Chaque évolution donne lieu à un nouveau tag : un changement rétro-incompatible incrémente le majeur, une fonctionnalité le mineur, un correctif le patch.

Étape 6 : Consommer le module avec une version figée

Section intitulée « Étape 6 : Consommer le module avec une version figée »

Dans un projet consommateur, référencez le module par sa source Git avec ?ref= pour épingler la version :

projet-consommateur/main.tf
module "logs_bucket" {
source = "git::https://github.com/infrabank/terraform-aws-secure-bucket.git?ref=v1.0.0"
name = "infrabank-logs"
tags = {
purpose = "logs"
}
}
Fenêtre de terminal
terraform init # télécharge le module au tag v1.0.0
terraform plan

Sans ?ref=, Terraform prend la branche par défaut, exposant le projet aux évolutions non maîtrisées du module. Épingler un tag garantit la reproductibilité.

  • terraform test passe dans le module.
  • Le tag v1.0.0 existe et est poussé.
  • Le projet consommateur télécharge exactement v1.0.0 via ?ref=.
Fenêtre de terminal
# Côté consommateur, si des ressources ont été créées :
terraform destroy -auto-approve