Skip to content

You are viewing documentation for Instruqt 2.0 Labs. For Tracks documentation, please visit docs.instruqt.com.

Functions Overview


Functions allow you to transform and combine values within HCL expressions. Instruqt labs support both standard HCL functions and custom functions specific to lab environments.

Functions are organized into logical categories based on their purpose:

Text manipulation, formatting, and string operations.

Mathematical operations and number formatting.

Operations on lists, maps, and sets.

Encoding and decoding data in various formats.

File operations and path manipulation.

Date formatting and time calculations.

Functions specific to Instruqt lab environments.

Functions are called by name with comma-separated arguments in parentheses:

# Simple function call
upper("hello") # Returns "HELLO"
# Function with multiple arguments
join(", ", ["apple", "banana", "cherry"]) # Returns "apple, banana, cherry"
# Nested function calls
upper(trim(" hello world ")) # Returns "HELLO WORLD"

Functions can be used in any HCL expression within your lab configuration:

resource "container" "app" {
image {
name = "nginx:${lower(var.environment)}" # Use lower() function
}
environment = {
API_KEY = base64_encode(var.api_secret) # Encode sensitive data
HOME_DIR = data("workspace") # Get lab data directory
}
}
resource "template" "config" {
source = file("./config.tmpl") # Read template file
destination = "./config.json"
variables = {
release_date = formatdate("YYYY-MM-DD", var.release_date) # Format a date you supply
host_ip = docker_ip() # Get Docker host IP
}
}

HCL automatically converts between compatible types, but you can use functions for explicit conversions:

# String to number: parseint for integers, jsondecode for decimals
locals {
port = parseint(var.port_string, 10) # "8080" -> 8080
ratio = jsondecode(var.ratio_string) # "0.75" -> 0.75
}
# Number to string
locals {
message = format("Port: %d", local.port)
}
# JSON encoding/decoding
locals {
config_json = jsonencode({
name = "lab"
enabled = true
})
parsed_config = jsondecode(local.config_json)
}
resource "container" "web" {
count = 3
image {
name = "app:latest"
}
environment = {
INSTANCE_NAME = format("web-%02d", count.index + 1) # web-01, web-02, web-03
}
}
resource "container" "app" {
image {
name = var.use_alpine ? "app:alpine" : "app:ubuntu"
}
environment = {
LOG_LEVEL = upper(var.log_level != "" ? var.log_level : "info") # Default to "INFO"
}
}
variable "allowed_regions" {
default = ["us-east-1", "us-west-2", "eu-west-1"]
}
resource "aws_account" "lab" {
regions = concat(
var.allowed_regions,
["us-central-1"] # Always include us-central-1
)
}
  1. Use Descriptive Variable Names: Make function usage clear

    locals {
    normalized_username = lower(join("-", split("@", var.email)))
    }
  2. Handle Edge Cases: Consider empty values and errors

    locals {
    safe_port = var.custom_port != "" ? var.custom_port : "8080"
    trimmed_input = trimspace(var.user_input)
    }
  3. Prefer Built-in Functions: Use standard functions over complex expressions

    # Good
    locals {
    items = split(",", var.csv_list)
    }
    # Avoid complex regex when simpler functions work
  4. Document Complex Expressions: Add comments for clarity

    locals {
    # Extract username from email by taking everything before @
    username = element(split("@", var.email), 0)
    }