Terraform Associate
Deep Dive
HCL (HashiCorp Configuration Language) es el lenguaje declarativo con el que describes toda la infraestructura en Terraform. Dominar su sintaxis es la base para el examen y para el trabajo diario.
Contenido
Todo en Terraform se define dentro de bloques. Cada bloque tiene un tipo, etiquetas opcionales y un cuerpo de argumentos entre llaves.
| Bloque | Etiquetas | Propósito |
|---|---|---|
| terraform {} | ninguna | Configuración del propio Terraform (versión requerida, providers, backend) |
| provider "aws" {} | "aws" | Configura un proveedor (credenciales, región, alias) |
| resource "aws_vpc" "main" {} | "aws_vpc" "main" | Define un recurso gestionado: tipo + nombre local |
| data "aws_ami" "ubuntu" {} | "aws_ami" "ubuntu" | Lee datos de infraestructura existente sin crearla |
| variable "env" {} | "env" | Declara un parámetro de entrada del módulo |
| output "vpc_id" {} | "vpc_id" | Expone un valor del módulo hacia afuera |
| locals {} | ninguna | Define valores intermedios reutilizables sin exponer como variable |
| module "vpc" {} | "vpc" | Llama a un módulo hijo (local o remoto) |
# Estructura mínima de un módulo raíz
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = local.vpc_name
}
}
variable "aws_region" {
type = string
default = "us-east-1"
}
locals {
vpc_name = "vpc-${var.aws_region}"
}
output "vpc_id" {
value = aws_vpc.main.id
}Los argumentos dentro de los bloques tienen tipos. Terraform los valida en tiempo de plan.
Tipos primitivos
Texto. Con interpolación: "vpc-${var.env}"
Entero o decimal: 3, 3.14
Booleano. true o false (sin comillas)
Tipos complejos
Lista ordenada. Acceso por índice: var.list[0]
Conjunto sin duplicados ni orden garantizado
Mapa clave-valor. Acceso: var.map["key"]
Estructura con claves tipadas específicas
Lista con tipos heterogéneos en posiciones fijas
Las referencias conectan bloques entre sí. Terraform las usa para construir el grafo de dependencias automáticamente.
| Referencia | Ejemplo | Descripción |
|---|---|---|
| <tipo>.<nombre>.<atributo> | aws_vpc.main.id | Atributo de un recurso |
| var.<nombre> | var.aws_region | Valor de una variable de entrada |
| local.<nombre> | local.vpc_name | Valor local calculado |
| data.<tipo>.<nombre>.<atrib> | data.aws_ami.ubuntu.id | Atributo de una data source |
| module.<nombre>.<output> | module.vpc.vpc_id | Output de un módulo hijo |
| path.module | path.module | Ruta del directorio del módulo actual |
| terraform.workspace | terraform.workspace | Nombre del workspace activo |
# Interpolación en strings: ${ ... }
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id # referencia directa
cidr_block = "10.0.1.0/24"
availability_zone = "${var.aws_region}a" # interpolación
tags = {
Name = "subnet-${terraform.workspace}-public"
}
}💡 Interpolación vs referencia directa
Cuando el argumento acepta directamente una referencia, no uses interpolación: escribe vpc_id = aws_vpc.main.id, no vpc_id = "${aws_vpc.main.id}". La interpolación convierte el valor a string, perdiendo el tipo original.
# Comentario de una línea (estilo preferido en HCL)
// También válido (estilo C) — menos común en Terraform
/* Comentario
de múltiples
líneas */
# terraform fmt reordena los argumentos alfabéticamente
# y alinea los signos = en bloques con varios argumentos:
resource "aws_s3_bucket" "logs" {
bucket = "my-logs-bucket" # argumento corto
force_destroy = true # argumento largo alineado
}🎯 Para el examen
#, // y /* */. El examen puede preguntar cuáles son válidos.terraform fmt usa 2 espacios de indentación y alinea = en bloques. Nunca uses tabs manualmente..tf (o .tf.json para JSON nativo).Terraform carga todos los archivos .tf del directorio de trabajo como si fueran uno solo. La separación en archivos es solo para organización humana.
main.tf
Recursos principales del módulo. Es el punto de entrada conceptual.
variables.tf
Todas las declaraciones de variable {}. Solo la declaración, no los valores.
outputs.tf
Todos los bloques output {}.
providers.tf
Bloque terraform {} con required_providers y bloques provider {}.
locals.tf
Bloque locals {} con valores intermedios. Opcional para módulos pequeños.
versions.tf
Alternativa a providers.tf para separar el bloque terraform {} de los providers.
⚠️ Archivos que NO se cometen al VCS
terraform.tfstate / *.tfstate.backup — contienen datos sensibles en texto plano.terraform/ — directorio de plugins descargados (pesado, regenerable con init)*.tfvars con secretos — credenciales, tokens, contraseñas.terraform.lock.hcl — sí se comete: fija versiones exactas de providers¿Entendiste este tema?
Pon a prueba lo que acabas de aprender
En un archivo HCL de Terraform, necesitas referenciar el atributo id de un recurso aws_instance llamado web desde otro recurso. ¿Cuál es la sintaxis correcta?