DEV Community

Alex Spinov
Alex Spinov

Posted on

Pulumi Has a Free API That Lets You Write Infrastructure as Real Code

Pulumi is infrastructure as code using real programming languages — TypeScript, Python, Go, C#. No YAML. No HCL. Just code.

Define Infrastructure in TypeScript

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

// S3 bucket for scraped data
const bucket = new aws.s3.BucketV2("scraping-data", {
  bucket: "my-scraping-results",
});

// Lambda function for scraping
const scraperFunction = new aws.lambda.Function("scraper", {
  runtime: "nodejs20.x",
  handler: "index.handler",
  code: new pulumi.asset.AssetArchive({
    "index.js": new pulumi.asset.FileAsset("./scraper/index.js"),
  }),
  timeout: 300,
  memorySize: 512,
  environment: {
    variables: {
      BUCKET_NAME: bucket.bucket,
      NODE_ENV: "production",
    },
  },
});

// Schedule: run every hour
const schedule = new aws.cloudwatch.EventRule("hourly-scrape", {
  scheduleExpression: "rate(1 hour)",
});

new aws.cloudwatch.EventTarget("scraper-target", {
  rule: schedule.name,
  arn: scraperFunction.arn,
});

// Export outputs
export const bucketName = bucket.bucket;
export const functionArn = scraperFunction.arn;
Enter fullscreen mode Exit fullscreen mode

Containers: ECS + Fargate

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

const cluster = new aws.ecs.Cluster("scraping-cluster");

const service = new awsx.ecs.FargateService("scraper-service", {
  cluster: cluster.arn,
  desiredCount: 2,
  taskDefinitionArgs: {
    container: {
      name: "scraper",
      image: "my-scraper:latest",
      cpu: 256,
      memory: 512,
      essential: true,
      environment: [
        { name: "DATABASE_URL", value: dbUrl },
      ],
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Database: RDS PostgreSQL

const db = new aws.rds.Instance("scraping-db", {
  engine: "postgres",
  engineVersion: "16.1",
  instanceClass: "db.t4g.micro",
  allocatedStorage: 20,
  dbName: "scraping",
  username: "admin",
  password: config.requireSecret("dbPassword"),
  skipFinalSnapshot: true,
});

export const dbEndpoint = db.endpoint;
Enter fullscreen mode Exit fullscreen mode

Stack References: Multi-Stack

// In network stack
export const vpcId = vpc.id;
export const subnetIds = subnets.map(s => s.id);

// In app stack
const network = new pulumi.StackReference("org/network/prod");
const vpcId = network.getOutput("vpcId");
Enter fullscreen mode Exit fullscreen mode

Testing Infrastructure

import * as pulumi from "@pulumi/pulumi";
import { describe, it, expect } from "vitest";

describe("Infrastructure", () => {
  it("bucket should have encryption", async () => {
    const bucket = new aws.s3.BucketV2("test-bucket");
    const encryption = await bucket.serverSideEncryptionConfiguration;
    expect(encryption).toBeDefined();
  });
});
Enter fullscreen mode Exit fullscreen mode

Deploy scraping infrastructure? My Apify tools run on managed infrastructure.

Custom IaC solution? Email spinov001@gmail.com

Top comments (0)