Cheatsheet - HCL
HCL (HashiCorp Configuration Language) is a configuration language created by HashiCorp. It's designed to be human-friendly for machine-generated, and provides a structured way to define configurations for tools like Terraform, Vault, Nomad, Consul, and Packer.
It's a superset of JSON, meaning any valid JSON is also valid HCL. However, HCL adds features that make it more readable and flexible for human users.
Basic Syntax & Structure
HCL is built around blocks and arguments.
Arguments: Set a value for a specific name.
# argument_name = value
name = "Terraform"
version = 1.0
enabled = true
Blocks: Define a container for arguments and other nested blocks. Blocks have a type, and optionally one or more labels.
# block_type "block_label1" "block_label2" {
# argument = value
# nested_block_type "label" { ... }
# }
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t2.micro"
tags = {
Name = "HelloWorld"
Env = "Dev"
}
}
Comments:
# This is a single-line comment
// This is also a single-line comment
/* This is a multi-line comment */
Data Types
HCL supports common data types.
Strings: Enclosed in double quotes. Can use interpolation.
region = "us-east-1"
message = "Hello, ${var.user_name}!"
Numbers: Integers or floating-point numbers.
count = 5
price = 99.99
Booleans: true
or false
.
ssl_enabled = true
Lists/Tuples: Ordered collections of values.
subnets = ["10.0.1.0/24", "10.0.2.0/24"]
Maps/Objects: Key-value pairs. Keys are strings.
tags = {
Environment = "Production"
Owner = "IT Team"
}
Null: null
. Represents the absence of a value.
Expressions
Expressions allow dynamic values and logic.
Literal Expressions: Directly represent a value (e.g., "string"
, 123
, true
, ["a", "b"]
, {key="val"}
).
Reference Expressions: Reference a named value.
var.name
: Access an input variable.resource_type.resource_name.attribute
: Access an attribute of a resource.local.name
: Access a local value.
Arithmetic Operators: +
, -
, *
, /
, %
total_cost = var.num_servers * 50.0
Comparison Operators: ==
, !=
, <
, >
, <=
, >=
is_prod = var.environment == "production"
Logical Operators: &&
(and), ||
(or), !
(not)
condition = var.enabled && (var.mode == "active" || var.mode == "standby")
Conditional Operator (Ternary): condition ? true_val : false_val
instance_type = var.env == "prod" ? "m5.large" : "t3.medium"
Collection Operators:
- Index Access:
list[index]
,map["key"]
- Splat Operator (
.*
and[*]
): Transform a list of objects into a list of a specific attribute.# If az_list is a list of objects like [{id="a", zone="us-east-1a"}, ...] zones = az_list[*].zone # ["us-east-1a", "us-east-1b", ...]
Function Calls: function_name(arg1, arg2, ...)
instance_ip = cidrhost("10.0.0.0/16", 5)
lower_case_name = lower("MYAPP")
Common built-in functions often depend on the HCL-consuming tool (e.g., Terraform functions).
Variables & Values (Terraform-centric, but general HCL concept)
While HCL itself is just a language, how variables are defined and used is typically driven by the tool using it. Here's a common pattern from Terraform:
Input Variables (variable
block): Define values to be provided to the configuration.
variable "region" {
description = "AWS region"
type = string
default = "us-east-1"
}
# Usage: var.region
Local Values (locals
block): Define named expressions that can be reused within the configuration.
locals {
common_tags = {
Project = "MyProject"
Env = var.environment
}
full_name = "${var.prefix}-${var.service_name}"
}
# Usage: local.common_tags, local.full_name
Output Values (output
block): Define values that are exposed as outputs of the configuration.
output "instance_ip" {
description = "Public IP of the EC2 instance"
value = aws_instance.web.public_ip
}
String Interpolation & Templates
HCL uses ${...}
for interpolation within strings.
Simple Interpolation:
server_name = "app-${count.index}"
Conditional Interpolation:
message = "VM running in ${var.env == "prod" ? "Production" : "Development"}."
Dynamic Blocks (HCL2): Create multiple nested blocks based on a collection.
resource "aws_security_group" "example" {
name = "example"
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.port
to_port = ingress.value.port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
}
File Types
.hcl
: Standard HCL file extension..tf
: Terraform configuration file extension (which uses HCL)..json
: HCL can parse JSON, so you can sometimes use.json
files for configuration, especially for machine-generated configs.