Dit deel is nog niet vertaald. Je ziet de Engelse tekst.
$ als gewone gebruiker# als root (of met sudo)
Vaardigheden in dit hoofdstuk
- Complexe types, expressies, functies en dynamische blokken
Use complex types
Besides string, number and bool, variables can be lists, sets, maps, objects and tuples.
| Type | Example value |
|---|---|
list(string) | ["web", "app", "db"] (ordered, duplicates allowed) |
set(string) | ["web", "app"] (no order, no duplicates) |
map(string) | { env = "dev", owner = "it" } |
object({...}) | { name = "web", size = "Standard_B2s", zone = 1 } |
tuple([string, number]) | ["web", 2] |
variable "subnets" {
type = map(object({
prefix = string
nsg_open = list(number)
}))
default = {
web = { prefix = "10.30.1.0/24", nsg_open = [80, 443] }
app = { prefix = "10.30.2.0/24", nsg_open = [8080] }
}
}Create many resources with count and for_each
count makes N copies (index count.index). for_each makes one per map key or set item (key each.key, value each.value).
resource "azurerm_subnet" "this" {
for_each = var.subnets
name = "snet-${each.key}"
resource_group_name = azurerm_resource_group.app.name
virtual_network_name = azurerm_virtual_network.app.name
address_prefixes = [each.value.prefix]
}
resource "azurerm_public_ip" "lb" {
count = var.env == "prod" ? 1 : 0
name = "pip-lb-${var.env}"
location = azurerm_resource_group.app.location
resource_group_name = azurerm_resource_group.app.name
allocation_method = "Static"
sku = "Standard"
}Onthoud
Prefer for_each with stable keys. With count, removing an item in the middle shifts the index and Terraform replaces the following resources.
Write expressions
Expressions compute values: conditions, for expressions, splats and string templates.
locals {
is_prod = var.env == "prod"
vm_size = local.is_prod ? "Standard_D2s_v5" : "Standard_B2s"
subnet_ids = [for s in azurerm_subnet.this : s.id]
upper_names = { for k, v in var.subnets : k => upper(k) }
open_ports = flatten([for k, v in var.subnets : v.nsg_open])
all_nic_ids = azurerm_network_interface.web[*].id
greeting = "Hello from ${var.env}%{ if local.is_prod } (production)%{ endif }"
}| Expression | Meaning |
|---|---|
cond ? a : b | Choose a or b |
[for x in LIST : f(x)] | A new list |
{for k, v in MAP : k => f(v)} | A new map |
[for x in LIST : x if cond] | Filter |
resource[*].attr | Splat: the attribute of all instances |
"${…}", %{ if … } | String templates |
Use built-in functions
Terraform has many functions; you can not write your own. Try them in terraform console.
| Function | Example → result |
|---|---|
lower, upper, replace | lower("ShOp") → "shop" |
join, split | join(",", ["a","b"]) → "a,b" |
length, contains, lookup | lookup(var.sizes, "dev", "B2s") |
merge, concat, flatten, distinct | merge(local.tags, {app = "shop"}) |
cidrsubnet, cidrhost | cidrsubnet("10.30.0.0/16", 8, 1) → "10.30.1.0/24" |
file, templatefile, base64encode | templatefile("cloud-init.tpl", {env = var.env}) |
try, can, coalesce | try(var.cfg.size, "B2s") |
jsonencode, yamldecode | Policies and config files |
Generate nested blocks with dynamic
A dynamic block writes repeated nested blocks (like NSG rules) from a list or map.
resource "azurerm_network_security_group" "web" {
name = "nsg-web"
location = azurerm_resource_group.app.location
resource_group_name = azurerm_resource_group.app.name
dynamic "security_rule" {
for_each = var.subnets["web"].nsg_open
content {
name = "allow-${security_rule.value}"
priority = 100 + security_rule.key
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = tostring(security_rule.value)
source_address_prefix = "Internet"
destination_address_prefix = "*"
}
}
}Let op
Dynamic blocks make code harder to read. Use them for real lists, not to hide two simple blocks.