Templates Packer¶
Les templates HCL2 permettent de parametrer les builds via des variables, des expressions et des blocs dynamiques. Un même template peut produire des images différentes selon le contexte d'exécution.
Variables¶
Les variables se declarent dans un bloc variable avec un type et une valeur par défaut optionnelle.
variable "project_id" {
type = string
description = "ID du projet GCP"
}
variable "region" {
type = string
default = "europe-west1"
}
variable "tags" {
type = list(string)
default = ["packer", "base"]
}
On accede a une variable avec le préfixe var. :
source "googlecompute" "base" {
project_id = var.project_id
zone = "${var.region}-b"
tags = var.tags
}
Fichiers de variables¶
Les fichiers .auto.pkrvars.hcl sont charges automatiquement. Les autres fichiers necessitent le flag -var-file :
# Charge automatiquement project.auto.pkrvars.hcl
packer build .
# Charge un fichier specifique
packer build -var-file=prod.pkrvars.hcl .
Exemple de fichier prod.pkrvars.hcl :
Secrets
Ne jamais commiter de fichiers de variables contenant des secrets (mots de passe, clés d'API). Utiliser des variables d'environnement prefixees PKR_VAR_ ou un gestionnaire de secrets.
Locals¶
Les locals sont des variables calculees, non modifiables depuis l'extérieur. Ils évitent la répétition d'expressions complexes.
locals {
timestamp = formatdate("YYYYMMDDhhmmss", timestamp())
image_name = "base-${var.os}-${local.timestamp}"
image_family = "base-${var.os}"
}
source "googlecompute" "base" {
image_name = local.image_name
image_family = local.image_family
}
Conditions¶
Packer HCL2 supporte les expressions ternaires pour adapter le build selon le contexte.
variable "env" {
type = string
default = "dev"
}
locals {
disk_size = var.env == "prod" ? 50 : 20
machine_type = var.env == "prod" ? "n2-standard-4" : "e2-medium"
}
source "googlecompute" "base" {
disk_size = local.disk_size
machine_type = local.machine_type
}
Blocs dynamiques¶
Le bloc dynamic avec for_each permet de générer plusieurs blocs identiques à partir d'une liste ou d'une map.
variable "provisioner_scripts" {
type = list(string)
default = ["scripts/base.sh", "scripts/security.sh"]
}
build {
sources = ["source.googlecompute.base"]
dynamic "provisioner" {
labels = ["shell"]
for_each = var.provisioner_scripts
content {
script = provisioner.value
}
}
}
Fonctions utiles¶
| Fonction | Usage |
|---|---|
timestamp() | Horodatage RFC3339 au moment du build |
formatdate("YYYYMMDD", t) | Formate un timestamp en chaîne lisible |
upper(s) / lower(s) | Conversion de casse |
replace(s, old, new) | Remplacement de sous-chaîne |
file("chemin/fichier") | Lit le contenu d'un fichier |
Exemple combinant plusieurs fonctions :
locals {
date = formatdate("YYYY-MM-DD", timestamp())
image_name = replace("base-${var.os}-${local.date}", ".", "-")
}
Structure de projet recommandee¶
packer/
├── main.pkr.hcl # Sources et builds
├── variables.pkr.hcl # Declarations de variables
├── locals.pkr.hcl # Locals calcules
├── versions.pkr.hcl # required_plugins
├── dev.auto.pkrvars.hcl # Valeurs par defaut (non secret)
└── prod.pkrvars.hcl # Valeurs prod (a ne pas commiter)
Séparer les declarations de variables et les valeurs facilite la réutilisation du template dans plusieurs environnements.