Aller au contenu

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 :

project_id = "mon-projet-prod"
region     = "europe-west1"
tags       = ["packer", "prod"]

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.

export PKR_VAR_project_id="mon-projet"
packer build .

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.