Skip to content

Pulumi

Language Overview

Pulumi is an Infrastructure as Code (IaC) platform that enables defining, deploying, and managing cloud infrastructure using familiar programming languages like TypeScript, Python, Go, C#, and Java.

Key Characteristics

  • Languages: TypeScript (preferred), Python, Go, C#, Java, YAML
  • Paradigm: Imperative infrastructure as code with declarative state management
  • Type System: Full type safety in supported languages
  • State Management: Pulumi Cloud, S3, Azure Blob, GCS, or local backends
  • Provider Ecosystem: 100+ providers including AWS, Azure, GCP, Kubernetes
  • Version Support: Targets Pulumi CLI 3.x

Primary Use Cases

  • Multi-cloud infrastructure provisioning (AWS, Azure, GCP)
  • Kubernetes cluster and resource management
  • Serverless application infrastructure
  • Network and security infrastructure
  • Database and storage provisioning
  • CI/CD pipeline infrastructure

Quick Reference

Category Convention Example Notes
Naming
Projects kebab-case my-web-app, vpc-network Project directory names
Stacks kebab-case dev, staging, prod Environment names
Resources camelCase mainVpc, webServer Resource variable names
Components PascalCase VpcNetwork, WebCluster Component class names
Config Keys camelCase instanceType, dbPassword Configuration keys
Files (TypeScript)
Entry Point index.ts index.ts Main Pulumi program
Components component-name.ts vpc-network.ts Component definitions
Config config.ts config.ts Configuration helpers
Files (Python)
Entry Point __main__.py __main__.py Main Pulumi program
Components component_name.py vpc_network.py Component definitions
Files (Go)
Entry Point main.go main.go Main Pulumi program
Components component_name.go vpc_network.go Component definitions
Project Structure
Config Pulumi.yaml Pulumi.yaml Project configuration
Stack Config Pulumi.<stack>.yaml Pulumi.dev.yaml Stack-specific config
Best Practices
TypeScript Preferred language Type safety, IDE support Best developer experience
Components Use ComponentResource Reusable patterns Encapsulate resources
Secrets Use Pulumi secrets pulumi config set --secret Encrypted in state
Outputs Export important values export const vpcId = vpc.id Cross-stack references

Project Structure

TypeScript Project

my-pulumi-project/
├── index.ts                    # Main entry point
├── components/                 # Reusable components
│   ├── vpc-network.ts
│   ├── database-cluster.ts
│   └── web-server.ts
├── config/                     # Configuration helpers
│   └── index.ts
├── types/                      # Type definitions
│   └── index.ts
├── Pulumi.yaml                 # Project configuration
├── Pulumi.dev.yaml             # Dev stack configuration
├── Pulumi.staging.yaml         # Staging stack configuration
├── Pulumi.prod.yaml            # Production stack configuration
├── package.json
├── tsconfig.json
└── test/
    └── index.test.ts           # Unit tests

Python Project

my-pulumi-project/
├── __main__.py                 # Main entry point
├── components/                 # Reusable components
│   ├── __init__.py
│   ├── vpc_network.py
│   ├── database_cluster.py
│   └── web_server.py
├── config/                     # Configuration helpers
│   ├── __init__.py
│   └── settings.py
├── Pulumi.yaml                 # Project configuration
├── Pulumi.dev.yaml             # Dev stack configuration
├── Pulumi.prod.yaml            # Production stack configuration
├── requirements.txt            # Python dependencies
├── pyproject.toml              # Project metadata
└── tests/
    └── test_components.py      # Unit tests

Go Project

my-pulumi-project/
├── main.go                     # Main entry point
├── components/                 # Reusable components
│   ├── vpc_network.go
│   ├── database_cluster.go
│   └── web_server.go
├── config/                     # Configuration helpers
│   └── config.go
├── Pulumi.yaml                 # Project configuration
├── Pulumi.dev.yaml             # Dev stack configuration
├── Pulumi.prod.yaml            # Production stack configuration
├── go.mod                      # Go module
├── go.sum                      # Go dependencies
└── tests/
    └── main_test.go            # Unit tests

Basic Infrastructure

TypeScript: Basic AWS VPC

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

// Get configuration
const config = new pulumi.Config();
const environment = pulumi.getStack();
const projectName = pulumi.getProject();

// Common tags for all resources
const commonTags = {
  Environment: environment,
  Project: projectName,
  ManagedBy: 'pulumi',
};

// Create VPC
const vpc = new aws.ec2.Vpc('main-vpc', {
  cidrBlock: config.get('vpcCidr') || '10.0.0.0/16',
  enableDnsHostnames: true,
  enableDnsSupport: true,
  tags: {
    ...commonTags,
    Name: `${projectName}-${environment}-vpc`,
  },
});

// Create Internet Gateway
const igw = new aws.ec2.InternetGateway('main-igw', {
  vpcId: vpc.id,
  tags: {
    ...commonTags,
    Name: `${projectName}-${environment}-igw`,
  },
});

// Create public subnets across availability zones
const publicSubnets: aws.ec2.Subnet[] = [];
const availabilityZones = ['us-east-1a', 'us-east-1b', 'us-east-1c'];

availabilityZones.forEach((az, index) => {
  const subnet = new aws.ec2.Subnet(`public-subnet-${index}`, {
    vpcId: vpc.id,
    cidrBlock: `10.0.${index}.0/24`,
    availabilityZone: az,
    mapPublicIpOnLaunch: true,
    tags: {
      ...commonTags,
      Name: `${projectName}-${environment}-public-${az}`,
      Type: 'public',
    },
  });
  publicSubnets.push(subnet);
});

// Create private subnets
const privateSubnets: aws.ec2.Subnet[] = [];

availabilityZones.forEach((az, index) => {
  const subnet = new aws.ec2.Subnet(`private-subnet-${index}`, {
    vpcId: vpc.id,
    cidrBlock: `10.0.${index + 10}.0/24`,
    availabilityZone: az,
    tags: {
      ...commonTags,
      Name: `${projectName}-${environment}-private-${az}`,
      Type: 'private',
    },
  });
  privateSubnets.push(subnet);
});

// Create public route table
const publicRouteTable = new aws.ec2.RouteTable('public-rt', {
  vpcId: vpc.id,
  routes: [
    {
      cidrBlock: '0.0.0.0/0',
      gatewayId: igw.id,
    },
  ],
  tags: {
    ...commonTags,
    Name: `${projectName}-${environment}-public-rt`,
  },
});

// Associate public subnets with public route table
publicSubnets.forEach((subnet, index) => {
  new aws.ec2.RouteTableAssociation(`public-rta-${index}`, {
    subnetId: subnet.id,
    routeTableId: publicRouteTable.id,
  });
});

// Export outputs
export const vpcId = vpc.id;
export const vpcCidr = vpc.cidrBlock;
export const publicSubnetIds = publicSubnets.map((s) => s.id);
export const privateSubnetIds = privateSubnets.map((s) => s.id);

Python: Basic AWS VPC

import pulumi
import pulumi_aws as aws

# Get configuration
config = pulumi.Config()
environment = pulumi.get_stack()
project_name = pulumi.get_project()

# Common tags for all resources
common_tags = {
    "Environment": environment,
    "Project": project_name,
    "ManagedBy": "pulumi",
}

# Create VPC
vpc = aws.ec2.Vpc(
    "main-vpc",
    cidr_block=config.get("vpc_cidr") or "10.0.0.0/16",
    enable_dns_hostnames=True,
    enable_dns_support=True,
    tags={
        **common_tags,
        "Name": f"{project_name}-{environment}-vpc",
    },
)

# Create Internet Gateway
igw = aws.ec2.InternetGateway(
    "main-igw",
    vpc_id=vpc.id,
    tags={
        **common_tags,
        "Name": f"{project_name}-{environment}-igw",
    },
)

# Create public subnets across availability zones
availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]
public_subnets = []

for index, az in enumerate(availability_zones):
    subnet = aws.ec2.Subnet(
        f"public-subnet-{index}",
        vpc_id=vpc.id,
        cidr_block=f"10.0.{index}.0/24",
        availability_zone=az,
        map_public_ip_on_launch=True,
        tags={
            **common_tags,
            "Name": f"{project_name}-{environment}-public-{az}",
            "Type": "public",
        },
    )
    public_subnets.append(subnet)

# Create private subnets
private_subnets = []

for index, az in enumerate(availability_zones):
    subnet = aws.ec2.Subnet(
        f"private-subnet-{index}",
        vpc_id=vpc.id,
        cidr_block=f"10.0.{index + 10}.0/24",
        availability_zone=az,
        tags={
            **common_tags,
            "Name": f"{project_name}-{environment}-private-{az}",
            "Type": "private",
        },
    )
    private_subnets.append(subnet)

# Create public route table
public_route_table = aws.ec2.RouteTable(
    "public-rt",
    vpc_id=vpc.id,
    routes=[
        aws.ec2.RouteTableRouteArgs(
            cidr_block="0.0.0.0/0",
            gateway_id=igw.id,
        )
    ],
    tags={
        **common_tags,
        "Name": f"{project_name}-{environment}-public-rt",
    },
)

# Associate public subnets with public route table
for index, subnet in enumerate(public_subnets):
    aws.ec2.RouteTableAssociation(
        f"public-rta-{index}",
        subnet_id=subnet.id,
        route_table_id=public_route_table.id,
    )

# Export outputs
pulumi.export("vpc_id", vpc.id)
pulumi.export("vpc_cidr", vpc.cidr_block)
pulumi.export("public_subnet_ids", [s.id for s in public_subnets])
pulumi.export("private_subnet_ids", [s.id for s in private_subnets])

Go: Basic AWS VPC

package main

import (
    "fmt"

    "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ec2"
    "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 {
        // Get configuration
        cfg := config.New(ctx, "")
        environment := ctx.Stack()
        projectName := ctx.Project()

        // Common tags for all resources
        commonTags := pulumi.StringMap{
            "Environment": pulumi.String(environment),
            "Project":     pulumi.String(projectName),
            "ManagedBy":   pulumi.String("pulumi"),
        }

        // Get VPC CIDR from config or use default
        vpcCidr := cfg.Get("vpcCidr")
        if vpcCidr == "" {
            vpcCidr = "10.0.0.0/16"
        }

        // Create VPC
        vpc, err := ec2.NewVpc(ctx, "main-vpc", &ec2.VpcArgs{
            CidrBlock:          pulumi.String(vpcCidr),
            EnableDnsHostnames: pulumi.Bool(true),
            EnableDnsSupport:   pulumi.Bool(true),
            Tags: pulumi.StringMap{
                "Environment": commonTags["Environment"],
                "Project":     commonTags["Project"],
                "ManagedBy":   commonTags["ManagedBy"],
                "Name":        pulumi.Sprintf("%s-%s-vpc", projectName, environment),
            },
        })
        if err != nil {
            return err
        }

        // Create Internet Gateway
        igw, err := ec2.NewInternetGateway(ctx, "main-igw", &ec2.InternetGatewayArgs{
            VpcId: vpc.ID(),
            Tags: pulumi.StringMap{
                "Environment": commonTags["Environment"],
                "Project":     commonTags["Project"],
                "ManagedBy":   commonTags["ManagedBy"],
                "Name":        pulumi.Sprintf("%s-%s-igw", projectName, environment),
            },
        })
        if err != nil {
            return err
        }

        // Create public subnets
        availabilityZones := []string{"us-east-1a", "us-east-1b", "us-east-1c"}
        publicSubnetIds := pulumi.StringArray{}

        for i, az := range availabilityZones {
            subnet, err := ec2.NewSubnet(ctx, fmt.Sprintf("public-subnet-%d", i), &ec2.SubnetArgs{
                VpcId:               vpc.ID(),
                CidrBlock:           pulumi.Sprintf("10.0.%d.0/24", i),
                AvailabilityZone:    pulumi.String(az),
                MapPublicIpOnLaunch: pulumi.Bool(true),
                Tags: pulumi.StringMap{
                    "Environment": commonTags["Environment"],
                    "Project":     commonTags["Project"],
                    "ManagedBy":   commonTags["ManagedBy"],
                    "Name":        pulumi.Sprintf("%s-%s-public-%s", projectName, environment, az),
                    "Type":        pulumi.String("public"),
                },
            })
            if err != nil {
                return err
            }
            publicSubnetIds = append(publicSubnetIds, subnet.ID())
        }

        // Create private subnets
        privateSubnetIds := pulumi.StringArray{}

        for i, az := range availabilityZones {
            subnet, err := ec2.NewSubnet(ctx, fmt.Sprintf("private-subnet-%d", i), &ec2.SubnetArgs{
                VpcId:            vpc.ID(),
                CidrBlock:        pulumi.Sprintf("10.0.%d.0/24", i+10),
                AvailabilityZone: pulumi.String(az),
                Tags: pulumi.StringMap{
                    "Environment": commonTags["Environment"],
                    "Project":     commonTags["Project"],
                    "ManagedBy":   commonTags["ManagedBy"],
                    "Name":        pulumi.Sprintf("%s-%s-private-%s", projectName, environment, az),
                    "Type":        pulumi.String("private"),
                },
            })
            if err != nil {
                return err
            }
            privateSubnetIds = append(privateSubnetIds, subnet.ID())
        }

        // Create public route table
        publicRouteTable, err := ec2.NewRouteTable(ctx, "public-rt", &ec2.RouteTableArgs{
            VpcId: vpc.ID(),
            Routes: ec2.RouteTableRouteArray{
                &ec2.RouteTableRouteArgs{
                    CidrBlock: pulumi.String("0.0.0.0/0"),
                    GatewayId: igw.ID(),
                },
            },
            Tags: pulumi.StringMap{
                "Environment": commonTags["Environment"],
                "Project":     commonTags["Project"],
                "ManagedBy":   commonTags["ManagedBy"],
                "Name":        pulumi.Sprintf("%s-%s-public-rt", projectName, environment),
            },
        })
        if err != nil {
            return err
        }

        // Associate public subnets with route table
        for i := range availabilityZones {
            _, err := ec2.NewRouteTableAssociation(ctx, fmt.Sprintf("public-rta-%d", i),
                &ec2.RouteTableAssociationArgs{
                    SubnetId:     publicSubnetIds[i],
                    RouteTableId: publicRouteTable.ID(),
                })
            if err != nil {
                return err
            }
        }

        // Export outputs
        ctx.Export("vpcId", vpc.ID())
        ctx.Export("vpcCidr", vpc.CidrBlock)
        ctx.Export("publicSubnetIds", publicSubnetIds)
        ctx.Export("privateSubnetIds", privateSubnetIds)

        return nil
    })
}

Component Resources

TypeScript: Reusable VPC Component

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

// Component input properties interface
export interface VpcNetworkArgs {
  cidrBlock: string;
  availabilityZones: string[];
  enableNatGateway?: boolean;
  singleNatGateway?: boolean;
  tags?: { [key: string]: string };
}

// VPC Network Component Resource
export class VpcNetwork extends pulumi.ComponentResource {
  public readonly vpc: aws.ec2.Vpc;
  public readonly publicSubnets: aws.ec2.Subnet[];
  public readonly privateSubnets: aws.ec2.Subnet[];
  public readonly internetGateway: aws.ec2.InternetGateway;
  public readonly natGateways: aws.ec2.NatGateway[];
  public readonly vpcId: pulumi.Output<string>;
  public readonly publicSubnetIds: pulumi.Output<string>[];
  public readonly privateSubnetIds: pulumi.Output<string>[];

  constructor(
    name: string,
    args: VpcNetworkArgs,
    opts?: pulumi.ComponentResourceOptions
  ) {
    super('custom:network:VpcNetwork', name, {}, opts);

    const defaultTags = args.tags || {};

    // Create VPC
    this.vpc = new aws.ec2.Vpc(
      `${name}-vpc`,
      {
        cidrBlock: args.cidrBlock,
        enableDnsHostnames: true,
        enableDnsSupport: true,
        tags: {
          ...defaultTags,
          Name: `${name}-vpc`,
        },
      },
      { parent: this }
    );

    // Create Internet Gateway
    this.internetGateway = new aws.ec2.InternetGateway(
      `${name}-igw`,
      {
        vpcId: this.vpc.id,
        tags: {
          ...defaultTags,
          Name: `${name}-igw`,
        },
      },
      { parent: this }
    );

    // Create public subnets
    this.publicSubnets = args.availabilityZones.map((az, index) => {
      return new aws.ec2.Subnet(
        `${name}-public-${index}`,
        {
          vpcId: this.vpc.id,
          cidrBlock: `10.0.${index}.0/24`,
          availabilityZone: az,
          mapPublicIpOnLaunch: true,
          tags: {
            ...defaultTags,
            Name: `${name}-public-${az}`,
            Type: 'public',
          },
        },
        { parent: this }
      );
    });

    // Create private subnets
    this.privateSubnets = args.availabilityZones.map((az, index) => {
      return new aws.ec2.Subnet(
        `${name}-private-${index}`,
        {
          vpcId: this.vpc.id,
          cidrBlock: `10.0.${index + 10}.0/24`,
          availabilityZone: az,
          tags: {
            ...defaultTags,
            Name: `${name}-private-${az}`,
            Type: 'private',
          },
        },
        { parent: this }
      );
    });

    // Create public route table
    const publicRouteTable = new aws.ec2.RouteTable(
      `${name}-public-rt`,
      {
        vpcId: this.vpc.id,
        routes: [
          {
            cidrBlock: '0.0.0.0/0',
            gatewayId: this.internetGateway.id,
          },
        ],
        tags: {
          ...defaultTags,
          Name: `${name}-public-rt`,
        },
      },
      { parent: this }
    );

    // Associate public subnets
    this.publicSubnets.forEach((subnet, index) => {
      new aws.ec2.RouteTableAssociation(
        `${name}-public-rta-${index}`,
        {
          subnetId: subnet.id,
          routeTableId: publicRouteTable.id,
        },
        { parent: this }
      );
    });

    // Create NAT Gateways if enabled
    this.natGateways = [];
    if (args.enableNatGateway) {
      const natCount = args.singleNatGateway ? 1 : args.availabilityZones.length;

      for (let i = 0; i < natCount; i++) {
        const eip = new aws.ec2.Eip(
          `${name}-nat-eip-${i}`,
          {
            domain: 'vpc',
            tags: {
              ...defaultTags,
              Name: `${name}-nat-eip-${i}`,
            },
          },
          { parent: this }
        );

        const natGateway = new aws.ec2.NatGateway(
          `${name}-nat-${i}`,
          {
            allocationId: eip.id,
            subnetId: this.publicSubnets[i].id,
            tags: {
              ...defaultTags,
              Name: `${name}-nat-${i}`,
            },
          },
          { parent: this, dependsOn: [this.internetGateway] }
        );

        this.natGateways.push(natGateway);
      }

      // Create private route tables with NAT Gateway routes
      this.privateSubnets.forEach((subnet, index) => {
        const natIndex = args.singleNatGateway ? 0 : index;
        const privateRouteTable = new aws.ec2.RouteTable(
          `${name}-private-rt-${index}`,
          {
            vpcId: this.vpc.id,
            routes: [
              {
                cidrBlock: '0.0.0.0/0',
                natGatewayId: this.natGateways[natIndex].id,
              },
            ],
            tags: {
              ...defaultTags,
              Name: `${name}-private-rt-${index}`,
            },
          },
          { parent: this }
        );

        new aws.ec2.RouteTableAssociation(
          `${name}-private-rta-${index}`,
          {
            subnetId: subnet.id,
            routeTableId: privateRouteTable.id,
          },
          { parent: this }
        );
      });
    }

    // Export convenience properties
    this.vpcId = this.vpc.id;
    this.publicSubnetIds = this.publicSubnets.map((s) => s.id);
    this.privateSubnetIds = this.privateSubnets.map((s) => s.id);

    // Register outputs
    this.registerOutputs({
      vpcId: this.vpcId,
      publicSubnetIds: this.publicSubnetIds,
      privateSubnetIds: this.privateSubnetIds,
    });
  }
}

// Usage example
const network = new VpcNetwork('production', {
  cidrBlock: '10.0.0.0/16',
  availabilityZones: ['us-east-1a', 'us-east-1b', 'us-east-1c'],
  enableNatGateway: true,
  singleNatGateway: false,
  tags: {
    Environment: 'production',
    Team: 'platform',
  },
});

export const vpcId = network.vpcId;
export const publicSubnetIds = network.publicSubnetIds;
export const privateSubnetIds = network.privateSubnetIds;

Python: Reusable VPC Component

import pulumi
from pulumi import ComponentResource, ResourceOptions
import pulumi_aws as aws
from typing import Optional, List, Dict


class VpcNetworkArgs:
    """Arguments for VpcNetwork component."""

    def __init__(
        self,
        cidr_block: str,
        availability_zones: List[str],
        enable_nat_gateway: bool = False,
        single_nat_gateway: bool = True,
        tags: Optional[Dict[str, str]] = None,
    ):
        self.cidr_block = cidr_block
        self.availability_zones = availability_zones
        self.enable_nat_gateway = enable_nat_gateway
        self.single_nat_gateway = single_nat_gateway
        self.tags = tags or {}


class VpcNetwork(ComponentResource):
    """Reusable VPC Network component."""

    def __init__(
        self,
        name: str,
        args: VpcNetworkArgs,
        opts: Optional[ResourceOptions] = None,
    ):
        super().__init__("custom:network:VpcNetwork", name, {}, opts)

        default_tags = args.tags

        # Create VPC
        self.vpc = aws.ec2.Vpc(
            f"{name}-vpc",
            cidr_block=args.cidr_block,
            enable_dns_hostnames=True,
            enable_dns_support=True,
            tags={
                **default_tags,
                "Name": f"{name}-vpc",
            },
            opts=ResourceOptions(parent=self),
        )

        # Create Internet Gateway
        self.internet_gateway = aws.ec2.InternetGateway(
            f"{name}-igw",
            vpc_id=self.vpc.id,
            tags={
                **default_tags,
                "Name": f"{name}-igw",
            },
            opts=ResourceOptions(parent=self),
        )

        # Create public subnets
        self.public_subnets: List[aws.ec2.Subnet] = []
        for index, az in enumerate(args.availability_zones):
            subnet = aws.ec2.Subnet(
                f"{name}-public-{index}",
                vpc_id=self.vpc.id,
                cidr_block=f"10.0.{index}.0/24",
                availability_zone=az,
                map_public_ip_on_launch=True,
                tags={
                    **default_tags,
                    "Name": f"{name}-public-{az}",
                    "Type": "public",
                },
                opts=ResourceOptions(parent=self),
            )
            self.public_subnets.append(subnet)

        # Create private subnets
        self.private_subnets: List[aws.ec2.Subnet] = []
        for index, az in enumerate(args.availability_zones):
            subnet = aws.ec2.Subnet(
                f"{name}-private-{index}",
                vpc_id=self.vpc.id,
                cidr_block=f"10.0.{index + 10}.0/24",
                availability_zone=az,
                tags={
                    **default_tags,
                    "Name": f"{name}-private-{az}",
                    "Type": "private",
                },
                opts=ResourceOptions(parent=self),
            )
            self.private_subnets.append(subnet)

        # Create public route table
        public_route_table = aws.ec2.RouteTable(
            f"{name}-public-rt",
            vpc_id=self.vpc.id,
            routes=[
                aws.ec2.RouteTableRouteArgs(
                    cidr_block="0.0.0.0/0",
                    gateway_id=self.internet_gateway.id,
                )
            ],
            tags={
                **default_tags,
                "Name": f"{name}-public-rt",
            },
            opts=ResourceOptions(parent=self),
        )

        # Associate public subnets
        for index, subnet in enumerate(self.public_subnets):
            aws.ec2.RouteTableAssociation(
                f"{name}-public-rta-{index}",
                subnet_id=subnet.id,
                route_table_id=public_route_table.id,
                opts=ResourceOptions(parent=self),
            )

        # Create NAT Gateways if enabled
        self.nat_gateways: List[aws.ec2.NatGateway] = []
        if args.enable_nat_gateway:
            nat_count = 1 if args.single_nat_gateway else len(args.availability_zones)

            for i in range(nat_count):
                eip = aws.ec2.Eip(
                    f"{name}-nat-eip-{i}",
                    domain="vpc",
                    tags={
                        **default_tags,
                        "Name": f"{name}-nat-eip-{i}",
                    },
                    opts=ResourceOptions(parent=self),
                )

                nat_gateway = aws.ec2.NatGateway(
                    f"{name}-nat-{i}",
                    allocation_id=eip.id,
                    subnet_id=self.public_subnets[i].id,
                    tags={
                        **default_tags,
                        "Name": f"{name}-nat-{i}",
                    },
                    opts=ResourceOptions(
                        parent=self, depends_on=[self.internet_gateway]
                    ),
                )
                self.nat_gateways.append(nat_gateway)

            # Create private route tables with NAT Gateway routes
            for index, subnet in enumerate(self.private_subnets):
                nat_index = 0 if args.single_nat_gateway else index
                private_route_table = aws.ec2.RouteTable(
                    f"{name}-private-rt-{index}",
                    vpc_id=self.vpc.id,
                    routes=[
                        aws.ec2.RouteTableRouteArgs(
                            cidr_block="0.0.0.0/0",
                            nat_gateway_id=self.nat_gateways[nat_index].id,
                        )
                    ],
                    tags={
                        **default_tags,
                        "Name": f"{name}-private-rt-{index}",
                    },
                    opts=ResourceOptions(parent=self),
                )

                aws.ec2.RouteTableAssociation(
                    f"{name}-private-rta-{index}",
                    subnet_id=subnet.id,
                    route_table_id=private_route_table.id,
                    opts=ResourceOptions(parent=self),
                )

        # Export convenience properties
        self.vpc_id = self.vpc.id
        self.public_subnet_ids = [s.id for s in self.public_subnets]
        self.private_subnet_ids = [s.id for s in self.private_subnets]

        # Register outputs
        self.register_outputs(
            {
                "vpc_id": self.vpc_id,
                "public_subnet_ids": self.public_subnet_ids,
                "private_subnet_ids": self.private_subnet_ids,
            }
        )


# Usage example
network = VpcNetwork(
    "production",
    VpcNetworkArgs(
        cidr_block="10.0.0.0/16",
        availability_zones=["us-east-1a", "us-east-1b", "us-east-1c"],
        enable_nat_gateway=True,
        single_nat_gateway=False,
        tags={
            "Environment": "production",
            "Team": "platform",
        },
    ),
)

pulumi.export("vpc_id", network.vpc_id)
pulumi.export("public_subnet_ids", network.public_subnet_ids)
pulumi.export("private_subnet_ids", network.private_subnet_ids)

Go: Reusable VPC Component

package components

import (
    "fmt"

    "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ec2"
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

// VpcNetworkArgs contains the arguments for the VpcNetwork component
type VpcNetworkArgs struct {
    CidrBlock          string
    AvailabilityZones  []string
    EnableNatGateway   bool
    SingleNatGateway   bool
    Tags               map[string]string
}

// VpcNetwork is a reusable component for VPC infrastructure
type VpcNetwork struct {
    pulumi.ResourceState

    Vpc              *ec2.Vpc
    InternetGateway  *ec2.InternetGateway
    PublicSubnets    []*ec2.Subnet
    PrivateSubnets   []*ec2.Subnet
    NatGateways      []*ec2.NatGateway
    VpcId            pulumi.IDOutput
    PublicSubnetIds  pulumi.StringArrayOutput
    PrivateSubnetIds pulumi.StringArrayOutput
}

// NewVpcNetwork creates a new VPC network component
func NewVpcNetwork(
    ctx *pulumi.Context,
    name string,
    args *VpcNetworkArgs,
    opts ...pulumi.ResourceOption,
) (*VpcNetwork, error) {
    component := &VpcNetwork{}
    err := ctx.RegisterComponentResource("custom:network:VpcNetwork", name, component, opts...)
    if err != nil {
        return nil, err
    }

    defaultTags := pulumi.StringMap{}
    for k, v := range args.Tags {
        defaultTags[k] = pulumi.String(v)
    }

    // Create VPC
    vpc, err := ec2.NewVpc(ctx, fmt.Sprintf("%s-vpc", name), &ec2.VpcArgs{
        CidrBlock:          pulumi.String(args.CidrBlock),
        EnableDnsHostnames: pulumi.Bool(true),
        EnableDnsSupport:   pulumi.Bool(true),
        Tags: pulumi.StringMap{
            "Name": pulumi.Sprintf("%s-vpc", name),
        }.ToStringMapOutput().ApplyT(func(m map[string]string) map[string]string {
            for k, v := range args.Tags {
                m[k] = v
            }
            return m
        }).(pulumi.StringMapOutput),
    }, pulumi.Parent(component))
    if err != nil {
        return nil, err
    }
    component.Vpc = vpc
    component.VpcId = vpc.ID()

    // Create Internet Gateway
    igw, err := ec2.NewInternetGateway(ctx, fmt.Sprintf("%s-igw", name), &ec2.InternetGatewayArgs{
        VpcId: vpc.ID(),
        Tags: pulumi.StringMap{
            "Name": pulumi.Sprintf("%s-igw", name),
        },
    }, pulumi.Parent(component))
    if err != nil {
        return nil, err
    }
    component.InternetGateway = igw

    // Create public subnets
    publicSubnetIds := pulumi.StringArray{}
    for i, az := range args.AvailabilityZones {
        subnet, err := ec2.NewSubnet(ctx, fmt.Sprintf("%s-public-%d", name, i), &ec2.SubnetArgs{
            VpcId:               vpc.ID(),
            CidrBlock:           pulumi.Sprintf("10.0.%d.0/24", i),
            AvailabilityZone:    pulumi.String(az),
            MapPublicIpOnLaunch: pulumi.Bool(true),
            Tags: pulumi.StringMap{
                "Name": pulumi.Sprintf("%s-public-%s", name, az),
                "Type": pulumi.String("public"),
            },
        }, pulumi.Parent(component))
        if err != nil {
            return nil, err
        }
        component.PublicSubnets = append(component.PublicSubnets, subnet)
        publicSubnetIds = append(publicSubnetIds, subnet.ID())
    }
    component.PublicSubnetIds = publicSubnetIds.ToStringArrayOutput()

    // Create private subnets
    privateSubnetIds := pulumi.StringArray{}
    for i, az := range args.AvailabilityZones {
        subnet, err := ec2.NewSubnet(ctx, fmt.Sprintf("%s-private-%d", name, i), &ec2.SubnetArgs{
            VpcId:            vpc.ID(),
            CidrBlock:        pulumi.Sprintf("10.0.%d.0/24", i+10),
            AvailabilityZone: pulumi.String(az),
            Tags: pulumi.StringMap{
                "Name": pulumi.Sprintf("%s-private-%s", name, az),
                "Type": pulumi.String("private"),
            },
        }, pulumi.Parent(component))
        if err != nil {
            return nil, err
        }
        component.PrivateSubnets = append(component.PrivateSubnets, subnet)
        privateSubnetIds = append(privateSubnetIds, subnet.ID())
    }
    component.PrivateSubnetIds = privateSubnetIds.ToStringArrayOutput()

    // Create public route table
    publicRouteTable, err := ec2.NewRouteTable(ctx, fmt.Sprintf("%s-public-rt", name), &ec2.RouteTableArgs{
        VpcId: vpc.ID(),
        Routes: ec2.RouteTableRouteArray{
            &ec2.RouteTableRouteArgs{
                CidrBlock: pulumi.String("0.0.0.0/0"),
                GatewayId: igw.ID(),
            },
        },
        Tags: pulumi.StringMap{
            "Name": pulumi.Sprintf("%s-public-rt", name),
        },
    }, pulumi.Parent(component))
    if err != nil {
        return nil, err
    }

    // Associate public subnets
    for i, subnet := range component.PublicSubnets {
        _, err := ec2.NewRouteTableAssociation(ctx, fmt.Sprintf("%s-public-rta-%d", name, i),
            &ec2.RouteTableAssociationArgs{
                SubnetId:     subnet.ID(),
                RouteTableId: publicRouteTable.ID(),
            }, pulumi.Parent(component))
        if err != nil {
            return nil, err
        }
    }

    // Register outputs
    ctx.RegisterResourceOutputs(component, pulumi.Map{
        "vpcId":            component.VpcId,
        "publicSubnetIds":  component.PublicSubnetIds,
        "privateSubnetIds": component.PrivateSubnetIds,
    })

    return component, nil
}

Multi-Cloud Patterns

TypeScript: Multi-Cloud Storage

import * as pulumi from '@pulumi/pulumi';
import * as aws from '@pulumi/aws';
import * as azure from '@pulumi/azure-native';
import * as gcp from '@pulumi/gcp';

const config = new pulumi.Config();
const cloudProvider = config.require('cloudProvider'); // aws, azure, or gcp
const environment = pulumi.getStack();

// Common interface for storage outputs
interface StorageOutputs {
  bucketName: pulumi.Output<string>;
  bucketArn: pulumi.Output<string>;
}

function createAwsStorage(): StorageOutputs {
  const bucket = new aws.s3.BucketV2('app-storage', {
    bucket: `myapp-${environment}-storage`,
    tags: {
      Environment: environment,
      ManagedBy: 'pulumi',
    },
  });

  new aws.s3.BucketVersioningV2('app-storage-versioning', {
    bucket: bucket.id,
    versioningConfiguration: {
      status: 'Enabled',
    },
  });

  new aws.s3.BucketServerSideEncryptionConfigurationV2('app-storage-encryption', {
    bucket: bucket.id,
    rules: [
      {
        applyServerSideEncryptionByDefault: {
          sseAlgorithm: 'AES256',
        },
      },
    ],
  });

  new aws.s3.BucketPublicAccessBlock('app-storage-public-access', {
    bucket: bucket.id,
    blockPublicAcls: true,
    blockPublicPolicy: true,
    ignorePublicAcls: true,
    restrictPublicBuckets: true,
  });

  return {
    bucketName: bucket.id,
    bucketArn: bucket.arn,
  };
}

function createAzureStorage(): StorageOutputs {
  const resourceGroup = new azure.resources.ResourceGroup('app-rg', {
    resourceGroupName: `myapp-${environment}-rg`,
    location: 'eastus',
    tags: {
      Environment: environment,
      ManagedBy: 'pulumi',
    },
  });

  const storageAccount = new azure.storage.StorageAccount('appstorage', {
    resourceGroupName: resourceGroup.name,
    accountName: `myapp${environment}storage`,
    location: resourceGroup.location,
    sku: {
      name: 'Standard_LRS',
    },
    kind: 'StorageV2',
    enableHttpsTrafficOnly: true,
    minimumTlsVersion: 'TLS1_2',
    tags: {
      Environment: environment,
      ManagedBy: 'pulumi',
    },
  });

  const container = new azure.storage.BlobContainer('app-container', {
    resourceGroupName: resourceGroup.name,
    accountName: storageAccount.name,
    containerName: 'app-data',
    publicAccess: 'None',
  });

  return {
    bucketName: container.name,
    bucketArn: storageAccount.id,
  };
}

function createGcpStorage(): StorageOutputs {
  const bucket = new gcp.storage.Bucket('app-storage', {
    name: `myapp-${environment}-storage`,
    location: 'US',
    uniformBucketLevelAccess: true,
    versioning: {
      enabled: true,
    },
    labels: {
      environment: environment,
      managed_by: 'pulumi',
    },
  });

  return {
    bucketName: bucket.name,
    bucketArn: bucket.selfLink,
  };
}

// Create storage based on cloud provider
let storage: StorageOutputs;
switch (cloudProvider) {
  case 'aws':
    storage = createAwsStorage();
    break;
  case 'azure':
    storage = createAzureStorage();
    break;
  case 'gcp':
    storage = createGcpStorage();
    break;
  default:
    throw new Error(`Unsupported cloud provider: ${cloudProvider}`);
}

export const bucketName = storage.bucketName;
export const bucketArn = storage.bucketArn;

TypeScript: Kubernetes Deployment

import * as pulumi from '@pulumi/pulumi';
import * as k8s from '@pulumi/kubernetes';

const config = new pulumi.Config();
const appName = config.get('appName') || 'my-app';
const appImage = config.require('appImage');
const replicas = config.getNumber('replicas') || 3;
const environment = pulumi.getStack();

// Create namespace
const namespace = new k8s.core.v1.Namespace('app-namespace', {
  metadata: {
    name: `${appName}-${environment}`,
    labels: {
      app: appName,
      environment: environment,
    },
  },
});

// Create ConfigMap
const configMap = new k8s.core.v1.ConfigMap('app-config', {
  metadata: {
    name: `${appName}-config`,
    namespace: namespace.metadata.name,
  },
  data: {
    LOG_LEVEL: 'info',
    ENVIRONMENT: environment,
  },
});

// Create Secret
const secret = new k8s.core.v1.Secret('app-secret', {
  metadata: {
    name: `${appName}-secret`,
    namespace: namespace.metadata.name,
  },
  type: 'Opaque',
  stringData: {
    DATABASE_URL: config.requireSecret('databaseUrl'),
    API_KEY: config.requireSecret('apiKey'),
  },
});

// Create Deployment
const deployment = new k8s.apps.v1.Deployment('app-deployment', {
  metadata: {
    name: appName,
    namespace: namespace.metadata.name,
    labels: {
      app: appName,
    },
  },
  spec: {
    replicas: replicas,
    selector: {
      matchLabels: {
        app: appName,
      },
    },
    template: {
      metadata: {
        labels: {
          app: appName,
          version: 'v1',
        },
        annotations: {
          'prometheus.io/scrape': 'true',
          'prometheus.io/port': '8080',
        },
      },
      spec: {
        containers: [
          {
            name: appName,
            image: appImage,
            ports: [
              {
                containerPort: 8080,
                name: 'http',
              },
            ],
            envFrom: [
              {
                configMapRef: {
                  name: configMap.metadata.name,
                },
              },
              {
                secretRef: {
                  name: secret.metadata.name,
                },
              },
            ],
            resources: {
              requests: {
                cpu: '100m',
                memory: '128Mi',
              },
              limits: {
                cpu: '500m',
                memory: '512Mi',
              },
            },
            livenessProbe: {
              httpGet: {
                path: '/health',
                port: 'http',
              },
              initialDelaySeconds: 30,
              periodSeconds: 10,
            },
            readinessProbe: {
              httpGet: {
                path: '/ready',
                port: 'http',
              },
              initialDelaySeconds: 5,
              periodSeconds: 5,
            },
            securityContext: {
              runAsNonRoot: true,
              runAsUser: 1000,
              readOnlyRootFilesystem: true,
              allowPrivilegeEscalation: false,
            },
          },
        ],
        serviceAccountName: appName,
        securityContext: {
          fsGroup: 1000,
        },
      },
    },
  },
});

// Create Service
const service = new k8s.core.v1.Service('app-service', {
  metadata: {
    name: appName,
    namespace: namespace.metadata.name,
    labels: {
      app: appName,
    },
  },
  spec: {
    type: 'ClusterIP',
    ports: [
      {
        port: 80,
        targetPort: 8080,
        protocol: 'TCP',
        name: 'http',
      },
    ],
    selector: {
      app: appName,
    },
  },
});

// Create HorizontalPodAutoscaler
const hpa = new k8s.autoscaling.v2.HorizontalPodAutoscaler('app-hpa', {
  metadata: {
    name: `${appName}-hpa`,
    namespace: namespace.metadata.name,
  },
  spec: {
    scaleTargetRef: {
      apiVersion: 'apps/v1',
      kind: 'Deployment',
      name: deployment.metadata.name,
    },
    minReplicas: replicas,
    maxReplicas: replicas * 3,
    metrics: [
      {
        type: 'Resource',
        resource: {
          name: 'cpu',
          target: {
            type: 'Utilization',
            averageUtilization: 70,
          },
        },
      },
      {
        type: 'Resource',
        resource: {
          name: 'memory',
          target: {
            type: 'Utilization',
            averageUtilization: 80,
          },
        },
      },
    ],
  },
});

// Create ServiceAccount
const serviceAccount = new k8s.core.v1.ServiceAccount('app-sa', {
  metadata: {
    name: appName,
    namespace: namespace.metadata.name,
  },
});

// Create Ingress
const ingress = new k8s.networking.v1.Ingress('app-ingress', {
  metadata: {
    name: `${appName}-ingress`,
    namespace: namespace.metadata.name,
    annotations: {
      'kubernetes.io/ingress.class': 'nginx',
      'cert-manager.io/cluster-issuer': 'letsencrypt-prod',
      'nginx.ingress.kubernetes.io/ssl-redirect': 'true',
    },
  },
  spec: {
    tls: [
      {
        hosts: [`${appName}.example.com`],
        secretName: `${appName}-tls`,
      },
    ],
    rules: [
      {
        host: `${appName}.example.com`,
        http: {
          paths: [
            {
              path: '/',
              pathType: 'Prefix',
              backend: {
                service: {
                  name: service.metadata.name,
                  port: {
                    number: 80,
                  },
                },
              },
            },
          ],
        },
      },
    ],
  },
});

export const namespaceName = namespace.metadata.name;
export const deploymentName = deployment.metadata.name;
export const serviceName = service.metadata.name;
export const ingressHost = ingress.spec.rules[0].host;

Configuration Management

Stack Configuration

# Pulumi.yaml - Project configuration
name: my-infrastructure
runtime: nodejs
description: Production infrastructure for MyApp
config:
  pulumi:tags:
    value:
      pulumi:template: aws-typescript

# Pulumi.dev.yaml - Development stack
config:
  aws:region: us-east-1
  my-infrastructure:vpcCidr: 10.0.0.0/16
  my-infrastructure:instanceType: t3.micro
  my-infrastructure:minInstances: "1"
  my-infrastructure:maxInstances: "2"

# Pulumi.staging.yaml - Staging stack
config:
  aws:region: us-east-1
  my-infrastructure:vpcCidr: 10.1.0.0/16
  my-infrastructure:instanceType: t3.small
  my-infrastructure:minInstances: "2"
  my-infrastructure:maxInstances: "4"

# Pulumi.prod.yaml - Production stack
config:
  aws:region: us-east-1
  my-infrastructure:vpcCidr: 10.2.0.0/16
  my-infrastructure:instanceType: t3.medium
  my-infrastructure:minInstances: "3"
  my-infrastructure:maxInstances: "10"

TypeScript: Configuration Helper

import * as pulumi from '@pulumi/pulumi';

// Define configuration schema
interface AppConfig {
  vpcCidr: string;
  instanceType: string;
  minInstances: number;
  maxInstances: number;
  databasePassword: pulumi.Output<string>;
  enableMonitoring: boolean;
}

// Load and validate configuration
export function loadConfig(): AppConfig {
  const config = new pulumi.Config();

  return {
    vpcCidr: config.get('vpcCidr') || '10.0.0.0/16',
    instanceType: config.get('instanceType') || 't3.micro',
    minInstances: config.getNumber('minInstances') || 1,
    maxInstances: config.getNumber('maxInstances') || 3,
    databasePassword: config.requireSecret('databasePassword'),
    enableMonitoring: config.getBoolean('enableMonitoring') ?? true,
  };
}

// Environment-aware configuration
export function getEnvironmentConfig() {
  const stack = pulumi.getStack();
  const project = pulumi.getProject();

  const environments: Record<string, { isProduction: boolean; logLevel: string }> = {
    dev: { isProduction: false, logLevel: 'debug' },
    staging: { isProduction: false, logLevel: 'info' },
    prod: { isProduction: true, logLevel: 'warn' },
  };

  const envConfig = environments[stack] || environments.dev;

  return {
    stack,
    project,
    ...envConfig,
    resourcePrefix: `${project}-${stack}`,
  };
}

// Usage
const appConfig = loadConfig();
const envConfig = getEnvironmentConfig();

console.log(`Deploying to ${envConfig.stack} (production: ${envConfig.isProduction})`);

Python: Configuration Helper

import pulumi
from dataclasses import dataclass
from typing import Optional


@dataclass
class AppConfig:
    """Application configuration loaded from Pulumi config."""

    vpc_cidr: str
    instance_type: str
    min_instances: int
    max_instances: int
    database_password: pulumi.Output[str]
    enable_monitoring: bool


def load_config() -> AppConfig:
    """Load and validate configuration from Pulumi config."""
    config = pulumi.Config()

    return AppConfig(
        vpc_cidr=config.get("vpc_cidr") or "10.0.0.0/16",
        instance_type=config.get("instance_type") or "t3.micro",
        min_instances=config.get_int("min_instances") or 1,
        max_instances=config.get_int("max_instances") or 3,
        database_password=config.require_secret("database_password"),
        enable_monitoring=config.get_bool("enable_monitoring") or True,
    )


@dataclass
class EnvironmentConfig:
    """Environment-specific configuration."""

    stack: str
    project: str
    is_production: bool
    log_level: str
    resource_prefix: str


def get_environment_config() -> EnvironmentConfig:
    """Get environment-aware configuration."""
    stack = pulumi.get_stack()
    project = pulumi.get_project()

    environments = {
        "dev": {"is_production": False, "log_level": "debug"},
        "staging": {"is_production": False, "log_level": "info"},
        "prod": {"is_production": True, "log_level": "warn"},
    }

    env_config = environments.get(stack, environments["dev"])

    return EnvironmentConfig(
        stack=stack,
        project=project,
        is_production=env_config["is_production"],
        log_level=env_config["log_level"],
        resource_prefix=f"{project}-{stack}",
    )


# Usage
app_config = load_config()
env_config = get_environment_config()

pulumi.log.info(
    f"Deploying to {env_config.stack} (production: {env_config.is_production})"
)

Secret Management

TypeScript: Secrets Best Practices

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

const config = new pulumi.Config();

// Good - Use Pulumi secrets for sensitive configuration
const databasePassword = config.requireSecret('databasePassword');
const apiKey = config.requireSecret('apiKey');

// Good - Create AWS Secrets Manager secret
const dbSecret = new aws.secretsmanager.Secret('db-credentials', {
  name: `${pulumi.getProject()}-${pulumi.getStack()}-db-credentials`,
  description: 'Database credentials for the application',
  tags: {
    Environment: pulumi.getStack(),
    ManagedBy: 'pulumi',
  },
});

// Store secret value (encrypted in state)
const dbSecretVersion = new aws.secretsmanager.SecretVersion('db-credentials-value', {
  secretId: dbSecret.id,
  secretString: pulumi.interpolate`{
    "username": "admin",
    "password": "${databasePassword}"
  }`,
});

// Good - Reference secrets in resources without exposing
const lambdaFunction = new aws.lambda.Function('api-handler', {
  functionName: `${pulumi.getProject()}-${pulumi.getStack()}-api`,
  runtime: aws.lambda.Runtime.NodeJS18dX,
  handler: 'index.handler',
  role: lambdaRole.arn,
  code: new pulumi.asset.AssetArchive({
    '.': new pulumi.asset.FileArchive('./lambda'),
  }),
  environment: {
    variables: {
      // Good - Reference secret ARN, not value
      DB_SECRET_ARN: dbSecret.arn,
      // Bad - Never do this (would expose in CloudFormation)
      // DB_PASSWORD: databasePassword,
    },
  },
});

// Good - Grant Lambda permission to read secret
const secretPolicy = new aws.iam.RolePolicy('lambda-secret-access', {
  role: lambdaRole.name,
  policy: pulumi.interpolate`{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue"
      ],
      "Resource": "${dbSecret.arn}"
    }]
  }`,
});

// Export secret ARN (safe - just the reference)
export const dbSecretArn = dbSecret.arn;

// Bad - Never export secret values
// export const dbPassword = databasePassword;

Python: Secrets Best Practices

import pulumi
import pulumi_aws as aws
import json

config = pulumi.Config()

# Good - Use Pulumi secrets for sensitive configuration
database_password = config.require_secret("database_password")
api_key = config.require_secret("api_key")

# Good - Create AWS Secrets Manager secret
db_secret = aws.secretsmanager.Secret(
    "db-credentials",
    name=f"{pulumi.get_project()}-{pulumi.get_stack()}-db-credentials",
    description="Database credentials for the application",
    tags={
        "Environment": pulumi.get_stack(),
        "ManagedBy": "pulumi",
    },
)

# Store secret value (encrypted in state)
db_secret_version = aws.secretsmanager.SecretVersion(
    "db-credentials-value",
    secret_id=db_secret.id,
    secret_string=database_password.apply(
        lambda pwd: json.dumps({"username": "admin", "password": pwd})
    ),
)


# Good - Create function to reference secret
def create_lambda_with_secret(secret_arn: pulumi.Output[str]):
    """Create Lambda function that can access secrets."""
    lambda_role = aws.iam.Role(
        "lambda-role",
        assume_role_policy=json.dumps(
            {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Action": "sts:AssumeRole",
                        "Effect": "Allow",
                        "Principal": {"Service": "lambda.amazonaws.com"},
                    }
                ],
            }
        ),
    )

    # Grant secret access
    aws.iam.RolePolicy(
        "lambda-secret-access",
        role=lambda_role.name,
        policy=secret_arn.apply(
            lambda arn: json.dumps(
                {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Action": ["secretsmanager:GetSecretValue"],
                            "Resource": arn,
                        }
                    ],
                }
            )
        ),
    )

    return aws.lambda_.Function(
        "api-handler",
        function_name=f"{pulumi.get_project()}-{pulumi.get_stack()}-api",
        runtime="nodejs20.x",
        handler="index.handler",
        role=lambda_role.arn,
        code=pulumi.AssetArchive({".": pulumi.FileArchive("./lambda")}),
        environment=aws.lambda_.FunctionEnvironmentArgs(
            variables={
                # Good - Reference secret ARN, not value
                "DB_SECRET_ARN": secret_arn,
            }
        ),
    )


lambda_function = create_lambda_with_secret(db_secret.arn)

# Export secret ARN (safe - just the reference)
pulumi.export("db_secret_arn", db_secret.arn)

Testing

TypeScript: Unit Tests with Mocks

import * as pulumi from '@pulumi/pulumi';
import { expect } from 'chai';

// Mock Pulumi runtime for testing
pulumi.runtime.setMocks({
  newResource: function (args: pulumi.runtime.MockResourceArgs): {
    id: string;
    state: Record<string, unknown>;
  } {
    return {
      id: `${args.name}-id`,
      state: args.inputs,
    };
  },
  call: function (args: pulumi.runtime.MockCallArgs) {
    return args.inputs;
  },
});

// Import after setting mocks
import * as infra from '../index';

describe('Infrastructure', function () {
  describe('VPC', function () {
    it('should create VPC with correct CIDR', async function () {
      const vpcCidr = await new Promise<string>((resolve) => {
        infra.vpcCidr.apply((cidr) => resolve(cidr));
      });
      expect(vpcCidr).to.equal('10.0.0.0/16');
    });

    it('should create VPC with DNS enabled', async function () {
      const vpc = await new Promise<Record<string, unknown>>((resolve) => {
        infra.vpc.apply((v) => resolve(v as Record<string, unknown>));
      });
      expect(vpc.enableDnsHostnames).to.be.true;
      expect(vpc.enableDnsSupport).to.be.true;
    });
  });

  describe('Subnets', function () {
    it('should create 3 public subnets', async function () {
      const publicSubnetIds = await new Promise<string[]>((resolve) => {
        pulumi.all(infra.publicSubnetIds).apply((ids) => resolve(ids));
      });
      expect(publicSubnetIds).to.have.lengthOf(3);
    });

    it('should create 3 private subnets', async function () {
      const privateSubnetIds = await new Promise<string[]>((resolve) => {
        pulumi.all(infra.privateSubnetIds).apply((ids) => resolve(ids));
      });
      expect(privateSubnetIds).to.have.lengthOf(3);
    });
  });

  describe('Tags', function () {
    it('should apply environment tag to all resources', async function () {
      const vpcTags = await new Promise<Record<string, string>>((resolve) => {
        infra.vpc.apply((v) => {
          const vpc = v as { tags?: Record<string, string> };
          resolve(vpc.tags || {});
        });
      });
      expect(vpcTags).to.have.property('Environment');
      expect(vpcTags).to.have.property('ManagedBy', 'pulumi');
    });
  });
});

Python: Unit Tests with Mocks

import unittest
from unittest.mock import patch, MagicMock
import pulumi


class PulumiMocks(pulumi.runtime.Mocks):
    """Mock Pulumi runtime for testing."""

    def new_resource(self, args: pulumi.runtime.MockResourceArgs):
        """Create mock resource."""
        return [f"{args.name}-id", args.inputs]

    def call(self, args: pulumi.runtime.MockCallArgs):
        """Handle function calls."""
        return args.inputs


# Set up mocks before importing infrastructure code
pulumi.runtime.set_mocks(PulumiMocks())


class TestInfrastructure(unittest.TestCase):
    """Test infrastructure resources."""

    @pulumi.runtime.test
    def test_vpc_cidr(self):
        """Test VPC has correct CIDR block."""
        # Import after mocks are set
        from __main__ import vpc

        def check_cidr(cidr):
            self.assertEqual(cidr, "10.0.0.0/16")

        vpc.cidr_block.apply(check_cidr)

    @pulumi.runtime.test
    def test_vpc_dns_enabled(self):
        """Test VPC has DNS enabled."""
        from __main__ import vpc

        def check_dns_hostnames(enabled):
            self.assertTrue(enabled)

        def check_dns_support(enabled):
            self.assertTrue(enabled)

        vpc.enable_dns_hostnames.apply(check_dns_hostnames)
        vpc.enable_dns_support.apply(check_dns_support)

    @pulumi.runtime.test
    def test_public_subnet_count(self):
        """Test correct number of public subnets."""
        from __main__ import public_subnets

        self.assertEqual(len(public_subnets), 3)

    @pulumi.runtime.test
    def test_private_subnet_count(self):
        """Test correct number of private subnets."""
        from __main__ import private_subnets

        self.assertEqual(len(private_subnets), 3)

    @pulumi.runtime.test
    def test_vpc_tags(self):
        """Test VPC has required tags."""
        from __main__ import vpc

        def check_tags(tags):
            self.assertIn("Environment", tags)
            self.assertEqual(tags.get("ManagedBy"), "pulumi")

        vpc.tags.apply(check_tags)


class TestComponentResource(unittest.TestCase):
    """Test custom component resources."""

    @pulumi.runtime.test
    def test_vpc_network_component(self):
        """Test VpcNetwork component creates expected resources."""
        from components.vpc_network import VpcNetwork, VpcNetworkArgs

        network = VpcNetwork(
            "test-network",
            VpcNetworkArgs(
                cidr_block="10.0.0.0/16",
                availability_zones=["us-east-1a", "us-east-1b"],
                enable_nat_gateway=False,
                tags={"Environment": "test"},
            ),
        )

        # Verify component created expected resources
        self.assertIsNotNone(network.vpc)
        self.assertIsNotNone(network.internet_gateway)
        self.assertEqual(len(network.public_subnets), 2)
        self.assertEqual(len(network.private_subnets), 2)


if __name__ == "__main__":
    unittest.main()

Go: Unit Tests

package main

import (
    "testing"

    "github.com/pulumi/pulumi/sdk/v3/go/common/resource"
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    "github.com/stretchr/testify/assert"
)

// Mocks for Pulumi runtime
type mocks int

func (mocks) NewResource(args pulumi.MockResourceArgs) (string, resource.PropertyMap, error) {
    return args.Name + "-id", args.Inputs, nil
}

func (mocks) Call(args pulumi.MockCallArgs) (resource.PropertyMap, error) {
    return args.Args, nil
}

func TestInfrastructure(t *testing.T) {
    err := pulumi.RunErr(func(ctx *pulumi.Context) error {
        // Create infrastructure
        infra, err := createInfrastructure(ctx)
        if err != nil {
            return err
        }

        // Test VPC CIDR
        pulumi.All(infra.VpcCidr).ApplyT(func(all []interface{}) error {
            cidr := all[0].(string)
            assert.Equal(t, "10.0.0.0/16", cidr)
            return nil
        })

        // Test subnet counts
        assert.Len(t, infra.PublicSubnets, 3)
        assert.Len(t, infra.PrivateSubnets, 3)

        return nil
    }, pulumi.WithMocks("project", "stack", mocks(0)))

    assert.NoError(t, err)
}

func TestVpcNetworkComponent(t *testing.T) {
    err := pulumi.RunErr(func(ctx *pulumi.Context) error {
        // Create component
        network, err := NewVpcNetwork(ctx, "test-network", &VpcNetworkArgs{
            CidrBlock:         "10.0.0.0/16",
            AvailabilityZones: []string{"us-east-1a", "us-east-1b"},
            EnableNatGateway:  false,
            Tags:              map[string]string{"Environment": "test"},
        })
        if err != nil {
            return err
        }

        // Verify resources created
        assert.NotNil(t, network.Vpc)
        assert.NotNil(t, network.InternetGateway)
        assert.Len(t, network.PublicSubnets, 2)
        assert.Len(t, network.PrivateSubnets, 2)

        return nil
    }, pulumi.WithMocks("project", "stack", mocks(0)))

    assert.NoError(t, err)
}

func TestSecurityGroupRules(t *testing.T) {
    err := pulumi.RunErr(func(ctx *pulumi.Context) error {
        // Test security group creation
        sg, err := createSecurityGroup(ctx, "test-sg", &SecurityGroupArgs{
            VpcId:       pulumi.String("vpc-123"),
            Description: "Test security group",
            IngressRules: []IngressRule{
                {Port: 443, Protocol: "tcp", CidrBlocks: []string{"0.0.0.0/0"}},
            },
        })
        if err != nil {
            return err
        }

        // Verify security group
        assert.NotNil(t, sg)

        return nil
    }, pulumi.WithMocks("project", "stack", mocks(0)))

    assert.NoError(t, err)
}

Policy as Code (CrossGuard)

TypeScript: Policy Pack

import * as policy from '@pulumi/policy';
import * as aws from '@pulumi/aws';

// Create policy pack
new policy.PolicyPack('aws-security-policies', {
  policies: [
    // Require encryption on S3 buckets
    {
      name: 's3-bucket-encryption',
      description: 'S3 buckets must have server-side encryption enabled',
      enforcementLevel: 'mandatory',
      validateResource: policy.validateResourceOfType(aws.s3.BucketV2, (bucket, args, reportViolation) => {
        // Check if encryption is configured
        // Note: BucketV2 requires separate encryption configuration resource
        reportViolation(
          'S3 bucket must have a BucketServerSideEncryptionConfigurationV2 resource configured'
        );
      }),
    },

    // Require public access block on S3 buckets
    {
      name: 's3-no-public-access',
      description: 'S3 buckets must block public access',
      enforcementLevel: 'mandatory',
      validateResource: policy.validateResourceOfType(
        aws.s3.BucketPublicAccessBlock,
        (block, args, reportViolation) => {
          if (!block.blockPublicAcls) {
            reportViolation('S3 bucket must block public ACLs');
          }
          if (!block.blockPublicPolicy) {
            reportViolation('S3 bucket must block public policies');
          }
          if (!block.ignorePublicAcls) {
            reportViolation('S3 bucket must ignore public ACLs');
          }
          if (!block.restrictPublicBuckets) {
            reportViolation('S3 bucket must restrict public buckets');
          }
        }
      ),
    },

    // Require tags on all resources
    {
      name: 'require-tags',
      description: 'All resources must have Environment and ManagedBy tags',
      enforcementLevel: 'mandatory',
      validateResource: (args, reportViolation) => {
        const tags = (args.props as { tags?: Record<string, string> }).tags;
        if (tags === undefined) {
          reportViolation('Resource must have tags');
          return;
        }
        if (!tags.Environment) {
          reportViolation('Resource must have Environment tag');
        }
        if (!tags.ManagedBy) {
          reportViolation('Resource must have ManagedBy tag');
        }
      },
    },

    // Restrict instance types in production
    {
      name: 'approved-instance-types',
      description: 'EC2 instances must use approved instance types',
      enforcementLevel: 'mandatory',
      validateResource: policy.validateResourceOfType(
        aws.ec2.Instance,
        (instance, args, reportViolation) => {
          const approvedTypes = [
            't3.micro',
            't3.small',
            't3.medium',
            't3.large',
            'm5.large',
            'm5.xlarge',
          ];
          if (!approvedTypes.includes(instance.instanceType || '')) {
            reportViolation(
              `Instance type ${instance.instanceType} is not approved. ` +
                `Use one of: ${approvedTypes.join(', ')}`
            );
          }
        }
      ),
    },

    // Require VPC for databases
    {
      name: 'rds-in-vpc',
      description: 'RDS instances must be deployed in a VPC',
      enforcementLevel: 'mandatory',
      validateResource: policy.validateResourceOfType(
        aws.rds.Instance,
        (instance, args, reportViolation) => {
          if (!instance.dbSubnetGroupName) {
            reportViolation('RDS instance must be deployed in a VPC (requires db_subnet_group_name)');
          }
        }
      ),
    },

    // Require encryption for RDS
    {
      name: 'rds-encryption',
      description: 'RDS instances must have storage encryption enabled',
      enforcementLevel: 'mandatory',
      validateResource: policy.validateResourceOfType(
        aws.rds.Instance,
        (instance, args, reportViolation) => {
          if (!instance.storageEncrypted) {
            reportViolation('RDS instance must have storage encryption enabled');
          }
        }
      ),
    },

    // Prevent public IPs on EC2 instances
    {
      name: 'no-public-ip',
      description: 'EC2 instances should not have public IPs in production',
      enforcementLevel: 'advisory',
      validateResource: policy.validateResourceOfType(
        aws.ec2.Instance,
        (instance, args, reportViolation) => {
          if (instance.associatePublicIpAddress) {
            reportViolation(
              'EC2 instance should not have a public IP. ' + 'Use a load balancer or NAT gateway instead.'
            );
          }
        }
      ),
    },

    // Require deletion protection for production databases
    {
      name: 'rds-deletion-protection',
      description: 'RDS instances must have deletion protection enabled',
      enforcementLevel: 'mandatory',
      validateStack: (args, reportViolation) => {
        // Check if this is a production stack
        if (args.getConfig('environment') === 'prod') {
          for (const resource of args.resources) {
            if (resource.type === 'aws:rds/instance:Instance') {
              const props = resource.props as { deletionProtection?: boolean };
              if (!props.deletionProtection) {
                reportViolation(
                  `RDS instance ${resource.name} must have deletion protection enabled in production`
                );
              }
            }
          }
        }
      },
    },
  ],
});

Python: Policy Pack

from pulumi_policy import (
    EnforcementLevel,
    PolicyPack,
    ReportViolation,
    ResourceValidationArgs,
    ResourceValidationPolicy,
    StackValidationArgs,
    StackValidationPolicy,
)


def s3_bucket_encryption_validator(
    args: ResourceValidationArgs, report_violation: ReportViolation
):
    """Validate S3 bucket encryption."""
    if args.resource_type == "aws:s3/bucketV2:BucketV2":
        report_violation(
            "S3 bucket must have a BucketServerSideEncryptionConfigurationV2 "
            "resource configured"
        )


def s3_public_access_validator(
    args: ResourceValidationArgs, report_violation: ReportViolation
):
    """Validate S3 bucket public access block."""
    if args.resource_type == "aws:s3/bucketPublicAccessBlock:BucketPublicAccessBlock":
        if not args.props.get("blockPublicAcls"):
            report_violation("S3 bucket must block public ACLs")
        if not args.props.get("blockPublicPolicy"):
            report_violation("S3 bucket must block public policies")
        if not args.props.get("ignorePublicAcls"):
            report_violation("S3 bucket must ignore public ACLs")
        if not args.props.get("restrictPublicBuckets"):
            report_violation("S3 bucket must restrict public buckets")


def require_tags_validator(
    args: ResourceValidationArgs, report_violation: ReportViolation
):
    """Validate required tags on resources."""
    tags = args.props.get("tags")
    if tags is None:
        report_violation("Resource must have tags")
        return
    if "Environment" not in tags:
        report_violation("Resource must have Environment tag")
    if "ManagedBy" not in tags:
        report_violation("Resource must have ManagedBy tag")


def approved_instance_types_validator(
    args: ResourceValidationArgs, report_violation: ReportViolation
):
    """Validate EC2 instance types."""
    if args.resource_type == "aws:ec2/instance:Instance":
        approved_types = [
            "t3.micro",
            "t3.small",
            "t3.medium",
            "t3.large",
            "m5.large",
            "m5.xlarge",
        ]
        instance_type = args.props.get("instanceType")
        if instance_type not in approved_types:
            report_violation(
                f"Instance type {instance_type} is not approved. "
                f"Use one of: {', '.join(approved_types)}"
            )


def rds_encryption_validator(
    args: ResourceValidationArgs, report_violation: ReportViolation
):
    """Validate RDS encryption."""
    if args.resource_type == "aws:rds/instance:Instance":
        if not args.props.get("storageEncrypted"):
            report_violation("RDS instance must have storage encryption enabled")


def rds_deletion_protection_validator(
    args: StackValidationArgs, report_violation: ReportViolation
):
    """Validate RDS deletion protection in production."""
    environment = args.get_config("environment")
    if environment == "prod":
        for resource in args.resources:
            if resource.resource_type == "aws:rds/instance:Instance":
                if not resource.props.get("deletionProtection"):
                    report_violation(
                        f"RDS instance {resource.name} must have deletion "
                        "protection enabled in production"
                    )


PolicyPack(
    name="aws-security-policies",
    enforcement_level=EnforcementLevel.MANDATORY,
    policies=[
        ResourceValidationPolicy(
            name="s3-bucket-encryption",
            description="S3 buckets must have server-side encryption enabled",
            validate=s3_bucket_encryption_validator,
        ),
        ResourceValidationPolicy(
            name="s3-no-public-access",
            description="S3 buckets must block public access",
            validate=s3_public_access_validator,
        ),
        ResourceValidationPolicy(
            name="require-tags",
            description="All resources must have Environment and ManagedBy tags",
            validate=require_tags_validator,
        ),
        ResourceValidationPolicy(
            name="approved-instance-types",
            description="EC2 instances must use approved instance types",
            validate=approved_instance_types_validator,
        ),
        ResourceValidationPolicy(
            name="rds-encryption",
            description="RDS instances must have storage encryption enabled",
            validate=rds_encryption_validator,
        ),
        StackValidationPolicy(
            name="rds-deletion-protection",
            description="RDS instances must have deletion protection enabled",
            validate=rds_deletion_protection_validator,
        ),
    ],
)

CLI Commands

Common Pulumi Commands

## Project initialization
pulumi new aws-typescript              # Create new TypeScript project
pulumi new aws-python                  # Create new Python project
pulumi new aws-go                      # Create new Go project

## Stack management
pulumi stack init dev                  # Create new stack
pulumi stack select prod               # Switch to stack
pulumi stack ls                        # List all stacks
pulumi stack rm dev --yes              # Delete stack

## Configuration
pulumi config set aws:region us-east-1        # Set config value
pulumi config set --secret dbPassword p@ss    # Set secret
pulumi config get dbPassword                  # Get config value
pulumi config                                 # List all config

## Preview and deploy
pulumi preview                         # Preview changes
pulumi preview --diff                  # Preview with detailed diff
pulumi up                              # Deploy changes
pulumi up --yes                        # Deploy without confirmation
pulumi up --target 'urn:...'           # Deploy specific resource

## State management
pulumi refresh                         # Refresh state from cloud
pulumi refresh --yes                   # Refresh without confirmation
pulumi state delete 'urn:...'          # Remove resource from state
pulumi import aws:s3/bucket:Bucket my-bucket bucket-name  # Import existing

## Destroy
pulumi destroy                         # Destroy all resources
pulumi destroy --yes                   # Destroy without confirmation
pulumi destroy --target 'urn:...'      # Destroy specific resource

## Outputs
pulumi stack output                    # Show all outputs
pulumi stack output vpcId              # Show specific output
pulumi stack output --json             # JSON format

## History and logs
pulumi stack history                   # Show deployment history
pulumi logs                            # Show logs
pulumi logs --follow                   # Stream logs

## Policy
pulumi policy new aws-typescript       # Create policy pack
pulumi policy publish org/pack         # Publish policy pack
pulumi preview --policy-pack ./policy  # Preview with local policy

Backend Configuration

## Pulumi Cloud (default)
pulumi login                           # Login to Pulumi Cloud

## Self-managed backends
pulumi login s3://my-bucket            # S3 backend
pulumi login azblob://container        # Azure Blob backend
pulumi login gs://my-bucket            # GCS backend
pulumi login file://~/.pulumi          # Local file backend

## Backend with passphrase encryption
export PULUMI_CONFIG_PASSPHRASE="secret"
pulumi login s3://my-bucket

CI/CD Integration

GitHub Actions Workflow

name: Pulumi Deploy

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

env:
  PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  AWS_REGION: us-east-1

jobs:
  preview:
    name: Preview
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Pulumi Preview
        uses: pulumi/actions@v5
        with:
          command: preview
          stack-name: org/project/dev
          comment-on-pr: true
          github-token: ${{ secrets.GITHUB_TOKEN }}

  deploy-dev:
    name: Deploy to Dev
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Pulumi Deploy
        uses: pulumi/actions@v5
        with:
          command: up
          stack-name: org/project/dev

  deploy-prod:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: deploy-dev
    if: github.ref == 'refs/heads/main'
    environment: production
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Pulumi Deploy
        uses: pulumi/actions@v5
        with:
          command: up
          stack-name: org/project/prod

GitLab CI Pipeline

stages:
  - test
  - preview
  - deploy

variables:
  PULUMI_ACCESS_TOKEN: $PULUMI_ACCESS_TOKEN
  AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
  AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
  AWS_REGION: us-east-1

.pulumi-base:
  image: pulumi/pulumi-nodejs:latest
  before_script:
    - npm ci
    - pulumi login

test:
  extends: .pulumi-base
  stage: test
  script:
    - npm test
    - npm run lint

preview:
  extends: .pulumi-base
  stage: preview
  script:
    - pulumi stack select dev
    - pulumi preview
  only:
    - merge_requests

deploy-dev:
  extends: .pulumi-base
  stage: deploy
  script:
    - pulumi stack select dev
    - pulumi up --yes
  only:
    - main

deploy-prod:
  extends: .pulumi-base
  stage: deploy
  script:
    - pulumi stack select prod
    - pulumi up --yes
  only:
    - main
  when: manual
  environment:
    name: production

Anti-Patterns

Hardcoded Resource Names

// Bad - Hardcoded names prevent multiple environments
const bucket = new aws.s3.BucketV2('bucket', {
  bucket: 'my-app-bucket', // Cannot deploy to multiple environments
});

// Good - Use stack/project for uniqueness
const bucket = new aws.s3.BucketV2('bucket', {
  bucket: `my-app-${pulumi.getStack()}-bucket`,
});

// Good - Let Pulumi auto-name
const bucket = new aws.s3.BucketV2('app-bucket'); // Pulumi adds unique suffix

Secrets in Plain Text

// Bad - Secret exposed in state and logs
const config = new pulumi.Config();
const password = config.require('password');

// Good - Use Pulumi secrets
const password = config.requireSecret('password');

// Bad - Secret in code
const apiKey = 'sk_live_abc123'; // NEVER do this

// Good - From configuration
const apiKey = config.requireSecret('apiKey');

Missing Error Handling

// Bad - No error handling for async operations
const bucket = new aws.s3.BucketV2('bucket');
bucket.id.apply((id) => {
  // Assuming id is always valid
  console.log(id);
});

// Good - Handle potential undefined
bucket.id.apply((id) => {
  if (id) {
    console.log(`Bucket created: ${id}`);
  } else {
    console.error('Bucket ID not available');
  }
});

Circular Dependencies

// Bad - Circular dependency between resources
const sgA = new aws.ec2.SecurityGroup('sg-a', {
  ingress: [
    {
      securityGroups: [sgB.id], // sgB not defined yet!
    },
  ],
});

const sgB = new aws.ec2.SecurityGroup('sg-b', {
  ingress: [
    {
      securityGroups: [sgA.id],
    },
  ],
});

// Good - Use security group rules separately
const sgA = new aws.ec2.SecurityGroup('sg-a', {});
const sgB = new aws.ec2.SecurityGroup('sg-b', {});

new aws.ec2.SecurityGroupRule('sg-a-from-b', {
  securityGroupId: sgA.id,
  sourceSecurityGroupId: sgB.id,
  type: 'ingress',
  protocol: 'tcp',
  fromPort: 443,
  toPort: 443,
});

new aws.ec2.SecurityGroupRule('sg-b-from-a', {
  securityGroupId: sgB.id,
  sourceSecurityGroupId: sgA.id,
  type: 'ingress',
  protocol: 'tcp',
  fromPort: 443,
  toPort: 443,
});

Not Using Components

// Bad - Repeated infrastructure code
const vpcDev = new aws.ec2.Vpc('dev-vpc', {
  cidrBlock: '10.0.0.0/16',
  enableDnsHostnames: true,
});
const igwDev = new aws.ec2.InternetGateway('dev-igw', {
  vpcId: vpcDev.id,
});
// ... 50 more lines for dev

const vpcProd = new aws.ec2.Vpc('prod-vpc', {
  cidrBlock: '10.1.0.0/16',
  enableDnsHostnames: true,
});
const igwProd = new aws.ec2.InternetGateway('prod-igw', {
  vpcId: vpcProd.id,
});
// ... 50 more lines for prod (duplicated!)

// Good - Use ComponentResource
const devNetwork = new VpcNetwork('dev', {
  cidrBlock: '10.0.0.0/16',
  availabilityZones: ['us-east-1a', 'us-east-1b'],
});

const prodNetwork = new VpcNetwork('prod', {
  cidrBlock: '10.1.0.0/16',
  availabilityZones: ['us-east-1a', 'us-east-1b', 'us-east-1c'],
});

Ignoring Stack Outputs

// Bad - No outputs for cross-stack references
const vpc = new aws.ec2.Vpc('vpc', {
  cidrBlock: '10.0.0.0/16',
});
// Other stacks can't reference this VPC!

// Good - Export important values
export const vpcId = vpc.id;
export const vpcCidr = vpc.cidrBlock;
export const vpcArn = vpc.arn;

// In another stack, reference using StackReference
const networkStack = new pulumi.StackReference('org/network/prod');
const vpcId = networkStack.getOutput('vpcId');

Tool Configuration

TypeScript: package.json

{
  "name": "my-pulumi-project",
  "main": "index.ts",
  "devDependencies": {
    "@pulumi/pulumi": "^3.0.0",
    "@pulumi/aws": "^6.0.0",
    "@pulumi/policy": "^1.0.0",
    "@types/chai": "^4.3.0",
    "@types/mocha": "^10.0.0",
    "@types/node": "^20.0.0",
    "@typescript-eslint/eslint-plugin": "^6.0.0",
    "@typescript-eslint/parser": "^6.0.0",
    "chai": "^4.3.0",
    "eslint": "^8.50.0",
    "eslint-config-prettier": "^9.0.0",
    "mocha": "^10.2.0",
    "prettier": "^3.0.0",
    "ts-node": "^10.9.0",
    "typescript": "^5.2.0"
  },
  "scripts": {
    "build": "tsc",
    "test": "mocha -r ts-node/register test/**/*.test.ts",
    "lint": "eslint . --ext .ts",
    "lint:fix": "eslint . --ext .ts --fix",
    "format": "prettier --write '**/*.ts'",
    "format:check": "prettier --check '**/*.ts'",
    "validate": "npm run lint && npm run format:check && npm run test"
  }
}

Python: pyproject.toml

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "my-pulumi-project"
version = "0.1.0"
description = "Pulumi infrastructure project"
readme = "README.md"
requires-python = ">=3.9"
dependencies = [
    "pulumi>=3.0.0",
    "pulumi-aws>=6.0.0",
    "pulumi-policy>=1.0.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0.0",
    "pytest-cov>=4.0.0",
    "black>=23.0.0",
    "flake8>=6.0.0",
    "mypy>=1.0.0",
    "isort>=5.12.0",
]

[tool.black]
line-length = 100
target-version = ["py39", "py310", "py311"]

[tool.isort]
profile = "black"
line_length = 100

[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
ignore_missing_imports = true

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
addopts = "-v --cov=. --cov-report=term-missing"

Go: go.mod

module my-pulumi-project

go 1.21

require (
    github.com/pulumi/pulumi-aws/sdk/v6 v6.0.0
    github.com/pulumi/pulumi/sdk/v3 v3.0.0
    github.com/stretchr/testify v1.8.4
)

ESLint Configuration

// .eslintrc.js
module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
    project: './tsconfig.json',
  },
  plugins: ['@typescript-eslint'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
    'prettier',
  ],
  rules: {
    '@typescript-eslint/no-explicit-any': 'error',
    '@typescript-eslint/explicit-function-return-type': 'warn',
    '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
    '@typescript-eslint/no-floating-promises': 'error',
    'no-console': ['warn', { allow: ['warn', 'error'] }],
  },
  ignorePatterns: ['*.js', '*.d.ts', 'node_modules/'],
};

Pre-commit Configuration

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-added-large-files
      - id: detect-private-key

  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v3.1.0
    hooks:
      - id: prettier
        types_or: [javascript, jsx, ts, tsx, json]

  - repo: https://github.com/pre-commit/mirrors-eslint
    rev: v8.56.0
    hooks:
      - id: eslint
        files: \.tsx?$
        types: [file]
        additional_dependencies:
          - eslint@8.56.0
          - '@typescript-eslint/eslint-plugin@6.21.0'
          - '@typescript-eslint/parser@6.21.0'
          - eslint-config-prettier@9.1.0

  - repo: https://github.com/psf/black
    rev: 24.1.0
    hooks:
      - id: black

  - repo: https://github.com/pycqa/flake8
    rev: 7.0.0
    hooks:
      - id: flake8

  - repo: https://github.com/pycqa/isort
    rev: 5.13.0
    hooks:
      - id: isort

References

Official Documentation

Best Practices

Provider Documentation


Status: Active