SuperAPI AI Directory

pulumi

Coding & development

View repository

Updated 10-15 21:49

About this skill

Pulumi

Pulumi is an Infrastructure as Code (IaC) platform that allows engineering teams to define, deploy, and manage cloud infrastructure using general-purpose languages like TypeScript, Python, and Go.

When to Use

  • Modern Programming Languages for Infrastructure as Code (IaC): TypeScript, Python, Go, and C# instead of domain-specific languages (DSL).
  • Modular Component Resources: Encapsulating complex cloud topologies into reusable, typed classes and libraries.
  • Real-Time Integration & Unit Testing: Writing standard unit tests for infrastructure using Vitest, Jest, or PyTest.
  • Kubernetes & Multi-Cloud Native: Provisioning AWS, Azure, GCP, and Kubernetes workloads in a single unified language.

Quick Start

import * as pulum from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const bucket = new aws.s3.Bucket("my-bucket", { acl: "private", });

export const bucketName = bucket.id;


## Core Concepts

### Modular Infrastructure Component with TypeScript

Creating an encapsulated, reusable microservice infrastructure component:

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

interface MicroserviceArgs {
  vpcId: pulumi.Input<string>;
  subnetIds: pulumi.Input<string[]>;
  imageTag: string;
}

export class ContainerMicroservice extends pulumi.ComponentResource {
  public readonly url: pulumi.Output<string>;

  constructor(
    name: string,
    args: MicroserviceArgs,
    opts?: pulumi.ComponentResourceOptions,
  ) {
    super("custom:cloud:ContainerMicroservice", name, {}, opts);

    // ECR Repository
    const repo = new aws.ecr.Repository(
      `${name}-repo`,
      {
        imageScanningConfiguration: { scanOnPush: true },
      },
      { parent: this },
    );

    // Application Load Balancer
    const alb = new aws.lb.LoadBalancer(
      `${name}-alb`,
      {
        internal: false,
        subnets: args.subnetIds,
      },
      { parent: this },
    );

    this.url = alb.dnsName;
    this.registerOutputs({ url: this.url });
  }
}

// In index.ts:
const service = new ContainerMicroservice("billing", {
  vpcId: "vpc-0123456789",
  subnetIds: ["subnet-a", "subnet-b"],
  imageTag: "v2.1.0",
});
export const endpoint = service.url;

Secret Management & Stack Configuration

Encrypting sensitive credentials automatically:

# Configure encrypted secret in stack configuration
pulumi config set --secret dbPassword "SuperSecurePassword2026!"

# Read secret in Pulumi program
const config = new pulumi.Config();
const dbPassword = config.requireSecret("dbPassword"); // Returned as Output<string> (masked)

Pulumi CLI Operations

Previewing and applying infrastructure changes:

# Preview proposed changes with detailed diff
pulumi preview

# Deploy infrastructure to cloud stack
pulumi up --yes

# Destroy stack resources cleanly
pulumi destroy

Common Patterns

Typed ComponentResource for Reusable Infrastructure Modules

Problem: Copy-pasting raw cloud resource definitions across staging and production stacks.

Solution: Encapsulate resources into reusable Pulumi ComponentResources:

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

interface MicroserviceArgs {
  vpcId: pulumi.Input<string>;
  imageUri: pulumi.Input<string>;
  port: number;
}

export class Microservice extends pulumi.ComponentResource {
  public readonly url: pulumi.Output<string>;

  constructor(
    name: string,
    args: MicroserviceArgs,
    opts?: pulumi.ComponentResourceOptions,
  ) {
    super("custom:app:Microservice", name, {}, opts);

    const sg = new aws.ec2.SecurityGroup(
      `${name}-sg`,
      {
        vpcId: args.vpcId,
        ingress: [
          {
            protocol: "tcp",
            fromPort: args.port,
            toPort: args.port,
            cidrBlocks: ["0.0.0.0/0"],
          },
        ],
      },
      { parent: this },
    );

    // Output URL
    this.url = pulumi.interpolate`http://service.${name}.internal:${args.port}`;
    this.registerOutputs({ url: this.url });
  }
}

Best Practices

Do:

  • Encapsulate related infrastructure into custom ComponentResource classes for reusability.
  • Treat secret values strictly as pulumi.Output<string> to ensure automated masking in console logs.
  • Run unit tests against infrastructure mocks before executing deployments in CI/CD pipelines.
  • Configure Pulumi Cloud or an S3/GCS backend for reliable stack state locking and auditing.

Don't:

  • Call .get() on Pulumi Outputs during resource declaration; use .apply() to chain asynchronous outputs.
  • Commit plaintext secrets to Pulumi.<stack>.yaml files; use --secret flag.
  • Mix side-effects (e.g. database schema migrations) directly inside Pulumi IaC definitions.

Troubleshooting

Error Cause Solution
Diagnostics: Resource '...' already exists Attempting to create resource that exists outside of Pulumi state. Import resource into state: pulumi import <type> <name> <id>.
Stack locked by another operation Previous update interrupted or crashed before releasing state lock. Cancel lock after verifying no operation is running: pulumi cancel.
Error: Output<T> cannot be passed to string Accessing .apply() outputs as plain synchronous strings. Wrap dependent values with pulumi.interpolate or use .apply().

References