RousselTMLEARNING

Automation

The HCL language: resources, variables, outputs, data and expressions

Writing Terraform: terraform, provider, resource and data blocks, typed variables with validation, locals, outputs, expressions, functions, count, for_each, dynamic blocks and meta-arguments.

1. Blocks #

The structure of a configuration.

Example #

Terraform blocks
The order of files and blocks does not matter.
terraform {
  required_version = ">= 1.7"
  required_providers { aws = { source = "hashicorp/aws", version = "~> 5.0" } }
}

provider "aws" { region = var.region }

variable "region" {
  type    = string
  default = "eu-west-3"
}

variable "environnement" {
  type = string
  validation {
    condition     = contains(["recette", "prod"], var.environnement)
    error_message = "recette ou prod uniquement."
  }
}

locals {
  etiquettes = { environnement = var.environnement, gere_par = "terraform" }
}

data "aws_availability_zones" "zones" { state = "available" }

resource "aws_s3_bucket" "rapports" {
  bucket = "rapports-${var.environnement}-${random_id.suffixe.hex}"
  tags   = local.etiquettes
}

resource "random_id" "suffixe" { byte_length = 4 }

output "bucket" { value = aws_s3_bucket.rapports.bucket }

2. Repeating resources #

count, for_each, dynamic.

count or for_each? #

Meta-argumentWhen to use it
countN identical copies; addressed by index (fragile if you remove an element from the middle)
for_eachOne resource per key of a map or set: stable addresses
variable "files" { default = { facturation = 3, expedition = 5 } }

resource "aws_sqs_queue" "file" {
  for_each                   = var.files
  name                       = "commandes-${each.key}"
  visibility_timeout_seconds = each.value * 10
}

resource "aws_security_group" "web" {
  name = "web"
  dynamic "ingress" {
    for_each = [80, 443]
    content {
      from_port   = ingress.value
      to_port     = ingress.value
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  }
}

3. Expressions and functions #

Computing values.

Useful ones #

NeedExample
Conditionalvar.env == "prod" ? 3 : 1
for loop[for z in data.aws_availability_zones.zones.names : upper(z)]
Merging mapsmerge(local.etiquettes, { role = "web" })
Encodingjsonencode({...}), yamldecode(file("x.yaml"))
File templatetemplatefile("init.sh.tftpl", { port = 8080 })
terraform console
> cidrsubnet("10.0.0.0/16", 8, 2)
"10.0.2.0/24"
> [for i in range(3) : "web-${i}"]

Related articles

Terraform: principles, architecture and workflow

Understand Terraform: declarative infrastructure as code, architecture (core, providers, state), the init, pl…

Terraform state: remote backends, locking, import and refactoring

Manage Terraform state: the role of the state file, sensitive data, remote backends (S3, azurerm, gcs, HCP Te…

Terraform modules: designing, versioning and reusing

Structure Terraform with modules: root module and child modules, inputs and outputs, sources (local, Git, reg…

Keep learning

Support us

♥ SUPPORT US

Support RousselTM Learning

Courses, articles, labs and certificates stay free with no intrusive ads. A voluntary contribution, of any amount you choose, pays for hosting, lab environments and new content.

Contribute with PayPal Any amount · card or PayPal accountLearn more
QR code PayPal
Or scan this QR code with your phone

Thank you, every contribution counts!