Voici comment automatiser la documentation associée à vos solutions Terraform afin de garantir sa cohérence quelques soient les évolutions mise en oeuvre.
Terraform Docs
Terraform Docs est un outil open source qui permet de générer une documentation pour les configurations Terraform. Il permet de créer une documentation claire et structurée pour les modules, les ressources, les variables et les sorties utilisés dans vos configurations Terraform.
L'outil Terraform Docs utilise les informations présentes dans les fichiers Terraform pour générer automatiquement la documentation. Cela permet de garantir que la documentation est à jour et cohérente avec les configurations Terraform.
Terraform Docs supporte plusieurs formats de sortie tels que Markdown, JSON et HTML, ce qui permet une intégration facile avec d'autres outils de documentation. Il permet également de personnaliser la documentation en utilisant des modèles.
En utilisant Terraform Docs, vous pouvez améliorer la documentation de vos configurations Terraform et faciliter la compréhension pour les autres membres de l'équipe.
Installation de l'outil sous Windows en utilisant Winget
Winget est un gestionnaire de packages open source pour Windows. Il permet d'installer facilement des applications en utilisant une interface en ligne de commande.
Winget est conçu pour être simple à utiliser et permet de rechercher, installer, désinstaller et mettre à jour des applications à partir d'un catalogue centralisé de packages.
Pour rechercher l'identifiant du package associé à "Terraform-docs" utiliser cette commande dans un terminal Windows :
winget search "Terraform-docs"
Une fois l'ID identifié, il vous suffit d'exécuter cette commande pour procéder à l'installation de l'outil :
winget install "Terraform-docs.Terraform-docs"
Comme le message ci-dessus l'indique penser à redémarrez votre terminal avant de d'utiliser la commande "terraform-docs":
Génération de votre documentation en local
Exemple simple
Afin de travailler sur un exemple accésible à tous, je vais réutiliser un exemple que j'avais réalisé pour un événement (Clash Session #10 Pulumi vs Terraform) dont voici le repository GitHub: https://github.com/aloizeau/Clash-TerraformVsPulumi
Sur cette solution, j'ai à la fois des modules et des scripts de ressources Azure qui me permet de déployer une solution simple. Je vais donc la cloner puis me mettre à la racine de la solution:
Comme vous pourrez le constater cette solution n'a pas de documentation technique présentant la solution Terraform implémentée, voyons maintenant comment la générer en utilisant Terraform-docs.
La commande suivante va permettre de générer l'ensemble de la documentation dans un fichier README.md de façon récurcive au format markdown.
terraform-docs markdown --recursive --output-file README.md .
Ce qui est intéressant c'est qu'il ne va pas écrasser le fichier README.md existant mais le compléter avec les informations extraites de la solution Terraform:
Voici le rendu standard sans personnalisation :
Cela étant basé sur le contenu de vos fichiers, il est très important de prendre le temps nécessaire pour ajouter des descriptions, conditions, configurations ...
Voici un exemple permettant d'avoir un niveau de détail suffisant lors de la génération :
variable "location" {
description = "(Optional) The Azure Region where the Windows Web App should exist. Changing this forces a new Windows Web App to be created."
type = string
default = "westeurope"
validation {
condition = contains(["westeurope", "northeurope", "francecentral"], var.location)
error_message = "Sorry, but we only accept 'westeurope', 'northeurope' or 'francecentral' values."
}
}
Utilisation d'un fichier de configuration
L'outil Terraform-docs propose des options permettant de personnaliser le fichier de sortie: https://terraform-docs.io/user-guide/configuration/
Voici un exemple d'une configuration personnalisée où je paramétre mes préférences et dans lequel j'ajoute un header et footer:
formatter: "markdown document" # this is required: https://terraform-docs.io/user-guide/configuration/formatter/
version: "= 0.16.0"
header-from: "/docs/.header.md"
footer-from: "/docs/.footer.md"
recursive:
enabled: false
path: modules
sections:
show:
- header
- providers
- inputs
- outputs
- footer
content: |-
{{ .Header }}
{{ .Providers }}
{{ .Inputs }}
{{ .Outputs }}
{{ .Footer }}
output:
file: README.md
mode: inject
template: |-
[//]: # (BEGIN_TF_DOCS)
{{ .Content }}
[//]: # (END_TF_DOCS)
output-values:
enabled: false
from: ""
sort:
enabled: true
by: required
settings:
anchor: true
color: true
default: true
description: true
escape: true
hide-empty: true
html: true
indent: 2
lockfile: true
read-comments: true
required: true
sensitive: true
type: true
Après avoir initialisé ce fichier je peux maintenant éxécuter la génération via cette ligne:
terraform-docs -c .terraform-docs.yml .
Nous retrouvons maintenant une personnalisation du fichier de sortie :
Automatisation DevOps
Voici maintenant comment automatiser la génération de votre documentation au travers de votre CI/CD pour nos deux outils préférés :
GitHub
Azure DevOps
Workflow GitHub
name: Generate terraform docs
on:
- pull_request
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Render terraform docs and push changes back to PR
uses: terraform-docs/gh-actions@main
with:
working-dir: .
output-file: README.md
output-method: inject
git-push: "true"
Pipeline Azure DevOps
name: $(BuildDefinitionName)_$(date:yyyyMMdd)$(rev:.r)
trigger:
branches:
include:
- main
- feature/*
paths:
exclude:
- pipelines/*
- environments/*
pool:
vmImage: ubuntu-latest # This is the default if you don't specify a pool or vmImage.
variables:
- name: Version
value: "v0.16.0"
stages:
- stage: "TerraformDoc"
jobs:
- job: "TerraformDocsJobs"
workspace:
clean: all
displayName: "Generate Terraform Docs"
steps:
- checkout: self
clean: true
persistCredentials: true
- bash: |
# build new doc
./tfdocs/terraform-docs markdown . --output-file=README.md --recursive --read-comments --output-mode=inject
# timestamp files
files=$(find . -type f -name "README.md")
for file in ${files}
do
echo
echo 'Processing '$file
tempFile='TEMP-README.txt'
touch $tempFile
rm $tempFile
cat $file | while read line; do
if [[ $line =~ ^Last ]]; then
# ignore old timestamp line if any
echo
else
echo $line >> $tempFile
fi
done
echo 'Last generated by Terraform-docs '$(date '+%Y-%m-%d %H:%M:%S') >> $tempFile
rm $file
mv $tempFile $file
done
name: "generateTerraformDoc"
displayName: "Generate > Terraform-docs"
- script: |
echo $(Build.SourceBranch)
sourceBranch=$(Build.SourceBranch)
current_branch=$(echo "${sourceBranch:11}")
email=$(Build.RequestedForEmail)
name=$(echo "${email::-7}")
git config --global user.email $email
git config --global user.name "$name (from Azure DevOps Pipeline)"
git checkout -b $current_branch
# git pull $current_branch --rebase
git add "**.md"
git commit -m "[skip ci] Update readme.md files"
git push --force --set-upstream origin $current_branch
name: "gitCommit"
displayName: "Git > Add or update readme.md files"