Variables and Values
A variable gives a name to a value so you can reuse it and refer to it later.
Every configuration language you already use has a version of this: a locals
block in HCL, a variables: section in Pulumi YAML. In a general-purpose
language, naming a value is the most basic thing you do, and it works the same
way whether the value is a string, a number, or the result of creating a
resource.
Where you have seen this before
In Pulumi YAML, variables names a value once so you can reference it
elsewhere in the same file:
variables:
bucketName: my-app-data
resources:
bucket:
type: aws:s3:Bucket
properties:
bucket: ${bucketName}
In Terraform HCL, a locals block does the same thing, and ${...}
interpolation substitutes it into a string:
locals {
bucket_name = "my-app-data"
}
resource "aws_s3_bucket" "bucket" {
bucket = "${local.bucket_name}"
}
The syntax
In a general-purpose language, you declare a variable and assign it a value in one statement. Most Pulumi languages infer the type from the value, so you rarely write the type out yourself.
const bucketName = "my-app-data";
const replicaCount = 3;
bucket_name = "my-app-data"
replica_count = 3
bucketName := "my-app-data"
replicaCount := 3
var bucketName = "my-app-data";
var replicaCount = 3;
var bucketName = "my-app-data";
var replicaCount = 3;
variables:
bucketName: my-app-data
replicaCount: 3
locals {
bucket_name = "my-app-data"
replica_count = 3
}
Building a string out of a variable works the way you’d expect from ${...}
interpolation, just with each language’s own syntax: template literals in
TypeScript, f-strings in Python, fmt.Sprintf in Go, $"..." in C#, and
String.format in Java.
const label = `${bucketName}-${replicaCount}`;
label = f"{bucket_name}-{replica_count}"
label := fmt.Sprintf("%s-%d", bucketName, replicaCount)
var label = $"{bucketName}-{replicaCount}";
var label = String.format("%s-%d", bucketName, replicaCount);
variables:
label: ${bucketName}-${replicaCount}
locals {
label = "${local.bucket_name}-${local.replica_count}"
}
In a Pulumi program
Stack configuration is the language equivalent of a Pulumi.<stack>.yaml
value you’d otherwise reference directly. You read it into a variable with
pulumi.Config and use it the same way you’d use any other variable. Set the
value first, since config.require fails if it isn’t set:
pulumi config set environment production
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const config = new pulumi.Config();
const environment = config.require("environment");
const bucket = new aws.s3.Bucket(`data-${environment}`);
import pulumi
import pulumi_aws as aws
config = pulumi.Config()
environment = config.require("environment")
bucket = aws.s3.Bucket(f"data-{environment}")
package main
import (
"fmt"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
cfg := config.New(ctx, "")
environment := cfg.Require("environment")
_, err := s3.NewBucket(ctx, fmt.Sprintf("data-%s", environment), nil)
return err
})
}
using Pulumi;
using Pulumi.Aws.S3;
return await Deployment.RunAsync(() =>
{
var config = new Config();
var environment = config.Require("environment");
var bucket = new Bucket($"data-{environment}");
});
import com.pulumi.Pulumi;
import com.pulumi.Config;
import com.pulumi.aws.s3.Bucket;
public class App {
public static void main(String[] args) {
Pulumi.run(ctx -> {
var config = ctx.config();
var environment = config.require("environment");
var bucket = new Bucket("data-" + environment);
});
}
}
config:
environment:
type: string
resources:
bucket:
type: aws:s3:Bucket
properties:
bucket: data-${environment}
variable "environment" {
type = string
}
resource "aws_s3_bucket" "bucket" {
bucket = "data-${var.environment}"
}
What to watch out for
Not every value on a resource is a plain string or number you can interpolate
directly. Many resource properties are outputs: values Pulumi doesn’t know
until the resource is actually created, such as a generated ARN or a load
balancer’s DNS name. Ordinary string interpolation doesn’t work on an output,
because the value isn’t available when your program runs. See
inputs and outputs for how that model
works, and each language’s interpolation helper, such as pulumi.interpolate
in TypeScript or pulumi.Output.format() in Python, for building strings out
of them.
Next steps
Continue to conditionals
to see how if statements replace count-based conditionals.
Learn more
- Configuration for the full set of options for reading and validating stack configuration.