Build cloud infrastructure with Pulumi using TypeScript for type-safe IaC in Google Antigravity
# Pulumi TypeScript Infrastructure for Google Antigravity
Pulumi enables infrastructure as code using real programming languages. This guide covers Pulumi patterns with TypeScript optimized for Google Antigravity IDE and Gemini 3.
## Project Setup
```typescript
// Pulumi.yaml
name: my-infrastructure
runtime: nodejs
description: Production infrastructure with Pulumi
// index.ts
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
const config = new pulumi.Config();
const environment = pulumi.getStack();
const projectName = config.require("projectName");
// Tags applied to all resources
const tags = {
Environment: environment,
Project: projectName,
ManagedBy: "pulumi",
};
```
## VPC Component
```typescript
// components/vpc.ts
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
interface VpcArgs {
name: string;
cidrBlock?: string;
numberOfAvailabilityZones?: number;
tags?: Record<string, string>;
}
export class Vpc extends pulumi.ComponentResource {
public readonly vpc: awsx.ec2.Vpc;
public readonly vpcId: pulumi.Output<string>;
public readonly privateSubnetIds: pulumi.Output<string[]>;
public readonly publicSubnetIds: pulumi.Output<string[]>;
constructor(name: string, args: VpcArgs, opts?: pulumi.ComponentResourceOptions) {
super("custom:network:Vpc", name, {}, opts);
this.vpc = new awsx.ec2.Vpc(name, {
cidrBlock: args.cidrBlock || "10.0.0.0/16",
numberOfAvailabilityZones: args.numberOfAvailabilityZones || 3,
natGateways: { strategy: awsx.ec2.NatGatewayStrategy.OnePerAz },
subnetSpecs: [
{ type: awsx.ec2.SubnetType.Public, cidrMask: 24 },
{ type: awsx.ec2.SubnetType.Private, cidrMask: 24 },
],
tags: { ...args.tags, Name: name },
}, { parent: this });
this.vpcId = this.vpc.vpcId;
this.privateSubnetIds = this.vpc.privateSubnetIds;
this.publicSubnetIds = this.vpc.publicSubnetIds;
this.registerOutputs({
vpcId: this.vpcId,
privateSubnetIds: this.privateSubnetIds,
publicSubnetIds: this.publicSubnetIds,
});
}
}
```
## ECS Fargate Service
```typescript
// components/fargate-service.ts
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
interface FargateServiceArgs {
name: string;
vpcId: pulumi.Input<string>;
subnetIds: pulumi.Input<string[]>;
image: string;
port: number;
cpu?: number;
memory?: number;
desiredCount?: number;
environment?: Record<string, string>;
secrets?: Record<string, pulumi.Input<string>>;
healthCheckPath?: string;
tags?: Record<string, string>;
}
export class FargateService extends pulumi.ComponentResource {
public readonly url: pulumi.Output<string>;
public readonly service: awsx.ecs.FargateService;
constructor(name: string, args: FargateServiceArgs, opts?: pulumi.ComponentResourceOptions) {
super("custom:ecs:FargateService", name, {}, opts);
// Create ECS cluster
const cluster = new aws.ecs.Cluster(`${name}-cluster`, {
settings: [{ name: "containerInsights", value: "enabled" }],
tags: args.tags,
}, { parent: this });
// Create ALB
const alb = new awsx.lb.ApplicationLoadBalancer(`${name}-alb`, {
subnetIds: args.subnetIds,
tags: args.tags,
}, { parent: this });
// Create Fargate service
this.service = new awsx.ecs.FargateService(`${name}-service`, {
cluster: cluster.arn,
networkConfiguration: {
subnets: args.subnetIds,
assignPublicIp: false,
},
desiredCount: args.desiredCount || 2,
taskDefinitionArgs: {
container: {
name: args.name,
image: args.image,
cpu: args.cpu || 256,
memory: args.memory || 512,
essential: true,
portMappings: [{
containerPort: args.port,
targetGroup: alb.defaultTargetGroup,
}],
environment: Object.entries(args.environment || {}).map(([name, value]) => ({
name,
value,
})),
secrets: Object.entries(args.secrets || {}).map(([name, valueFrom]) => ({
name,
valueFrom,
})),
healthCheck: {
command: ["CMD-SHELL", `curl -f http://localhost:${args.port}${args.healthCheckPath || "/health"} || exit 1`],
interval: 30,
timeout: 5,
retries: 3,
},
logConfiguration: {
logDriver: "awslogs",
options: {
"awslogs-group": `/ecs/${name}`,
"awslogs-region": aws.config.region || "us-east-1",
"awslogs-stream-prefix": "ecs",
},
},
},
},
tags: args.tags,
}, { parent: this });
this.url = alb.loadBalancer.dnsName;
this.registerOutputs({ url: this.url });
}
}
```
## RDS Database Component
```typescript
// components/database.ts
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as random from "@pulumi/random";
interface DatabaseArgs {
name: string;
vpcId: pulumi.Input<string>;
subnetIds: pulumi.Input<string[]>;
allowedSecurityGroups: pulumi.Input<string>[];
instanceClass?: string;
allocatedStorage?: number;
tags?: Record<string, string>;
}
export class Database extends pulumi.ComponentResource {
public readonly endpoint: pulumi.Output<string>;
public readonly secretArn: pulumi.Output<string>;
public readonly connectionString: pulumi.Output<string>;
constructor(name: string, args: DatabaseArgs, opts?: pulumi.ComponentResourceOptions) {
super("custom:database:PostgreSQL", name, {}, opts);
// Generate password
const password = new random.RandomPassword(`${name}-password`, {
length: 32,
special: false,
}, { parent: this });
// Create subnet group
const subnetGroup = new aws.rds.SubnetGroup(`${name}-subnets`, {
subnetIds: args.subnetIds,
tags: args.tags,
}, { parent: this });
// Create security group
const securityGroup = new aws.ec2.SecurityGroup(`${name}-sg`, {
vpcId: args.vpcId,
ingress: args.allowedSecurityGroups.map(sg => ({
fromPort: 5432,
toPort: 5432,
protocol: "tcp",
securityGroups: [sg],
})),
egress: [{
fromPort: 0,
toPort: 0,
protocol: "-1",
cidrBlocks: ["0.0.0.0/0"],
}],
tags: args.tags,
}, { parent: this });
// Create RDS instance
const db = new aws.rds.Instance(`${name}-db`, {
identifier: name,
engine: "postgres",
engineVersion: "15.4",
instanceClass: args.instanceClass || "db.t3.medium",
allocatedStorage: args.allocatedStorage || 20,
storageType: "gp3",
storageEncrypted: true,
dbName: name.replace(/-/g, "_"),
username: "admin",
password: password.result,
dbSubnetGroupName: subnetGroup.name,
vpcSecurityGroupIds: [securityGroup.id],
backupRetentionPeriod: 7,
multiAz: true,
deletionProtection: true,
skipFinalSnapshot: false,
finalSnapshotIdentifier: `${name}-final`,
tags: args.tags,
}, { parent: this });
this.endpoint = db.endpoint;
this.connectionString = pulumi.interpolate`postgresql://admin:${password.result}@${db.endpoint}/${name.replace(/-/g, "_")}`;
// Store credentials in Secrets Manager
const secret = new aws.secretsmanager.Secret(`${name}-credentials`, {
name: `${name}-db-credentials`,
tags: args.tags,
}, { parent: this });
new aws.secretsmanager.SecretVersion(`${name}-credentials-version`, {
secretId: secret.id,
secretString: pulumi.jsonStringify({
username: "admin",
password: password.result,
host: db.address,
port: db.port,
database: name.replace(/-/g, "_"),
}),
}, { parent: this });
this.secretArn = secret.arn;
this.registerOutputs({
endpoint: this.endpoint,
secretArn: this.secretArn,
});
}
}
```
## Best Practices
1. **Component Resources**: Create reusable components for common patterns
2. **Type Safety**: Leverage TypeScript for compile-time validation
3. **Stacks**: Use stacks for environment separation
4. **Secrets**: Never hardcode secrets; use config secrets or Secrets Manager
5. **Outputs**: Export important values for cross-stack references
6. **Testing**: Write unit tests for infrastructure components
Google Antigravity's Gemini 3 understands Pulumi patterns and can generate infrastructure code from architecture requirements.This Pulumi prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their pulumi implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For Pulumi projects, consider mentioning your framework version, coding style, and any specific libraries you're using.