Parmi tous les concepts à connaître sur Terraform (providers, states, workspaces, etc.), il y a aussi les modules.
Les modules Terraform sont des collections autonomes et réutilisables de code d'infrastructure, permettant aux utilisateurs d'encapsuler et de partager des configurations pour des composants spécifiques, favorisant ainsi la facilité de maintenance dans les projets d'infrastructure as code.
Ils peuvent être utilisés au sein de votre entreprise ou partagés publiquement avec la communauté.
Dans cet article, nous allons créer un module de la manière la plus simple possible en décrivant la structure et en implémentant certaines best practices d'écriture et mécanismes de validation de code.
Un exemple simple
Pour illustrer la création d'un module, nous allons prendre le cas courant des buckets S3 à créer sur AWS.
Le découpage du module dépendra de vos besoins. Hashicorp ne recommande pas d'écrire des modules pour des wrappers de ressources publiques, car tous ces modules sont déjà rendus disponibles par la communauté.
Nous prenons ici un cas simple pour la démonstration, aussi si vous souhaitez fournir un module privé selon les standards de votre entreprise, il peut toujours être judicieux de faire un wrapper.
Nous allons implémenter la structure expliquée par Hashicorp, en créant uniquement les éléments de base qui nous intéressent. Nous veillons également à suivre les conventions de nommage recommandées.
Voici la structure que nous allons mettre en place, je vais décrire tous ces éléments.
├── .pre-commit-config.yaml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── examples
│ └── s3_bucket_simple.tf
├── main.tf
├── outputs.tf
├── variables.tf
└── versions.tf
Ressources principales
main.tf définit la ressource principale à créer, dans notre cas, le bucket s3 :
resource "aws_s3_bucket" "this" {
bucket = var.name
tags = var.tags
}
resource "aws_s3_bucket_ownership_controls" "this" {
bucket = aws_s3_bucket.this.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_acl" "this" {
depends_on = [aws_s3_bucket_ownership_controls.this]
bucket = aws_s3_bucket.this.id
acl = "private"
}
variables.tf définit les variables que vous pouvez passer au module :
variable "name" {
type = string
default = null
description = "Name for the bucket. If omitted, Terraform will assign a random, unique name."
}
variable "tags" {
type = map(any)
default = null
description = "Details the tags to apply to the bucket"
}
outputs.tf définit les attributs que vous pouvez exporter depuis le module :
output "bucket_id" {
value = aws_s3_bucket.this.id
description = "Bucket Name (aka ID)"
}
output "bucket_arn" {
value = aws_s3_bucket.this.arn
description = "Bucket ARN"
}
output "bucket_name" {
value = aws_s3_bucket.this.bucket
description = "Bucket Name"
}
et versions.tf définit les versions autorisées de Terraform et les fournisseurs pour utiliser le module :
terraform {
required_version = ">=1.2"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0, < 5.16.0"
}
}
}
Exemple d’utilisation
Un exemple est décrit dans le fichier examples/s3_bucket_simple.tf, vous pouvez l'utiliser pour vous inspirer dans l'utilisation du module :
module "test_s3" {
source = "git::<https://github.com/mylab/terraform-s3-module.git?ref=0.0.4>"
name = "${var.workspace}-${var.env}-test-bucket"
tags = {
Name = "${var.workspace}-${var.env}-test-bucket"
Env = var.env
}
}
Licence
Pour les dépôts publics, un choix courant est la GPL (General Public License) v3, elle offre de solides protections pour les logiciels open source, garantissant que toute modification ou distribution du code doit également être open source et librement accessible à la communauté.
Si vous n'êtes pas sûr de la licence que vous souhaitez attribuer au projet, vous pouvez vous rendre sur choosealicense.com.
Documentation
Il y a deux niveaux de documentation :
- README.md donne des instructions pour utiliser le module
- CONTRIBUTING.md fournit des instructions pour améliorer le module lui-même
Validation de la qualité pour les contributions
Lorsque les gens contribuent au projet, nous utilisons un outil appelé pre-commit, qui nous permet d'améliorer le code avant que les modifications ne soient partagées dans le dépôt.
Nous utilisons des scripts de validation, appelés hooks, notamment ceux de pre-commit-terraform.
.pre-commit-config.yaml définit les hooks que nous voulons exécuter avec pre-commit
repos:
- repo: <https://github.com/antonbabenko/pre-commit-terraform>
rev: v1.85.0
hooks:
- id: terraform_fmt
- id: terraform_tflint
- id: terraform_checkov
- id: terraform_docs
Terraform-fmt est une commande intégrée à Terraform pour garantir que le code est correctement formaté.
tflint vérifie que le code Terraform ne présente aucun problème de frappe ou d'oubli.
checkov évite de valider des ressources AWS présentant des vulnérabilités de sécurité, il analyse les ressources déployées et indique ce qui n'est pas conforme aux règles de bonnes pratiques de sécurité.
terraform-docs génère la documentation bien formatée dans le fichier README.md.
Exposition du module
Le module peut provenir d'un registre ou d'une référence locale/distante.
Pour une référence locale, vous pouvez l'appeler ainsi :
module "s3" {
source = "./path/to/your/module"
…
Pour une référence à distance, vous avez le choix entre https et ssh :
# https
module "s3" {
source = "git::<https://github.com/mylab/terraform-s3-module.git?ref=0.0.4>"
…
# ssh
module "s3" {
source = "git@github.com:mylab/terraform-s3-module.git?ref=0.0.4"
…
Vous pouvez mettre le module sur le registry Terraform, mais vous pouvez très bien l'utiliser directement sans le référencer sur cette plateforme.
Si vous souhaitez le référencer pour le partager avec la communauté publique, il est assez simple d'y publier votre dépôt git. Il suffit de vous inscrire avec votre compte Github, de sélectionner votre dépôt et de cliquer sur « publier ».
Une bonne pratique consiste à créer des releases git taggées, afin de pointer dessus lors des appels de modules (vous pouvez également mettre à jour le changelog pour tracer les évolutions).
Conclusion
Vous avez maintenant toutes les clés pour créer et publier un module complet et bien configuré, à partager au sein de votre entreprise ou publiquement avec la communauté.