Passer au contenu principal

Fondamentaux (Terraform)

Expressions et fonctions

HCL supporte des expressions et des fonctions built-in qui permettent de construire des configurations dynamiques sans dupliquer du code. Les maîtriser réduit considérablement la verbosité des projets Terraform et facilite la gestion des cas particuliers.

Expressions conditionnelles

variable "environment" { type = string }

locals {
  instance_type = var.environment == "prod" ? "t3.large" : "t3.micro"
  multi_az      = var.environment == "prod" ? true : false
  replica_count = var.environment == "prod" ? 3 : 1
}

Expressions for

variable "users" {
  default = ["alice", "bob", "charlie"]
}

# Transformer une liste
locals {
  upper_users = [for u in var.users : upper(u)]
  # ["ALICE", "BOB", "CHARLIE"]

  # Filtrer
  admin_users = [for u in var.users : u if u != "charlie"]
  # ["alice", "bob"]

  # Produire un map
  user_map = { for u in var.users : u => "${u}@example.com" }
  # { alice = "alice@example.com", ... }
}

# Sur une ressource (for_each)
resource "aws_iam_user" "users" {
  for_each = toset(var.users)
  name     = each.key
}

Fonctions de chaînes

locals {
  # Concaténation
  bucket_name = "${var.project}-${var.environment}-logs"

  # Manipulation
  upper_env   = upper(var.environment)
  lower_name  = lower(var.project_name)
  trimmed     = trimspace("  hello  ")

  # Format
  formatted   = format("%s-%03d", var.prefix, count.index)

  # Split / join
  parts       = split(",", "a,b,c")    # ["a", "b", "c"]
  joined      = join("-", ["a", "b"])  # "a-b"

  # Regex
  clean_name  = replace(var.name, "/[^a-z0-9-]/", "-")
}

Fonctions de collections

locals {
  # Listes
  flat     = flatten([[1, 2], [3, 4]])        # [1, 2, 3, 4]
  unique   = distinct(["a", "b", "a"])        # ["a", "b"]
  combined = concat(var.list1, var.list2)
  length   = length(var.users)

  # Maps
  merged   = merge(var.default_tags, var.extra_tags)
  keys     = keys(var.servers_map)
  values   = values(var.servers_map)
  selected = lookup(var.ami_map, var.region, "default-ami")

  # Conversion
  as_set   = toset(var.users)
  as_list  = tolist(var.users_set)
  as_map   = tomap({ key = "value" })
}

Fonctions réseau et encodage

locals {
  # Calculs CIDR
  subnets     = cidrsubnets("10.0.0.0/16", 4, 4, 4)
  # ["10.0.0.0/20", "10.0.16.0/20", "10.0.32.0/20"]

  host_ip     = cidrhost("10.0.1.0/24", 5)   # "10.0.1.5"
  netmask     = cidrnetmask("10.0.0.0/16")    # "255.255.0.0"

  # Encodage
  b64         = base64encode("hello")
  b64_file    = filebase64("${path.module}/script.sh")
  json_str    = jsonencode({ key = "value" })
  yaml_str    = yamlencode({ key = "value" })

  # Fichiers
  template    = templatefile("${path.module}/tpl/config.tpl", {
    host = var.db_host
    port = var.db_port
  })
}

Fonctions de vérification

locals {
  safe_value = try(var.complex_object.optional_key, "default")
  # try() évalue la première expression sans erreur

  is_valid   = can(regex("^[a-z]+$", var.name))
  # can() retourne true si l'expression ne lève pas d'erreur
}