Pulumi — Basics
Pulumi — Basics
Section titled “Pulumi — Basics”What it is
Section titled “What it is”IaC using real programming languages (TS/JS, Python, Go, .NET, Java, YAML). Same providers as Terraform under the hood (Pulumi can reuse TF providers via bridge).
Why pick Pulumi over Terraform
Section titled “Why pick Pulumi over Terraform”- Real loops, conditionals, helper functions, classes.
- IDE features (types, completions, refactoring).
- Test infrastructure with regular unit/integration tests (mocha, pytest, go test).
- Easier multi-cloud abstractions.
- Component model — package and reuse infra abstractions.
Trade-offs:
- More opinionated, smaller community than TF.
- Code can become as hairy as any program (TF’s restriction protects against that).
- State is stored in Pulumi Cloud (free for individuals) or self-hosted backend (S3/GCS/Azure).
Core concepts
Section titled “Core concepts”- Project — directory with
Pulumi.yaml+ code. - Stack — independent instance (env):
dev,staging,prod. Each has own state. - Resource — provider-managed thing (
new aws.s3.Bucket(...)). - Provider — plugin (aws, gcp, kubernetes, github, etc.).
- Output — async-typed value flowing between resources.
- Component — composite resource exposing multiple primitives.
- Config — per-stack settings (
pulumi config set foo bar). - Backend — state storage (Pulumi Cloud default, or self-hosted).
CLI lifecycle
Section titled “CLI lifecycle”pulumi new aws-typescript # scaffoldpulumi stack init dev # create stackpulumi config set aws:region eu-west-1pulumi up # plan + apply (interactive)pulumi preview # plan onlypulumi destroypulumi stack select prodpulumi state # state opspulumi import aws:s3/bucket:Bucket logs my-bucketOutputs and Inputs
Section titled “Outputs and Inputs”Outputs are promises — you can’t just use them directly as strings. Use apply() or interpolation:
const bucket = new aws.s3.Bucket("data");const arnLog = bucket.arn.apply(a => `arn=${a}`);const url = pulumi.interpolate`https://${bucket.bucketDomainName}/path`;Sample (TypeScript)
Section titled “Sample (TypeScript)”import * as aws from "@pulumi/aws";import * as pulumi from "@pulumi/pulumi";
const cfg = new pulumi.Config();const env = pulumi.getStack();
const bucket = new aws.s3.Bucket("data", { versioning: { enabled: true }, serverSideEncryptionConfiguration: { rule: { applyServerSideEncryptionByDefault: { sseAlgorithm: "AES256" } }, }, tags: { Env: env, Owner: "platform" },});
export const bucketName = bucket.id;Sample (Python)
Section titled “Sample (Python)”import pulumiimport pulumi_aws as aws
bucket = aws.s3.Bucket("data", versioning={"enabled": True}, tags={"env": pulumi.get_stack()},)pulumi.export("bucket_name", bucket.id)Components
Section titled “Components”Reusable abstractions:
class WebApp extends pulumi.ComponentResource { public url: pulumi.Output<string>; constructor(name: string, args: WebAppArgs, opts?) { super("custom:WebApp", name, args, opts); const lb = new aws.lb.LoadBalancer(...); const tg = new aws.lb.TargetGroup(...); // wire up this.url = lb.dnsName; this.registerOutputs({ url: this.url }); }}Testing
Section titled “Testing”// unit (no cloud calls)pulumi.runtime.setMocks({ newResource(args) { return { id: args.name + "_id", state: args.inputs }; }, call(args) { return args.inputs; },});
import * as infra from "../index";
test("bucket has versioning", async () => { const v = await new Promise(res => (infra.bucket.versioning as any).apply(res)); expect(v.enabled).toBe(true);});Also: integration tests via pulumi up against a temp stack.
State storage backends
Section titled “State storage backends”- Pulumi Cloud (default) — managed, has UI, free for individuals.
- Self-hosted:
pulumi login s3://bucket,gs://...,azblob://..., file://.
When to use Pulumi vs Terraform
Section titled “When to use Pulumi vs Terraform”Pulumi:
- Engineering team, comfortable with TS/Python/Go.
- Heavy logic in infra (loops, complex transformations).
- Want infra unit tests without TF’s mock limitations.
- Polyglot stack already (Node services, Go services).
Terraform:
- Mixed teams (ops + dev).
- Want HCL’s enforced simplicity.
- Battle-tested community modules already cover your needs.