DEV Community

Alex Spinov
Alex Spinov

Posted on

Pulumi Has a Free Automation API You're Not Using

Pulumi's Automation API lets you embed infrastructure-as-code inside your applications. No CLI needed — create, update, and destroy stacks programmatically from TypeScript, Python, or Go.

The Free APIs You're Missing

1. Automation API — Programmatic Infrastructure

import { LocalWorkspace } from "@pulumi/pulumi/automation";

async function deployInfra() {
  const stack = await LocalWorkspace.createOrSelectStack({
    stackName: "production",
    projectName: "my-app",
    program: async () => {
      const bucket = new aws.s3.Bucket("my-bucket", {
        website: { indexDocument: "index.html" },
      });
      return { bucketUrl: bucket.websiteEndpoint };
    },
  });

  await stack.setConfig("aws:region", { value: "us-east-1" });
  const result = await stack.up({ onOutput: console.log });
  console.log("URL:", result.outputs.bucketUrl.value);
}
Enter fullscreen mode Exit fullscreen mode

Deploy infrastructure from an Express route, a Lambda function, or a CLI tool. No shell exec needed.

2. Stack References — Cross-Stack Dependencies

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

const networkStack = new pulumi.StackReference("org/network/prod");
const vpcId = networkStack.getOutput("vpcId");
const subnetIds = networkStack.getOutput("subnetIds");

const cluster = new aws.ecs.Cluster("app", {
  settings: [{ name: "containerInsights", value: "enabled" }],
});
Enter fullscreen mode Exit fullscreen mode

3. Component Resources — Reusable Infrastructure Patterns

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

  constructor(name: string, args: WebAppArgs, opts?: pulumi.ComponentResourceOptions) {
    super("custom:WebApp", name, {}, opts);

    const bucket = new aws.s3.Bucket(`${name}-bucket`, {}, { parent: this });
    const cdn = new aws.cloudfront.Distribution(`${name}-cdn`, {
      origins: [{ domainName: bucket.bucketRegionalDomainName }],
    }, { parent: this });

    this.url = cdn.domainName;
    this.registerOutputs({ url: this.url });
  }
}

// Usage: const app = new WebApp("my-site", { domain: "example.com" });
Enter fullscreen mode Exit fullscreen mode

4. Policy as Code — Enforce Rules Before Deploy

import { PolicyPack, validateResourceOfType } from "@pulumi/policy";
import * as aws from "@pulumi/aws";

new PolicyPack("security", {
  policies: [
    {
      name: "no-public-s3",
      description: "S3 buckets must not be public",
      enforcementLevel: "mandatory",
      validateResource: validateResourceOfType(aws.s3.Bucket, (bucket, args, reportViolation) => {
        if (bucket.acl === "public-read") {
          reportViolation("S3 buckets cannot be public");
        }
      }),
    },
  ],
});
Enter fullscreen mode Exit fullscreen mode

5. Transforms — Modify Resources Before Creation

const stack = await LocalWorkspace.createOrSelectStack({
  stackName: "prod",
  program: async () => { /* ... */ },
});

pulumi.runtime.registerStackTransformation((args) => {
  if (args.type === "aws:ec2/instance:Instance") {
    args.props.tags = { ...args.props.tags, ManagedBy: "pulumi" };
  }
  return { props: args.props, opts: args.opts };
});
Enter fullscreen mode Exit fullscreen mode

Getting Started

curl -fsSL https://get.pulumi.com | sh
pulumi new typescript
pulumi up
Enter fullscreen mode Exit fullscreen mode

Need data from any website delivered as clean JSON? I build production web scrapers that handle anti-bot, proxies, and rate limits. 77 scrapers running in production. Email me: Spinov001@gmail.com

Check out my awesome-web-scraping list for the best scraping tools and resources.

Top comments (0)