terra_madre/hcl

HCL Expression and Block Types

This module defines the core HCL (HashiCorp Configuration Language) types used as the foundation for Terraform configurations.

References

Types

Binary operators. Reference: https://developer.hashicorp.com/terraform/language/expressions/operators

pub type BinaryOperator {
  Add
  Subtract
  Multiply
  Divide
  Modulo
  Equal
  NotEqual
  LessThan
  LessEq
  GreaterThan
  GreaterEq
  And
  Or
}

Constructors

  • Add
  • Subtract
  • Multiply
  • Divide
  • Modulo
  • Equal
  • NotEqual
  • LessThan
  • LessEq
  • GreaterThan
  • GreaterEq
  • And
  • Or

Generic HCL block - the fundamental structural element.

Example

resource "aws_instance" "web" {
  ami           = "ami-12345"
  instance_type = "t2.micro"

  ebs_block_device {
    device_name = "/dev/sda1"
  }
}
Block(
  type_: "resource",
  labels: ["aws_instance", "web"],
  attributes: dict.from_list([
    #("ami", StringLiteral("ami-12345")),
    #("instance_type", StringLiteral("t2.micro")),
  ]),
  blocks: [
    Block(
      type_: "ebs_block_device",
      labels: [],
      attributes: dict.from_list([
        #("device_name", StringLiteral("/dev/sda1")),
      ]),
      blocks: [],
    ),
  ],
)
pub type Block {
  Block(
    type_: String,
    labels: List(String),
    attributes: dict.Dict(String, Expr),
    blocks: List(Block),
  )
}

Constructors

  • Block(
      type_: String,
      labels: List(String),
      attributes: dict.Dict(String, Expr),
      blocks: List(Block),
    )

Condition block for precondition/postcondition and variable validation.

pub type Condition {
  Condition(condition: Expr, error_message: String)
}

Constructors

  • Condition(condition: Expr, error_message: String)

Represents all HCL expression types.

Examples

// String literal: "hello"
StringLiteral("hello")

// Integer: 42
IntLiteral(42)

// Reference: var.region
GetAttr(Identifier("var"), "region")

// Function call: file("path/to/file")
FunctionCall("file", [StringLiteral("path/to/file")], False)

// Conditional: var.enabled ? "yes" : "no"
Conditional(
  GetAttr(Identifier("var"), "enabled"),
  StringLiteral("yes"),
  StringLiteral("no"),
)
pub type Expr {
  StringLiteral(String)
  IntLiteral(Int)
  FloatLiteral(Float)
  BoolLiteral(Bool)
  NullLiteral
  Identifier(String)
  GetAttr(Expr, String)
  Index(Expr, Expr)
  ListExpr(List(Expr))
  MapExpr(List(#(MapKey, Expr)))
  TemplateExpr(List(TemplatePart))
  Heredoc(
    marker: String,
    indent_strip: Bool,
    content: List(TemplatePart),
  )
  FunctionCall(
    name: String,
    args: List(Expr),
    expand_final: Bool,
  )
  UnaryOp(UnaryOperator, Expr)
  BinaryOp(left: Expr, op: BinaryOperator, right: Expr)
  Conditional(
    condition: Expr,
    true_result: Expr,
    false_result: Expr,
  )
  ForExpr(ForClause)
  Splat(Expr, SplatType)
}

Constructors

  • StringLiteral(String)

    String literal: "us-west-2"

  • IntLiteral(Int)

    Integer literal: 8080

  • FloatLiteral(Float)

    Floating-point literal: 3.14

  • BoolLiteral(Bool)

    Boolean literal: true / false

  • NullLiteral

    Null literal: null

  • Identifier(String)

    Bare identifier - root of attribute access chains: var, local, aws_instance

  • GetAttr(Expr, String)

    Attribute access: var.region, aws_instance.web.id

  • Index(Expr, Expr)

    Index access: var.list[0], var.map["key"]

  • ListExpr(List(Expr))

    List/tuple: ["a", "b", "c"]

  • MapExpr(List(#(MapKey, Expr)))

    Map/object: { name = "example", port = 8080 }

  • TemplateExpr(List(TemplatePart))

    Template string with interpolations: "Hello, ${var.name}!"

  • Heredoc(
      marker: String,
      indent_strip: Bool,
      content: List(TemplatePart),
    )

    Heredoc: <<EOF ... EOF

  • FunctionCall(name: String, args: List(Expr), expand_final: Bool)

    Function call: file("config.json"), max(1, 2, 3) Set expand_final=True for trailing ...: concat(list1, list2...)

  • UnaryOp(UnaryOperator, Expr)

    Unary operation: -5, !var.enabled

  • BinaryOp(left: Expr, op: BinaryOperator, right: Expr)

    Binary operation: 1 + 2, var.count > 0, var.a && var.b

  • Conditional(
      condition: Expr,
      true_result: Expr,
      false_result: Expr,
    )

    Conditional (ternary): var.enabled ? "on" : "off"

  • ForExpr(ForClause)

    For expression: [for s in var.list : upper(s)]

  • Splat(Expr, SplatType)

    Splat expression: aws_instance.example[*].id

For expression clause. Reference: https://developer.hashicorp.com/terraform/language/expressions/for

pub type ForClause {
  ForList(
    key_var: option.Option(String),
    value_var: String,
    collection: Expr,
    result: Expr,
    condition: option.Option(Expr),
  )
  ForMap(
    key_var: option.Option(String),
    value_var: String,
    collection: Expr,
    key_result: Expr,
    value_result: Expr,
    condition: option.Option(Expr),
    grouping: Bool,
  )
}

Constructors

  • ForList(
      key_var: option.Option(String),
      value_var: String,
      collection: Expr,
      result: Expr,
      condition: option.Option(Expr),
    )

    [for v in coll : result] or [for k, v in coll : result if cond]

  • ForMap(
      key_var: option.Option(String),
      value_var: String,
      collection: Expr,
      key_result: Expr,
      value_result: Expr,
      condition: option.Option(Expr),
      grouping: Bool,
    )

    {for v in coll : k => v} or {for k, v in coll : k => v...}

Specifies which attributes to ignore during updates.

pub type IgnoreChanges {
  IgnoreAll
  IgnoreList(List(Expr))
}

Constructors

  • IgnoreAll
  • IgnoreList(List(Expr))

Lifecycle configuration for resources. Reference: https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle

pub type Lifecycle {
  Lifecycle(
    create_before_destroy: option.Option(Bool),
    prevent_destroy: option.Option(Bool),
    ignore_changes: option.Option(IgnoreChanges),
    replace_triggered_by: option.Option(List(Expr)),
    precondition: List(Condition),
    postcondition: List(Condition),
  )
}

Constructors

Key in a map expression - can be identifier or computed.

{ name = "static", (var.key) = "dynamic" }
pub type MapKey {
  IdentKey(String)
  ExprKey(Expr)
}

Constructors

  • IdentKey(String)
  • ExprKey(Expr)

Meta-arguments shared by resource, data, and module blocks. Reference: https://developer.hashicorp.com/terraform/language/meta-arguments/count

pub type MetaArguments {
  MetaArguments(
    count: option.Option(Expr),
    for_each: option.Option(Expr),
    provider: option.Option(Expr),
    depends_on: option.Option(List(Expr)),
  )
}

Constructors

Splat expression type. Reference: https://developer.hashicorp.com/terraform/language/expressions/splat

pub type SplatType {
  FullSplat
  AttrSplat
}

Constructors

  • FullSplat
  • AttrSplat

Template directives for control flow within strings.

"Hello, %{ if var.name != "" }${var.name}%{ else }World%{ endif }!"
pub type TemplateDirective {
  IfDirective(
    condition: Expr,
    true_branch: List(TemplatePart),
    false_branch: List(TemplatePart),
  )
  ForDirective(
    key_var: option.Option(String),
    value_var: String,
    collection: Expr,
    body: List(TemplatePart),
  )
}

Constructors

Part of a template expression.

pub type TemplatePart {
  LiteralPart(String)
  Interpolation(Expr)
  Directive(TemplateDirective)
}

Constructors

Unary operators. Reference: https://developer.hashicorp.com/terraform/language/expressions/operators

pub type UnaryOperator {
  Negate
  Not
}

Constructors

  • Negate
  • Not

Values

pub fn block_with_attrs(
  type_: String,
  labels: List(String),
  attributes: List(#(String, Expr)),
) -> Block

Create a block with attributes but no nested blocks.

block_with_attrs("provider", ["aws"], [#("region", StringLiteral("us-west-2"))])
pub fn empty_lifecycle() -> Lifecycle

Create empty lifecycle configuration.

pub fn empty_meta() -> MetaArguments

Create empty meta-arguments.

pub fn ref(path: String) -> Expr

Build a reference chain from dot-notation: "var.region" -> GetAttr(Identifier("var"), "region")

ref("var.region")
// => GetAttr(Identifier("var"), "region")

ref("aws_instance.web.public_ip")
// => GetAttr(GetAttr(Identifier("aws_instance"), "web"), "public_ip")
pub fn simple_block(
  type_: String,
  attributes: List(#(String, Expr)),
) -> Block

Create a simple block with no labels or nested blocks.

simple_block("versioning", [#("enabled", BoolLiteral(True))])
Search Document