Resources & the program
Declaring infra in code.
A Pulumi program builds infrastructure by constructing resource objects. Each resource takes a name (unique within the program), an arguments object, and optional options; constructing it registers it with the engine as something that should exist. Dependencies are inferred when you pass one resource’s output into another’s input — the same implicit-graph idea as Terraform, expressed as normal variable references.
import * as aws from "@pulumi/aws";const logs = new aws.s3.BucketV2("logs", {bucket: "acme-logs-prod",});// passing logs.id into another resource creates a dependency edgenew aws.s3.BucketVersioningV2("logs-versioning", {bucket: logs.id,versioningConfiguration: { status: "Enabled" },});
Now use the language
This is where Pulumi earns its keep: to make ten buckets, you write a loop; to make a resource conditional, an if; to factor out a pattern, a function. There is no special DSL construct for iteration or conditionals because you already have the language’s. The result is that repetitive or parameterized infrastructure reads like the rest of your codebase.
const envs = ["dev", "staging", "prod"];const buckets = envs.map(env =>new aws.s3.BucketV2(`data-${env}`, { bucket: `acme-data-${env}` }));// a helper function that encapsulates a pattern:function privateBucket(name: string) {const b = new aws.s3.BucketV2(name, {});new aws.s3.BucketPublicAccessBlock(`${name}-block`, {bucket: b.id, blockPublicAcls: true, blockPublicPolicy: true,});return b;}