diff --git a/content/docs/iac/languages-sdks/hcl/_index.md b/content/docs/iac/languages-sdks/hcl/_index.md new file mode 100644 index 000000000000..9310cd275d62 --- /dev/null +++ b/content/docs/iac/languages-sdks/hcl/_index.md @@ -0,0 +1,93 @@ +--- +title_tag: "HCL | Languages & SDKs" +meta_desc: An overview of Pulumi HCL, a language plugin for writing infrastructure as code in Terraform-like HCL syntax on any cloud. +title: HCL +h1: Pulumi & HCL +meta_image: /images/docs/meta-images/docs-meta.png +menu: + iac: + name: HCL + parent: iac-languages + weight: 7 + identifier: iac-languages-hcl + languages: + identifier: hcl-language + weight: 7 + +aliases: +- /docs/languages-sdks/hcl/ +--- + +Pulumi supports writing your infrastructure as code using Pulumi HCL, a language plugin that lets you author Pulumi programs in [Terraform](https://developer.hashicorp.com/terraform)-like HCL syntax. You get familiar HCL blocks, expressions, and built-in functions while using Pulumi's state management, secrets handling, and deployment engine. + +Pulumi HCL is developed in the [pulumi-labs/pulumi-hcl](https://github.com/pulumi-labs/pulumi-hcl) repository. + +## Prerequisites + +All you need to use Pulumi HCL is the [Pulumi CLI](/docs/install/), version 3.235.0 or later. The HCL language and converter plugins ship with the CLI. + +## Example + +A Pulumi HCL project consists of a `Pulumi.yaml` with `runtime: hcl` and one or more `.hcl` files in the project directory. + +`Pulumi.yaml`: + +```yaml +name: simple-hcl +runtime: hcl +description: A simple Pulumi HCL project +``` + +`main.hcl`: + +```hcl +pulumi { + required_providers { + random = { + source = "pulumi/random" + version = ">= 4.0.0" + } + } +} + +variable "prefix" { + type = string + default = "test" +} + +resource "random_pet" "my_pet" { + prefix = var.prefix + length = 2 +} + +output "pet_name" { + value = random_pet.my_pet.id +} +``` + +{{% notes "info" %}} +Provider sources must use the `pulumi/` namespace (for example, `pulumi/aws`), not `hashicorp/`. +{{% /notes %}} + +Further examples are available in the [Pulumi HCL GitHub repository](https://github.com/pulumi-labs/pulumi-hcl/tree/master/examples). The specification for Pulumi HCL programs is in the [Pulumi HCL reference](/docs/iac/languages-sdks/hcl/hcl-language-reference/). + +## Pulumi programming model + +The Pulumi programming model defines the core concepts you will use when creating infrastructure as code programs using Pulumi. [Concepts](/docs/iac/concepts/) describes these concepts with examples available in all supported languages. + +To learn how the Pulumi programming model is implemented for Pulumi HCL, refer to the [Pulumi HCL reference](/docs/iac/languages-sdks/hcl/hcl-language-reference/). + +## Terraform compatibility + +Pulumi HCL is broadly compatible with Terraform-like HCL syntax. Resources, data sources, variables, locals, outputs, modules, expressions, and most built-in functions work as documented by HashiCorp, with two notable behavioral differences: + +- Provider sources must use the `pulumi/` namespace, not `hashicorp/`. +- Resource replacement creates the new resource before deleting the old one (the opposite of Terraform). Set `create_before_destroy = false` in a `lifecycle` block to opt into delete-first behavior. + +For the full list of differences and unsupported features, see the [Terraform compatibility section](/docs/iac/languages-sdks/hcl/hcl-language-reference/#terraform-compatibility) of the reference. + +## HCL packages + +The [Pulumi Registry](/registry/) houses 100+ packages that can be consumed from Pulumi HCL programs by declaring them in a `pulumi` `required_providers` block. + +For Terraform or OpenTofu providers that aren't published in the Pulumi Registry, use [Any Terraform Provider](/docs/iac/concepts/providers/any-terraform-provider/) to generate a local package on the fly. This is especially relevant for Pulumi HCL users who are bringing existing programs from a Terraform codebase that depends on community or internal providers without bridged Pulumi equivalents. diff --git a/content/docs/iac/languages-sdks/hcl/hcl-component-reference.md b/content/docs/iac/languages-sdks/hcl/hcl-component-reference.md new file mode 100644 index 000000000000..a2ebb77682e6 --- /dev/null +++ b/content/docs/iac/languages-sdks/hcl/hcl-component-reference.md @@ -0,0 +1,104 @@ +--- +title_tag: "Pulumi HCL Component Reference | Languages & SDKs" +meta_desc: Specification for authoring Pulumi multi-language components in HCL. +title: Component Reference +h1: Pulumi HCL component reference +meta_image: /images/docs/meta-images/docs-meta.png +menu: + iac: + name: Component Reference + parent: iac-languages-hcl + weight: 2 + languages: + parent: hcl-language + weight: 2 +--- + +Pulumi HCL modules can be authored as reusable Pulumi components consumable from any Pulumi language (TypeScript, Python, Go, .NET, Java, YAML, or HCL). This is known as a multi-language component (MLC). + +An HCL module becomes an MLC when it has a `PulumiPlugin.yaml` containing `runtime: hcl` and declares a `component` block (and optionally a `package` block) inside the module's `pulumi` block. The rest of the module is an ordinary Pulumi HCL program — see the [Pulumi HCL reference](/docs/iac/languages-sdks/hcl/hcl-language-reference/) for the full program model. + +## Example + +`PulumiPlugin.yaml`: + +```yaml +runtime: hcl +``` + +`main.hcl`: + +```hcl +pulumi { + component { + name = "VpcNetwork" + } + package { + name = "my-networking" + version = "1.0.0" + } + required_providers { + aws = { + source = "pulumi/aws" + version = ">= 6.0" + } + } +} + +variable "cidr_block" { + type = string + default = "10.0.0.0/16" +} + +resource "aws_vpc" "vpc" { + cidr_block = var.cidr_block +} + +output "vpc_id" { + value = aws_vpc.vpc.id +} +``` + +The module's [`variable`](/docs/iac/languages-sdks/hcl/hcl-language-reference/#variables) blocks become the component's inputs and its [`output`](/docs/iac/languages-sdks/hcl/hcl-language-reference/#outputs) blocks become the component's outputs. + +## Component definition + +### `component` block + +Declares the HCL module as a component resource. + +| Field | Type | Required | Default | Description | +| - | - | - | - | - | +| `name` | string | Yes | — | Component name. Must be a valid Pulumi name (alphanumeric, hyphens, underscores; must start with a letter or underscore). | +| `module` | string | No | `"index"` | Module segment of the component's resource token. Must be a valid Pulumi name. | + +### `package` block + +Declares the package identity for the component. + +| Field | Type | Required | Default | Description | +| - | - | - | - | - | +| `name` | string | No | Directory name of the module | Package name. Must be a valid Pulumi name when specified. | +| `version` | string | No | `"0.0.0-dev"` | Package version. Must be a valid [semver](https://semver.org/) string when specified. | + +Only one `component` block and one `package` block are allowed per `pulumi` block. Using `component` or `package` in a regular Pulumi program (one invoked directly via `pulumi up`) produces an error. + +## Resource token + +The component's Pulumi resource token is formed as: + +``` +{package.name}:{component.module}:{component.name} +``` + +For the example above the token is `my-networking:index:VpcNetwork`. + +## PulumiPlugin.yaml + +The `PulumiPlugin.yaml` file tells the Pulumi engine how to run the component provider. For HCL MLCs it should specify the `hcl` runtime: + +```yaml +runtime: hcl +``` + +The `component` and `package` blocks in the HCL source supply the provider name and version, so they do not need to be hardcoded elsewhere. diff --git a/content/docs/iac/languages-sdks/hcl/hcl-language-reference.md b/content/docs/iac/languages-sdks/hcl/hcl-language-reference.md new file mode 100644 index 000000000000..24591cb64cdd --- /dev/null +++ b/content/docs/iac/languages-sdks/hcl/hcl-language-reference.md @@ -0,0 +1,765 @@ +--- +title_tag: "Pulumi HCL Reference | Languages & SDKs" +meta_desc: Specification for the Pulumi HCL format, blocks, expressions, and built-in functions. +title: Reference +h1: Pulumi HCL reference +meta_image: /images/docs/meta-images/docs-meta.png +menu: + iac: + name: Reference + parent: iac-languages-hcl + weight: 1 + languages: + parent: hcl-language + weight: 1 +aliases: +- /docs/reference/hcl/ +- /docs/languages-sdks/hcl/hcl-language-reference/ +--- + +Pulumi programs can be defined in many languages, and the Pulumi HCL dialect offers an additional language for authoring Pulumi programs using [Terraform](https://developer.hashicorp.com/terraform)-like HCL syntax. + +A Pulumi HCL program consists of one or more `.hcl` files in a directory whose `Pulumi.yaml` specifies `runtime: hcl`: + +```yaml +name: my-project +runtime: hcl +``` + +HCL files declare infrastructure using the top-level blocks listed below. The full set of HCL [expressions](#expressions) and Terraform [built-in functions](#built-in-functions) is supported, along with Pulumi-specific asset and archive functions. See [Terraform compatibility](#terraform-compatibility) for the small number of differences. + +### Top-level blocks + +| Block | Purpose | +| - | - | +| `variable` | Declare input variables | +| `resource` | Manage cloud resources | +| `data` | Read external data via provider invocations | +| `provider` | Configure provider instances | +| `output` | Export values from the stack | +| `locals` | Define reusable intermediate values | +| `module` | Invoke local or remote modules as components | +| `call` | Invoke methods on resources | +| `moved` | Rename resources without recreation | +| `import` | Import existing cloud resources | +| `pulumi` | Required providers, version constraints, and component declarations | + +In many locations within these blocks, values are HCL expressions that reference variables, locals, resources, data sources, or modules. See [Expressions](#expressions) for the supported forms. + +### Variables + +`variable` blocks declare input values for the program. Each block has one label, the variable name, which is referenced in expressions as `var.`. + +```hcl +variable "region" { + type = string + default = "us-west-2" + description = "AWS region to deploy into" +} + +variable "instance_count" { + type = number + default = 1 +} + +variable "name" { + type = string + + validation { + condition = length(var.name) > 0 + error_message = "Name must not be empty." + } +} +``` + +| Attribute | Type | Required | Description | +| - | - | - | - | +| `type` | type expression | No | Type constraint (for example, `string`, `number`, `bool`, `list(string)`, `map(number)`, `object({...})`). | +| `default` | expression | No | Default value when the variable is not configured. | +| `description` | string | No | Human-readable description. | +| `sensitive` | bool | No | When `true`, the value becomes a [Pulumi secret](/docs/iac/concepts/secrets/). | +| `nullable` | bool | No | When `false`, rejects null values. Defaults to `true`. | +| `validation` | block | No | One or more validation rules (see below). | + +Each `validation` block has the following attributes: + +| Attribute | Type | Required | Description | +| - | - | - | - | +| `condition` | expression | Yes | Expression that must evaluate to `true`. | +| `error_message` | expression | Yes | Error message shown when the condition is `false`. | + +Variables are set through Pulumi's config system, in priority order: + +1. Environment variables: `TF_VAR_=` (highest priority). +1. Stack config: `pulumi config set : `. +1. Default values in `variable` blocks (lowest priority). + +### Resources + +`resource` blocks declare managed infrastructure. The first label is the resource type (Terraform-like, for example `aws_instance`); the second label is the logical name; the body contains the resource's input properties. + +```hcl +resource "aws_instance" "web" { + ami = "ami-12345678" + instance_type = "t3.micro" + + tags = { + Name = "web-server" + } +} +``` + +`resource` blocks support the full set of Pulumi [resource options](/docs/iac/concepts/resources/options/) as top-level attributes (with `snake_case` names — for example `retain_on_delete`, `parent`, `aliases`). See [Resource options](#resource-options) for the HCL surface and [the canonical resource-options reference](/docs/iac/concepts/resources/options/) for full semantics. Some options are also reachable via the [`lifecycle` block](#lifecycle-block) under their Terraform-like names (for example `prevent_destroy` → `protect`, `ignore_changes`). + +#### Meta-arguments + +| Argument | Type | Description | +| - | - | - | +| `count` | number | Create multiple instances indexed by `count.index`. | +| `for_each` | map or set | Create instances keyed by `each.key` with `each.value`. | +| `depends_on` | list | Explicit dependencies on other resources. | +| `provider` | reference | Specific provider configuration to use. | +| `providers` | list | Explicit provider resources (component resources only). | + +#### Lifecycle block + +```hcl +resource "aws_instance" "web" { + # ... + + lifecycle { + create_before_destroy = true + prevent_destroy = true + ignore_changes = [tags] + } +} +``` + +| Attribute | Type | Description | +| - | - | - | +| `create_before_destroy` | bool | When `false`, deletes the old resource before creating the replacement (Pulumi creates first by default). | +| `prevent_destroy` | bool | Protect the resource from accidental deletion. Maps to Pulumi's `protect` option. | +| `ignore_changes` | list | Property paths to exclude from diff detection. | + +The `lifecycle` block also supports `precondition` and `postcondition` blocks, each of which takes a `condition` expression and an `error_message` expression: + +```hcl +resource "aws_instance" "web" { + # ... + + lifecycle { + precondition { + condition = var.instance_type != "" + error_message = "Instance type must be specified." + } + + postcondition { + condition = self.public_ip != "" + error_message = "Instance must have a public IP." + } + } +} +``` + +#### Timeouts block + +```hcl +resource "aws_instance" "web" { + # ... + + timeouts { + create = "60m" + update = "30m" + delete = "2h" + } +} +``` + +| Attribute | Type | Description | +| - | - | - | +| `create` | string | Timeout for create operations. | +| `update` | string | Timeout for update operations. | +| `delete` | string | Timeout for delete operations. | + +#### Provisioners + +Provisioners run commands during resource lifecycle events. They map to the [Pulumi Command provider](/registry/packages/command/). + +```hcl +resource "aws_instance" "web" { + ami = "ami-12345678" + instance_type = "t3.micro" + + provisioner "local-exec" { + command = "echo ${self.public_ip} >> hosts.txt" + } + + provisioner "remote-exec" { + inline = [ + "sudo apt-get update", + "sudo apt-get install -y nginx", + ] + } + + provisioner "file" { + source = "config.txt" + destination = "/tmp/config.txt" + } + + connection { + type = "ssh" + user = "ubuntu" + private_key = file("~/.ssh/id_rsa") + host = self.public_ip + } +} +``` + +| Provisioner type | Pulumi equivalent | +| - | - | +| `local-exec` | `command:local:Command` | +| `remote-exec` | `command:remote:Command` | +| `file` | `command:remote:CopyToRemote` | + +Provisioner blocks accept `when` (`"create"` or `"destroy"`) and `on_failure` (`"continue"` or `"fail"`) attributes. The `self` reference inside a provisioner refers to the parent resource. `connection` blocks support SSH only; WinRM is not supported. + +#### Referencing resources + +Resources are referenced by `.`: + +```hcl +output "instance_id" { + value = aws_instance.web.id +} +``` + +When using `count`, instances are indexed: `aws_instance.web[0].id`, or `aws_instance.web[*].id` for the splat form. When using `for_each`, instances are keyed: `aws_instance.web["key"].id`. + +### Resource options + +In addition to the Terraform-like meta-arguments above, resource blocks accept Pulumi-specific [resource options](/docs/iac/concepts/resources/options/) as top-level attributes. + +```hcl +resource "aws_instance" "web" { + # ... + + parent = module.my_component + additional_secret_outputs = ["password"] + retain_on_delete = true + deleted_with = aws_vpc.main + replace_on_changes = ["ami"] + replace_with = [aws_instance.replacement] + hide_diffs = ["user_data"] + replacement_trigger = var.force_replace + import_id = "i-1234567890abcdef0" + aliases = ["old-name"] + version = "6.0.0" + plugin_download_url = "https://example.com/plugins" +} +``` + +| Attribute | Type | Description | +| - | - | - | +| `parent` | reference | Parent resource for component hierarchy. | +| `additional_secret_outputs` | list(string) | Output properties to encrypt in state. | +| `retain_on_delete` | bool | Keep the cloud resource when removed from the program. | +| `deleted_with` | reference | Cascade deletion when the referenced resource is deleted. | +| `replace_with` | list | Resources whose replacement triggers replacement of this one. | +| `hide_diffs` | list(string) | Property paths whose diffs should not be displayed. | +| `replace_on_changes` | list(string) | Property paths that force replacement when changed. | +| `replacement_trigger` | expression | Expression whose change triggers replacement. | +| `import_id` | string | Cloud resource ID to import. | +| `aliases` | list | Alternative names for this resource (used during renames). | +| `version` | string | Provider plugin version. | +| `plugin_download_url` | string | URL to download the provider plugin from. | + +Provider resources (with type `pulumi_providers_`) additionally accept an `env_var_mappings` attribute, which remaps environment variables for the provider. + +### Data sources + +`data` blocks read information from providers via invocations. They use the same type-naming convention as resources, and results are referenced as `data...`. + +```hcl +data "aws_ami" "ubuntu" { + most_recent = true + owners = ["099720109477"] + + filter { + name = "name" + values = ["ubuntu/images/hvm-ssd/ubuntu-*-amd64-server-*"] + } +} + +output "ami_id" { + value = data.aws_ami.ubuntu.id +} +``` + +Data sources support the same meta-arguments as resources: `count`, `for_each`, `depends_on`, and `provider`. + +### Providers + +Providers supply the implementation for resources and data sources. + +#### Required providers + +Declare provider requirements inside the `pulumi` block: + +```hcl +pulumi { + required_providers { + aws = { + source = "pulumi/aws" + version = ">= 6.0" + } + random = { + source = "pulumi/random" + version = "4.16.0" + } + } +} +``` + +Provider sources must use the `pulumi/` namespace, not `hashicorp/`. + +#### Provider configuration + +Configure providers with `provider` blocks: + +```hcl +provider "aws" { + region = "us-west-2" +} +``` + +#### Multiple provider configurations + +Use `alias` to create multiple configurations of the same provider: + +```hcl +provider "aws" { + region = "us-west-2" +} + +provider "aws" { + alias = "east" + region = "us-east-1" +} + +resource "aws_instance" "web" { + provider = aws.east + # ... +} +``` + +#### Provider resources + +Providers can also be declared as `resource` blocks for use with component resources: + +```hcl +resource "pulumi_providers_aws" "explicit" { + region = "us-west-2" +} + +resource "aws_instance" "web" { + providers = [pulumi_providers_aws.explicit] + # ... +} +``` + +The `pulumi_providers_` resource type creates an explicit provider instance. Pass it to component resources via the `providers` meta-argument. + +### Outputs + +`output` blocks export values from the stack via [`pulumi stack output`](/docs/iac/cli/commands/pulumi_stack_output/). + +```hcl +output "instance_ip" { + value = aws_instance.web.public_ip + description = "Public IP of the web server" +} + +output "db_password" { + value = random_password.db.result + sensitive = true +} + +output "vpc_id" { + value = aws_vpc.main.id + depends_on = [aws_internet_gateway.gw] + + precondition { + condition = aws_vpc.main.id != "" + error_message = "VPC must have an ID." + } +} +``` + +| Attribute | Type | Required | Description | +| - | - | - | - | +| `value` | expression | Yes | The value to export. | +| `description` | string | No | Human-readable description. | +| `sensitive` | bool | No | When `true`, the output becomes a Pulumi secret. | +| `depends_on` | list | No | Explicit dependencies. | +| `precondition` | block | No | Validation checks before export. | + +### Locals + +`locals` blocks define reusable intermediate values. Multiple `locals` blocks are allowed in a program; reference locals as `local.`. + +```hcl +locals { + common_tags = { + Environment = "dev" + Project = "my-project" + } + + name_prefix = "myapp-${var.environment}" + + user_data = <<-EOF + #!/bin/bash + echo "Hello, World!" > index.html + nohup python3 -m http.server 80 & + EOF +} + +resource "aws_instance" "web" { + tags = local.common_tags + user_data = local.user_data +} +``` + +### Modules + +`module` blocks invoke reusable configurations as Pulumi component resources. Module outputs are referenced as `module..`. + +```hcl +module "vpc" { + source = "./modules/vpc" + cidr_block = "10.0.0.0/16" +} + +output "vpc_id" { + value = module.vpc.vpc_id +} +``` + +#### Module sources + +| Source type | Example | +| - | - | +| Local path | `./modules/vpc` | +| Git | `git::https://github.com/org/repo.git?ref=v1.0.0` | +| Git with subdirectory | `git::https://github.com/org/repo.git//modules/vpc?ref=v1.0.0` | +| GitHub shorthand | `github.com/org/repo` | +| Bitbucket shorthand | `bitbucket.org/org/repo` | +| Terraform Registry | `terraform-aws-modules/vpc/aws` | +| HTTP archive | `https://example.com/module.zip` | + +Remote modules are cached in `~/.pulumi/modules/`. + +#### Module meta-arguments + +| Argument | Type | Description | +| - | - | - | +| `source` | string | Module source (required). | +| `version` | string | Version constraint (for registry modules). | +| `count` | number | Create multiple module instances. | +| `for_each` | map or set | Create keyed module instances. | +| `depends_on` | list | Explicit dependencies. | +| `providers` | map | Provider configuration mappings for the module. | + +### Call blocks + +`call` blocks invoke methods on existing resources. This is a Pulumi-specific extension with no Terraform equivalent. + +```hcl +resource "aws_instance" "web" { + ami = "ami-12345678" + instance_type = "t3.micro" +} + +call "web" "get_password_data" { +} + +output "password_data" { + value = call.web.get_password_data.password_data +} +``` + +The first label is the logical name of a declared resource. The second label is the method name. The body contains arguments to the method. Results are referenced as `call...`. + +### Moved and import blocks + +#### Moved blocks + +`moved` blocks rename resources without recreating them. They map to Pulumi's `aliases` resource option. + +```hcl +moved { + from = aws_instance.old_name + to = aws_instance.new_name +} +``` + +| Attribute | Type | Required | Description | +| - | - | - | - | +| `from` | reference | Yes | Original resource address. | +| `to` | reference | Yes | New resource address. | + +#### Import blocks + +`import` blocks import existing cloud resources into Pulumi state. + +```hcl +import { + to = aws_instance.web + id = "i-1234567890abcdef0" + provider = aws.east +} +``` + +| Attribute | Type | Required | Description | +| - | - | - | - | +| `to` | reference | Yes | Target resource address. | +| `id` | string | Yes | Cloud resource ID to import. | +| `provider` | reference | No | Provider configuration to use. | + +### Expressions + +Pulumi HCL supports the full HCL expression language. + +#### Literals + +```hcl +"hello" # string +42 # number +3.14 # number +true # bool +null # null +["a", "b", "c"] # list +{key = "value"} # map +``` + +#### String interpolation + +```hcl +"Hello, ${var.name}!" +"prefix-${local.env}-suffix" +``` + +#### Heredocs + +```hcl +<<-EOF + multi-line + string content +EOF +``` + +#### References + +| Reference | Description | +| - | - | +| `var.` | Input variable. | +| `local.` | Local value. | +| `.` | Resource attribute. | +| `.[]` | Counted resource instance. | +| `.[""]` | For-each resource instance. | +| `data..` | Data source attribute. | +| `module.` | Module output. | +| `call..` | Call block result. | +| `self` | Current resource (in provisioners). | +| `count.index` | Current count iteration index. | +| `each.key` | Current `for_each` key. | +| `each.value` | Current `for_each` value. | +| `path.module` | Path to the current module. | +| `path.root` | Path to the root module. | +| `path.cwd` | Current working directory. | +| `pulumi.stack` | Current stack name. | +| `pulumi.project` | Current project name. | +| `pulumi.organization` | Current organization name. | + +#### Operators + +| Category | Operators | +| - | - | +| Arithmetic | `+`, `-`, `*`, `/`, `%` | +| Comparison | `==`, `!=`, `<`, `<=`, `>`, `>=` | +| Logical | `&&`, `\|\|`, `!` | + +#### Conditional expression + +```hcl +condition ? true_value : false_value +``` + +#### For expressions + +```hcl +# List comprehension +[for name in var.names : upper(name)] + +# With index +[for i, name in var.names : "${i}-${name}"] + +# Map comprehension +{for k, v in var.tags : k => upper(v)} + +# With filter +[for name in var.names : name if name != ""] +``` + +#### Splat expressions + +```hcl +# Equivalent to [for r in aws_instance.web : r.id] +aws_instance.web[*].id +``` + +#### Property access + +```hcl +resource.name.property +resource.name["key"] +resource.name[0] +``` + +#### `try` and `can` + +```hcl +try(var.optional.nested.value, "default") +can(var.optional.nested.value) # returns true or false +``` + +### Built-in functions + +Pulumi HCL supports nearly all Terraform built-in functions, grouped by category below. + +| Category | Functions | +| - | - | +| Numeric | `abs`, `ceil`, `floor`, `log`, `max`, `min`, `pow`, `signum`, `parseint` | +| String | `chomp`, `endswith`, `format`, `formatlist`, `indent`, `join`, `lower`, `regex`, `regexall`, `replace`, `split`, `startswith`, `strcontains`, `strrev`, `substr`, `title`, `trim`, `trimprefix`, `trimsuffix`, `trimspace`, `upper` | +| Collection | `alltrue`, `anytrue`, `chunklist`, `coalesce`, `coalescelist`, `compact`, `concat`, `contains`, `distinct`, `element`, `entries`, `flatten`, `index`, `keys`, `length`, `list`, `lookup`, `map`, `matchkeys`, `merge`, `one`, `range`, `reverse`, `setintersection`, `setproduct`, `setsubtract`, `setunion`, `slice`, `sort`, `sum`, `transpose`, `values`, `zipmap` | +| Encoding | `base64decode`, `base64encode`, `base64gzip`, `csvdecode`, `jsondecode`, `jsonencode`, `textdecodebase64`, `textencodebase64`, `urlencode`, `yamldecode`, `yamlencode` | +| Filesystem | `abspath`, `basename`, `dirname`, `file`, `filebase64`, `fileexists`, `fileset`, `pathexpand`, `templatefile` | +| Date and time | `formatdate`, `timeadd`, `timecmp`, `timestamp` | +| Hash and crypto | `base64sha256`, `base64sha512`, `bcrypt`, `filebase64sha256`, `filebase64sha512`, `filemd5`, `filesha1`, `filesha256`, `filesha512`, `md5`, `rsadecrypt`, `sha1`, `sha256`, `sha512`, `uuid`, `uuidv5` | +| IP network | `cidrhost`, `cidrnetmask`, `cidrsubnet`, `cidrsubnets` | +| Type conversion | `can`, `issensitive`, `nonsensitive`, `sensitive`, `tobool`, `tolist`, `tomap`, `tonumber`, `toset`, `tostring`, `try`, `type` | + +#### Pulumi-specific functions + +| Function | Description | +| - | - | +| `fileAsset(path)` | Create a Pulumi `FileAsset` from a local file path. | +| `stringAsset(text)` | Create a Pulumi `StringAsset` from a string value. | +| `remoteAsset(uri)` | Create a Pulumi `RemoteAsset` from a URL. | +| `fileArchive(path)` | Create a Pulumi `FileArchive` from a local path. | +| `remoteArchive(uri)` | Create a Pulumi `RemoteArchive` from a URL. | +| `assetArchive(map)` | Create a Pulumi `AssetArchive` from a map of assets or archives. | +| `pulumiResourceName(resource)` | Get the logical name from a resource's URN. | +| `pulumiResourceType(resource)` | Get the type token from a resource's URN. | + +#### Functions not supported + +These Terraform functions have no equivalent in Pulumi HCL: + +| Function | Reason | +| - | - | +| `templatestring` | Inline template-string rendering is not supported. | +| `plantimestamp` | No Pulumi equivalent for plan-time timestamps. | +| `ephemeralasnull` | Pulumi has no ephemeral value concept. | + +The `provider::terraform::*` provider functions and `terraform.applying` are Terraform-internal and have no equivalent. + +### Stack references + +Access outputs from other Pulumi stacks using the `pulumi_stackreference` resource: + +```hcl +resource "pulumi_stackreference" "network" { + name = "myorg/networking/prod" +} + +output "vpc_id" { + value = pulumi_stackreference.network.outputs["vpc_id"] +} +``` + +### Pulumi block + +The `pulumi` block configures Pulumi-specific settings. + +#### Version constraints + +```hcl +pulumi { + required_version_range = ">= 3.0.0" +} +``` + +#### Multi-language components + +The `component` and `package` blocks declare an HCL module as a reusable Pulumi component consumable from any Pulumi language. See the [Pulumi HCL component reference](/docs/iac/languages-sdks/hcl/hcl-component-reference/) for details. + +```hcl +pulumi { + component { + name = "VpcNetwork" + module = "index" + } + package { + name = "my-networking" + version = "1.0.0" + } +} +``` + +### Terraform compatibility + +Pulumi HCL is broadly compatible with Terraform-like HCL syntax. This section covers the differences. + +#### Required changes + +The top-level `terraform` block is not supported. Move provider requirements into the `pulumi` block, and use the `pulumi/` namespace for provider sources instead of `hashicorp/`: + +```hcl +pulumi { + required_providers { + aws = { + source = "pulumi/aws" # not "hashicorp/aws" + version = ">= 6.0" + } + } +} +``` + +Terraform's `backend`, `cloud`, and `required_version` are not modeled — Pulumi manages state independently and uses `pulumi { required_version_range = "..." }` for its own version constraints. + +#### Behavioral differences + +**Resource replacement order.** Pulumi creates the new resource before deleting the old one (the opposite of Terraform). Set `create_before_destroy = false` in the `lifecycle` block to opt into delete-first behavior. + +**Sensitive values.** Variables and outputs marked `sensitive = true` become [Pulumi secrets](/docs/iac/concepts/secrets/), encrypted at rest in state. + +**Property names.** HCL uses `snake_case`. The plugin automatically converts to Pulumi's `camelCase` for the engine. Map keys are not translated. + +#### Feature mappings + +| Terraform feature | Pulumi equivalent | Notes | +| - | - | - | +| `prevent_destroy` | `protect` | Same behavior. | +| `ignore_changes` | `ignoreChanges` | Same behavior. | +| `create_before_destroy` | `deleteBeforeReplace` | Inverted logic. | +| `moved` blocks | `aliases` | Renames without recreation. | +| `import` blocks | Import resource option | Imports existing resources. | +| `timeouts` | `customTimeouts` | Same duration format. | +| Modules | Component resources | All source types supported. | +| Provisioners | Command provider | `local-exec`, `remote-exec`, `file`. | + +#### Unsupported features + +- **`replace_triggered_by`** — Terraform cascades replacement when *other* resources change. Use Pulumi HCL's `replace_with` resource option for the same effect; the Terraform-like `replace_triggered_by` attribute on a `lifecycle` block produces an error. +- **`dynamic` blocks** — Dynamic block generation is not implemented. +- **WinRM connections** — `connection` blocks support `type = "ssh"` only.