Pulumi ESC: Integrate with Terraform
Overview
Pulumi ESC integrates with Terraform and OpenTofu to help developers provision Terraform-managed infrastructure using centrally-managed, composable configuration and temporary credentials.
Prerequisites
To complete the steps in this tutorial, you will need to install the following prerequisites:
- the Pulumi ESC CLI
- the Terraform CLI
terraform
commands with the equivalent tofu
commands. In most cases, this is as simple as replacing terraform
with tofu
.Create and initialize a Terraform workspace
Create a directory to hold your infrastructure code, then copy and paste the following into a file named main.tf
:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
variable "instance_type" {
type = string
}
variable "region" {
type = string
}
provider "aws" {
region = var.region
}
data "aws_ami" "amazon_linux_2" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm*"]
}
}
resource "aws_instance" "app_server" {
ami = data.aws_ami.amazon_linux_2.id
instance_type = var.instance_type
tags = {
Name = "ESCExampleAppServer"
}
}
This sample code will create an EC2 instance running Amazon Linux 2. The instance’s region and instance type are supplied by the user via input variables.
Once you have created your main.tf
file, run terraform init
to install the necessary Terraform providers:
$ terraform init
Create an ESC environment with Terraform variables
ESC integrates with Terraform by exporting environment variables from an opened environment. These environment variables typically come in two flavors: those used by Terraform providers and those used to provide values for Terraform input variables. The former are specific to each Terraform provider, while the latter are of the form TF_VAR_<variable name>
.
For this guide, we’ll create an environment that supplies both temporary credentials for the Terraform AWS provider as well as values for our confguration’s region
and instance_type
input variables:
values:
# Fetch temporary AWS credentials via OIDC
aws:
login:
fn::open::aws-login:
oidc:
duration: 1h
roleArn: <your-oidc-iam-role-arn>
sessionName: pulumi-environments-session
environmentVariables:
# Export AWS Credentials
AWS_ACCESS_KEY_ID: ${aws.login.accessKeyId}
AWS_SECRET_ACCESS_KEY: ${aws.login.secretAccessKey}
AWS_SESSION_TOKEN: ${aws.login.sessionToken}
# Export Terraform variables
TF_VAR_region: us-west-2
TF_VAR_instance_type: t3.small
Run Terraform
Once you’ve created the example environment, you can now use the Terraform CLI with esc run
to invoke Terraform with credentials and configuration:
$ esc run <your-project-name>/<your-env-name> -i -- terraform apply
This will open your ESC environment, export its environment variables, and then invoke terraform apply
with those environment variables. The -i
instructs esc
to run in interactive mode, which is necessary for programs like the Terraform CLI that expect user input.
Run Terraform with -var-file
While simple Terraform input variables work well with environment variables, it can be difficult to set variables with complex types (e.g. arrays, objects). If your Terraform input variables have complex types, you can use -var-file
to supply their values.
values:
# Fetch temporary AWS credentials via OIDC
aws:
login:
fn::open::aws-login:
oidc:
duration: 1h
roleArn: <your-oidc-iam-role-arn>
sessionName: pulumi-environments-session
files:
TFVARS:
fn::toJSON:
region: us-west-2
instance_type: t3.small
environmentVariables:
# Export AWS Credentials
AWS_ACCESS_KEY_ID: ${aws.login.accessKeyId}
AWS_SECRET_ACCESS_KEY: ${aws.login.secretAccessKey}
AWS_SESSION_TOKEN: ${aws.login.sessionToken}
With this environment, the esc
CLI will write the value of the TFVARS
property to a temporary file, then export the path to that temporary file in the TFVARS
environment variable. You can then pass the path to this file to the Terraform CLI. This is slightly more involved because the Terraform CLI requires that the contents of the vars file is either valid HCL or JSON, and JSON files must have a .json
extension:
$ esc run <your-project-name>/<your-env-name> -i -- sh -c 'mv $TFVARS $TFVARS.json && terraform apply -var-file=$TFVARS.json'
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.