Elysia Tools
Navigation
Infrastructure as Code
Pulumi Infrastructure as Code
Modern Infrastructure as Code examples using Pulumi with TypeScript, Python, and Go
Samples
Entries inside this sample collection
Pulumi with TypeScript for AWS
Deploying AWS infrastructure using Pulumi and TypeScript
Difficulty
4/10
Estimated time
15 min
Tags
pulumi, typescript, aws, serverless, iac
Prerequisites
Node.js, AWS account, Pulumi CLI
// Pulumi TypeScript for AWS
import * as pulumi from '@pulumi/pulumi';
import * as aws from '@pulumi/aws';
// Get AWS provider configuration
const config = new pulumi.Config();
const stackName = pulumi.getStack();
const environment = stackName === 'prod' ? 'production' : 'development';
// Create an AWS resource (S3 Bucket)
const bucket = new aws.s3.Bucket('my-app-bucket', {
bucket: pulumi.interpolate`my-app-bucket-${stackName}-${Math.floor(Math.random() * 1000000)}`,
acl: 'private',
versioning: {
enabled: true,
},
tags: {
Name: pulumi.interpolate`my-app-bucket-${stackName}`,
Environment: environment,
Project: 'pulumi-demo',
ManagedBy: 'pulumi'
},
website: {
indexDocument: 'index.html',
errorDocument: 'error.html'
},
forceDestroy: true
});
// Create IAM role for Lambda
const lambdaRole = new aws.iam.Role('app-lambda-role', {
assumeRolePolicy: JSON.stringify({
Version: '2012-10-17',
Statement: [{
Action: 'sts:AssumeRole',
Effect: 'Allow',
Principal: {
Service: 'lambda.amazonaws.com'
}
}]
}),
tags: {
Name: pulumi.interpolate`app-lambda-role-${stackName}`,
Environment: environment
}
});
// Attach basic execution policy
new aws.iam.RolePolicyAttachment('app-lambda-basic-execution', {
role: lambdaRole.name,
policyArn: aws.iam.ManagedPolicies.AWSLambdaBasicExecutionRole,
});
// Create Lambda function
const lambdaFunction = new aws.lambda.Function('app-api-function', {
name: pulumi.interpolate`app-api-${stackName}`,
runtime: 'nodejs18.x',
handler: 'index.handler',
role: lambdaRole.arn,
s3Bucket: bucket.id,
s3Key: 'api/function.zip',
timeout: 30,
memorySize: 256,
environment: {
variables: {
NODE_ENV: environment,
BUCKET_NAME: bucket.id
}
},
tags: {
Name: pulumi.interpolate`app-api-${stackName}`,
Environment: environment
}
});
// Create API Gateway
const api = new aws.apigateway.RestApi('app-api', {
name: pulumi.interpolate`app-api-${stackName}`,
description: pulumi.interpolate`API Gateway for Pulumi demo in ${environment}`,
endpointConfiguration: {
types: 'REGIONAL',
}
});
// Create API resource
const apiResource = new aws.apigateway.Resource('app-api-resource', {
restApi: api.id,
parentId: api.rootResourceId,
pathPart: '{proxy+}'
});
// Create API method
const apiMethod = new aws.apigateway.Method('app-api-method', {
restApi: api.id,
resourceId: apiResource.id,
httpMethod: 'ANY',
authorization: 'NONE'
});
// Create API integration
const apiIntegration = new aws.apigateway.Integration('app-api-integration', {
restApi: api.id,
resourceId: apiResource.id,
httpMethod: apiMethod.httpMethod,
integrationHttpMethod: 'POST',
type: 'AWS_PROXY',
uri: lambdaFunction.invokeArn
});
// Grant API Gateway permission to invoke Lambda
const lambdaPermission = new aws.lambda.Permission('app-api-lambda-permission', {
statementId: 'AllowAPIGatewayInvoke',
action: 'lambda:InvokeFunction',
function: lambdaFunction.name,
principal: 'apigateway.amazonaws.com',
sourceArn: pulumi.interpolate`arn:aws:execute-api:${aws.getRegion()}:${aws.getAccountId()}:${api.id}/*/*`
});
// Create CloudWatch Log Group for Lambda
const logGroup = new aws.cloudwatch.LogGroup('app-lambda-logs', {
name: pulumi.interpolate`/aws/lambda/${lambdaFunction.name}`,
retentionInDays: 14,
tags: {
Name: pulumi.interpolate`${lambdaFunction.name}-logs`,
Environment: environment
}
});
// Output values
export const bucketName = bucket.id;
export const bucketArn = bucket.arn;
export const apiEndpoint = pulumi.interpolate`https://${api.id}.execute-api.${aws.getRegion()}.amazonaws.com/prod`;
export const lambdaFunctionName = lambdaFunction.name;
export const logGroupName = logGroup.name;
// Cross-stack references example (optional)
if (environment === 'production') {
const prodStackRef = new pulumi.StackReference('organization/project/prod');
const prodApiStackRef = new pulumi.StackReference('organization/project/prod-api');
prodStackRef.getOutput('bucket_name').apply(name => {
console.log('Referenced prod bucket:', name);
});
prodApiStackRef.getOutput('api_endpoint').apply(endpoint => {
console.log('Referenced prod API endpoint:', endpoint);
});
}Pulumi with Python for Google Cloud
Deploying GCP infrastructure using Pulumi and Python
Difficulty
6/10
Estimated time
25 min
Tags
pulumi, python, gcp, cloud run, cloud sql
Prerequisites
Python, GCP project, Pulumi CLI
# Pulumi Python for Google Cloud Platform
import pulumi
import pulumi_gcp as gcp
# Get configuration
config = pulumi.Config()
stack_name = pulumi.get_stack()
environment = 'production' if stack_name == 'prod' else 'development'
project_id = config.require('project_id')
region = config.get('region', 'us-central1')
# Create GCP provider
gcp_provider = gcp.provider.Provider('gcp',
project=project_id,
region=region
)
# Create VPC network
vpc_network = gcp.compute.Network('app-vpc',
name=f'app-vpc-{stack_name}',
auto_create_subnetworks=False,
description=f'VPC for application in {environment}',
routing_mode='REGIONAL',
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
# Create subnets
public_subnet = gcp.compute.Subnetwork('app-public-subnet',
name=f'app-public-subnet-{stack_name}',
ip_cidr_range='10.0.1.0/24',
region=region,
network=vpc_network.id,
private_ip_google_access=False,
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
private_subnet = gcp.compute.Subnetwork('app-private-subnet',
name=f'app-private-subnet-{stack_name}',
ip_cidr_range='10.0.2.0/24',
region=region,
network=vpc_network.id,
private_ip_google_access=True,
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
# Create Cloud Storage bucket
bucket_suffix = pulumi.random.RandomString('bucket-suffix',
length=8,
special=False,
upper=False
).result
storage_bucket = gcp.storage.Bucket('app-storage-bucket',
name=bucket_suffix.apply(lambda suffix: f'app-storage-bucket-{stack_name}-{suffix}'),
location=region,
storage_class='STANDARD',
uniform_bucket_level_access=True,
versioning= {
'enabled': True
},
labels={
'environment': environment,
'managed-by': 'pulumi'
},
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
# Create Cloud SQL instance
sql_instance = gcp.sql.DatabaseInstance('app-sql-instance',
name=f'app-sql-instance-{stack_name}',
database_version='POSTGRES_14',
region=region,
settings={
'tier': 'db-g1-small',
'disk_size': 20,
'disk_type': 'PD_SSD',
'ip_configuration': {
'ipv4_enabled': False,
'private_network': vpc_network.id,
'authorized_networks': []
},
'backup_configuration': {
'enabled': True,
'binary_log_enabled': True
}
},
deletion_protection=False,
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
# Create SQL database
sql_database = gcp.sql.Database('app-sql-database',
name='app_database',
instance=sql_instance.name,
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
# Create Cloud Run service
cloud_run_service = gcp.cloudrun.Service('app-cloudrun-service',
name=f'app-service-{stack_name}',
location=region,
template={
'spec': {
'containers': [{
'image': 'gcr.io/cloudrun/hello:latest',
'ports': [{
'name': 'http1',
'containerPort': 8080
}],
'envs': [
{
'name': 'DATABASE_HOST',
'value': sql_instance.private_ip_address.apply(lambda ip: f'{ip}:5432')
},
{
'name': 'DATABASE_NAME',
'value': sql_database.name
},
{
'name': 'STORAGE_BUCKET',
'value': storage_bucket.name
},
{
'name': 'ENVIRONMENT',
'value': environment
}
]
}],
'container_concurrency': 80,
'timeout_seconds': 30
}
},
traffic=[{
'percent': 100,
'latest_revision': True
}],
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
# Create IAM policy for Cloud Run
cloud_run_iam = gcp.cloudrun.IamPolicy('app-cloudrun-iam',
location=region,
project=project_id,
bindings=[{
'role': 'roles/run.invoker',
'members': ['allUsers']
}],
cloudrun=cloud_run_service.name,
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
# Create Cloud Scheduler job
scheduler_job = gcp.cloudscheduler.Job('app-scheduler-job',
name=f'app-scheduler-{stack_name}',
description='Scheduled job for data processing',
schedule='0 2 * * *', # Daily at 2 AM
time_zone='America/Los_Angeles',
pubsub_target={
'topic_name': gcp.pubsub.Topic('app-topic',
name=f'app-topic-{stack_name}',
opts=pulumi.ResourceOptions(provider=gcp_provider)
).id.apply(lambda id: f'projects/{project_id}/topics/{id}'),
'data': '{"task": "daily_cleanup"}'
},
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
# Create Cloud Function for background processing
cloud_function = gcp.cloudfunctions.Function('app-background-function',
name=f'app-background-func-{stack_name}',
description='Background processing function',
runtime='python39',
available_memory_mb=256,
source_archive_bucket=storage_bucket.name,
source_archive_object=gcp.storage.BucketObject('function-source',
name='background-function.zip',
bucket=storage_bucket.name,
source=pulumi.FileArchive('./function-source'),
opts=pulumi.ResourceOptions(provider=gcp_provider)
).name,
entry_point='handler',
event_trigger={
'event_type': 'google.pubsub.topic.publish',
'resource': scheduler_job.pubsub_target.topic_name
},
opts=pulumi.ResourceOptions(provider=gcp_provider)
)
# Export values
pulumi.export('project_id', project_id)
pulumi.export('vpc_network_name', vpc_network.name)
pulumi.export('public_subnet_name', public_subnet.name)
pulumi.export('private_subnet_name', private_subnet.name)
pulumi.export('storage_bucket_name', storage_bucket.name)
pulumi.export('sql_instance_name', sql_instance.name)
pulumi.export('sql_database_name', sql_database.name)
pulumi.export('sql_instance_ip', sql_instance.private_ip_address)
pulumi.export('cloud_run_service_url', cloud_run_service.statuses[0].url)
pulumi.export('scheduler_job_name', scheduler_job.name)
pulumi.export('cloud_function_name', cloud_function.name)Pulumi with Go for Kubernetes
Deploying Kubernetes resources using Pulumi and Go
Difficulty
7/10
Estimated time
30 min
Tags
pulumi, go, kubernetes, helm, deployment
Prerequisites
Go programming, Kubernetes, Helm
// Pulumi Go for Kubernetes
package main
import (
"context"
"fmt"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apps/v1"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/networking/v1"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/rbac/v1"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Get configuration
config := ctx.NewConfig()
stackName := ctx.Stack()
environment := "development"
if stackName == "prod" {
environment = "production"
}
namespaceName := fmt.Sprintf("app-%s", stackName)
// Create Kubernetes provider
k8sProvider, err := kubernetes.NewProvider(ctx, "k8s", &kubernetes.ProviderArgs{
Kubeconfig: config.Get("kubeconfig"),
})
if err != nil {
return err
}
// Create namespace
namespace, err := v1.NewNamespace(ctx, "app-namespace", &v1.NamespaceArgs{
Metadata: &v1.ObjectMetaArgs{
Name: pulumi.String(namespaceName),
Labels: pulumi.StringMap{
"name": pulumi.String(namespaceName),
"environment": pulumi.String(environment),
"managed-by": pulumi.String("pulumi"),
},
},
}, pulumi.Provider(k8sProvider))
if err != nil {
return err
}
// Create ConfigMap for application configuration
appConfigMap, err := v1.NewConfigMap(ctx, "app-config", &v1.ConfigMapArgs{
Metadata: &v1.ObjectMetaArgs{
Name: pulumi.String("app-config"),
Namespace: namespace.Name,
},
Data: pulumi.StringMap{
"API_URL": pulumi.String("https://api.example.com"),
"LOG_LEVEL": pulumi.String("info"),
"REDIS_HOST": pulumi.String("redis-service"),
"REDIS_PORT": pulumi.String("6379"),
"DB_HOST": pulumi.String("postgres-service"),
"DB_PORT": pulumi.String("5432"),
"ENVIRONMENT": pulumi.String(environment),
},
}, pulumi.Provider(k8sProvider))
if err != nil {
return err
}
// Create Secret for sensitive data
appSecret, err := v1.NewSecret(ctx, "app-secret", &v1.SecretArgs{
Metadata: &v1.ObjectMetaArgs{
Name: pulumi.String("app-secret"),
Namespace: namespace.Name,
},
StringData: pulumi.StringMap{
"DB_PASSWORD": pulumi.String("changeme123!"),
"API_KEY": pulumi.String("secret-api-key"),
"JWT_SECRET": pulumi.String("jwt-secret-key"),
},
}, pulumi.Provider(k8sProvider))
if err != nil {
return err
}
// Create Redis deployment
redisDeployment, err := v1.NewDeployment(ctx, "redis-deployment", &v1.DeploymentArgs{
Metadata: &v1.ObjectMetaArgs{
Name: pulumi.String("redis"),
Namespace: namespace.Name,
Labels: pulumi.StringMap{
"app": pulumi.String("redis"),
"tier": pulumi.String("cache"),
},
},
Spec: &v1.DeploymentSpecArgs{
Replicas: pulumi.Int(1),
Selector: &v1.LabelSelectorArgs{
MatchLabels: pulumi.StringMap{
"app": pulumi.String("redis"),
},
},
Template: &v1.PodTemplateSpecArgs{
Metadata: &v1.ObjectMetaArgs{
Labels: pulumi.StringMap{
"app": pulumi.String("redis"),
},
},
Spec: &v1.PodSpecArgs{
Containers: v1.ContainerArray{
&v1.ContainerArgs{
Name: pulumi.String("redis"),
Image: pulumi.String("redis:7-alpine"),
Ports: v1.ContainerPortArray{
&v1.ContainerPortArgs{
ContainerPort: pulumi.Int(6379),
},
},
Resources: &v1.ResourceRequirementsArgs{
Requests: pulumi.StringMap{
"memory": pulumi.String("64Mi"),
"cpu": pulumi.String("250m"),
},
Limits: pulumi.StringMap{
"memory": pulumi.String("128Mi"),
"cpu": pulumi.String("500m"),
},
},
},
},
},
},
},
}, pulumi.Provider(k8sProvider))
if err != nil {
return err
}
// Create Redis service
redisService, err := v1.NewService(ctx, "redis-service", &v1.ServiceArgs{
Metadata: &v1.ObjectMetaArgs{
Name: pulumi.String("redis-service"),
Namespace: namespace.Name,
},
Spec: &v1.ServiceSpecArgs{
Selector: pulumi.StringMap{
"app": pulumi.String("redis"),
},
Ports: v1.ServicePortArray{
&v1.ServicePortArgs{
Port: pulumi.Int(6379),
TargetPort: pulumi.Int(6379),
},
},
},
}, pulumi.Provider(k8sProvider))
if err != nil {
return err
}
// Create application deployment
appDeployment, err := v1.NewDeployment(ctx, "app-deployment", &v1.DeploymentArgs{
Metadata: &v1.ObjectMetaArgs{
Name: pulumi.String("app"),
Namespace: namespace.Name,
Labels: pulumi.StringMap{
"app": pulumi.String("my-app"),
"tier": pulumi.String("frontend"),
},
},
Spec: &v1.DeploymentSpecArgs{
Replicas: pulumi.IntPtr(3),
Selector: &v1.LabelSelectorArgs{
MatchLabels: pulumi.StringMap{
"app": pulumi.String("my-app"),
},
},
Template: &v1.PodTemplateSpecArgs{
Metadata: &v1.ObjectMetaArgs{
Labels: pulumi.StringMap{
"app": pulumi.String("my-app"),
},
},
Spec: &v1.PodSpecArgs{
Containers: v1.ContainerArray{
&v1.ContainerArgs{
Name: pulumi.String("app"),
Image: pulumi.String("nginx:alpine"),
Ports: v1.ContainerPortArray{
&v1.ContainerPortArgs{
ContainerPort: pulumi.Int(80),
},
},
Env: v1.EnvVarArray{
&v1.EnvVarArgs{
Name: pulumi.String("ENVIRONMENT"),
Value: pulumi.String(environment),
},
},
Resources: &v1.ResourceRequirementsArgs{
Requests: pulumi.StringMap{
"memory": pulumi.String("64Mi"),
"cpu": pulumi.String("250m"),
},
Limits: pulumi.StringMap{
"memory": pulumi.String("128Mi"),
"cpu": pulumi.String("500m"),
},
},
ReadinessProbe: &v1.ProbeArgs{
HttpGet: &v1.HTTPGetActionArgs{
Path: pulumi.String("/"),
Port: pulumi.Int(80),
},
InitialDelaySeconds: pulumi.Int(5),
PeriodSeconds: pulumi.Int(10),
},
},
},
},
},
},
}, pulumi.Provider(k8sProvider))
if err != nil {
return err
}
// Create application service
appService, err := v1.NewService(ctx, "app-service", &v1.ServiceArgs{
Metadata: &v1.ObjectMetaArgs{
Name: pulumi.String("app-service"),
Namespace: namespace.Name,
},
Spec: &v1.ServiceSpecArgs{
Type: pulumi.String("LoadBalancer"),
Selector: pulumi.StringMap{
"app": pulumi.String("my-app"),
},
Ports: v1.ServicePortArray{
&v1.ServicePortArgs{
Port: pulumi.Int(80),
TargetPort: pulumi.Int(80),
},
},
},
}, pulumi.Provider(k8sProvider))
if err != nil {
return err
}
// Create Ingress for HTTP routing
appIngress, err := networkingv1.NewIngress(ctx, "app-ingress", &networkingv1.IngressArgs{
Metadata: &v1.ObjectMetaArgs{
Name: pulumi.String("app-ingress"),
Namespace: namespace.Name,
Annotations: pulumi.StringMap{
"kubernetes.io/ingress.class": pulumi.String("nginx"),
"cert-manager.io/cluster-issuer": pulumi.String("letsencrypt-prod"),
},
},
Spec: &networkingv1.IngressSpecArgs{
Tls: networkingv1.IngressTLSArray{
&networkingv1.IngressTLSArgs{
Hosts: pulumi.StringArray{
pulumi.String("app.example.com"),
},
SecretName: pulumi.String("app-tls"),
},
},
Rules: networkingv1.IngressRuleArray{
&networkingv1.IngressRuleArgs{
Host: pulumi.String("app.example.com"),
Http: &networkingv1.HTTPIngressRuleValueArgs{
Paths: networkingv1.HTTPIngressPathArray{
&networkingv1.HTTPIngressPathArgs{
Path: pulumi.String("/"),
PathType: pulumi.String("Prefix"),
Backend: &networkingv1.IngressBackendArgs{
Service: &networkingv1.IngressServiceBackendArgs{
Name: appService.Name,
Port: &networkingv1.ServiceBackendPortArgs{
Number: pulumi.Int(80),
},
},
},
},
},
},
},
},
},
}, pulumi.Provider(k8sProvider))
if err != nil {
return err
}
// Deploy Helm chart for monitoring (Prometheus)
prometheusChart, err := helmv3.NewRelease(ctx, "prometheus", &helmv3.ReleaseArgs{
Chart: pulumi.String("prometheus"),
Version: pulumi.String("25.8.0"),
Namespace: namespace.Name,
RepositoryOpts: &helmv3.RepositoryOptsArgs{
Repo: pulumi.String("https://prometheus-community.github.io/helm-charts"),
},
Values: pulumi.Map{
"server": pulumi.Map{
"persistentVolume": pulumi.Map{
"enabled": pulumi.Bool(false),
},
},
"alertmanager": pulumi.Map{
"enabled": pulumi.Bool(false),
},
},
}, pulumi.Provider(k8sProvider))
if err != nil {
return err
}
// Export outputs
ctx.Export("namespace_name", namespace.Name)
ctx.Export("redis_deployment_name", redisDeployment.Name)
ctx.Export("redis_service_name", redisService.Name)
ctx.Export("app_deployment_name", appDeployment.Name)
ctx.Export("app_service_name", appService.Name)
ctx.Export("app_load_balancer_ip", appService.Status.Apply(func(status *v1.ServiceStatus) *string {
if status.LoadBalancer != nil && len(status.LoadBalancer.Ingress) > 0 {
return status.LoadBalancer.Ingress[0].Ip
}
return pulumi.String("")
}))
ctx.Export("ingress_host", appIngress.Spec.Apply(func(spec *networkingv1.IngressSpec) string {
if len(spec.Rules) > 0 {
return *spec.Rules[0].Host
}
return ""
}))
ctx.Export("prometheus_release_name", prometheusChart.Name)
return nil
})
}Multi-Cloud Infrastructure with Pulumi
Deploying infrastructure across multiple cloud providers with Pulumi
Difficulty
9/10
Estimated time
45 min
Tags
pulumi, multi-cloud, aws, azure, gcp, hybrid
Prerequisites
Advanced Pulumi, Multiple cloud accounts, Cross-cloud networking
// Multi-Cloud Infrastructure with Pulumi
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';
// Configuration
const config = new pulumi.Config();
const stackName = pulumi.getStack();
const environment = stackName === 'prod' ? 'production' : 'development';
// AWS Configuration
const awsRegion = config.get('awsRegion', 'us-west-2');
const awsProvider = new aws.Provider('aws', {
region: awsRegion,
});
// Azure Configuration
const azureLocation = config.get('azureLocation', 'East US');
const azureResourceGroupName = pulumi.interpolate `rg-pulumi-multi-${stackName}`;
const azureResourceGroup = new azure.resources.ResourceGroup('azure-rg', {
resourceGroupName: azureResourceGroupName,
location: azureLocation,
tags: {
environment,
managedBy: 'pulumi'
}
});
// GCP Configuration
const gcpConfig = new gcp.Provider('gcp', {
project: config.require('gcpProjectId'),
region: config.get('gcpRegion', 'us-central1'),
});
// AWS Infrastructure
const awsVpc = new aws.ec2.Vpc('aws-vpc', {
cidrBlock: '10.0.0.0/16',
enableDnsHostnames: true,
enableDnsSupport: true,
tags: {
Name: pulumi.interpolate `pulumi-multi-${stackName}`,
Environment: environment
}
}, { provider: awsProvider });
const awsSubnet = new aws.ec2.Subnet('aws-subnet', {
vpcId: awsVpc.id,
cidrBlock: '10.0.1.0/24',
availabilityZone: pulumi.interpolate `${awsRegion}a`,
mapPublicIpOnLaunch: true,
tags: {
Name: pulumi.interpolate `pulumi-multi-${stackName}-subnet`,
Environment: environment
}
}, { provider: awsProvider });
const awsSecurityGroup = new aws.ec2.SecurityGroup('aws-sg', {
vpcId: awsVpc.id,
ingress: [
{
protocol: 'tcp',
fromPort: 22,
toPort: 22,
cidrBlocks: ['0.0.0.0/0'],
description: 'SSH'
},
{
protocol: 'tcp',
fromPort: 80,
toPort: 80,
cidrBlocks: ['0.0.0.0/0'],
description: 'HTTP'
}
],
egress: [{
protocol: '-1',
fromPort: 0,
toPort: 0,
cidrBlocks: ['0.0.0.0/0']
}],
tags: {
Name: pulumi.interpolate `pulumi-multi-${stackName}-sg`,
Environment: environment
}
}, { provider: awsProvider });
// AWS Lambda function
const awsLambda = new aws.lambda.Function('aws-lambda', {
name: pulumi.interpolate `pulumi-multi-${stackName}-function`,
runtime: 'nodejs18.x',
handler: 'index.handler',
role: aws.iam.getRoleDocument('lambda-role-doc', {
assumeRolePolicy: JSON.stringify({
Version: '2012-10-17',
Statement: [{
Action: 'sts:AssumeRole',
Effect: 'Allow',
Principal: { Service: 'lambda.amazonaws.com' }
}]
})
}).then(doc => new aws.iam.Role('aws-lambda-role', {
assumeRolePolicy: doc.json,
name: pulumi.interpolate `pulumi-multi-${stackName}-lambda-role`
}, { provider: awsProvider }).arn),
code: new pulumi.asset.AssetArchive({
'index.js': new pulumi.asset.StringAsset(`
exports.handler = async (event) => {
return {
statusCode: 200,
body: JSON.stringify({
message: 'Hello from AWS Lambda!',
cloud: 'AWS',
region: process.env.AWS_REGION,
timestamp: new Date().toISOString()
})
};
};
`)
}),
environment: {
variables: {
ENVIRONMENT: environment
}
},
tags: {
Name: pulumi.interpolate `pulumi-multi-${stackName}-lambda`,
Environment: environment
}
}, { provider: awsProvider });
// Azure Infrastructure
const azureVirtualNetwork = new azure.network.VirtualNetwork('azure-vnet', {
virtualNetworkName: pulumi.interpolate `pulumi-multi-${stackName}-vnet`,
resourceGroupName: azureResourceGroup.name,
location: azureLocation,
addressSpace: {
addressPrefixes: ['10.1.0.0/16']
},
tags: {
environment,
managedBy: 'pulumi'
}
});
const azureSubnet = new azure.network.Subnet('azure-subnet', {
subnetName: pulumi.interpolate `pulumi-multi-${stackName}-subnet`,
resourceGroupName: azureResourceGroup.name,
virtualNetworkName: azureVirtualNetwork.name,
addressPrefix: '10.1.1.0/24',
privateEndpointNetworkPolicies: 'Disabled',
privateLinkServiceNetworkPolicies: 'Enabled'
});
const azureNetworkSecurityGroup = new azure.network.NetworkSecurityGroup('azure-nsg', {
networkSecurityGroupName: pulumi.interpolate `pulumi-multi-${stackName}-nsg`,
resourceGroupName: azureResourceGroup.name,
location: azureLocation,
securityRules: [
{
name: 'AllowSSH',
priority: 1000,
direction: 'Inbound',
access: 'Allow',
protocol: 'Tcp',
sourcePortRange: '*',
destinationPortRange: '22',
sourceAddressPrefix: '*',
destinationAddressPrefix: '*'
},
{
name: 'AllowHTTP',
priority: 1001,
direction: 'Inbound',
access: 'Allow',
protocol: 'Tcp',
sourcePortRange: '*',
destinationPortRange: '80',
sourceAddressPrefix: '*',
destinationAddressPrefix: '*'
}
]
});
// Azure Function App
const azureStorageAccount = new azure.storage.StorageAccount('azure-storage', {
accountName: pulumi.random.RandomString('storage-suffix', {
length: 8,
special: false,
upper: false
}).result.apply(suffix => `pulumi${suffix}`),
resourceGroupName: azureResourceGroup.name,
location: azureLocation,
kind: 'StorageV2',
sku: {
name: azure.storage.SkuName.Standard_LRS
},
tags: {
environment,
managedBy: 'pulumi'
}
});
const azureFunctionApp = new azure.web.WebApp('azure-function', {
name: pulumi.interpolate `pulumi-multi-${stackName}-function`,
resourceGroupName: azureResourceGroup.name,
location: azureLocation,
kind: 'functionapp',
serverFarmId: new azure.web.AppServicePlan('azure-app-service-plan', {
name: pulumi.interpolate `pulumi-multi-${stackName}-asp`,
resourceGroupName: azureResourceGroup.name,
location: azureLocation,
sku: {
name: azure.web.SkuName.Basic,
tier: azure.web.SkuTier.Basic,
size: 'B1'
},
kind: 'linux',
reserved: true
}).id,
siteConfig: {
linuxFxVersion: 'NODE|18-lts',
appSettings: [
{
name: 'WEBSITE_RUN_FROM_PACKAGE',
value: '1'
},
{
name: 'FUNCTIONS_WORKER_RUNTIME',
value: 'node'
},
{
name: 'ENVIRONMENT',
value: environment
},
{
name: 'AzureWebJobsStorage',
value: azureStorageAccount.primaryConnectionString
}
]
},
tags: {
environment,
managedBy: 'pulumi'
}
});
// GCP Infrastructure
const gcpVpcNetwork = new gcp.compute.Network('gcp-vpc', {
name: pulumi.interpolate `pulumi-multi-${stackName}-vnet`,
autoCreateSubnetworks: false,
description: pulumi.interpolate `VPC for Pulumi multi-cloud demo in ${environment}`,
routingMode: 'REGIONAL',
tags: {
environment,
managedBy: 'pulumi'
}
}, { provider: gcpConfig });
const gcpSubnet = new gcp.compute.Subnetwork('gcp-subnet', {
name: pulumi.interpolate `pulumi-multi-${stackName}-subnet`,
ipCidrRange: '10.2.1.0/24',
region: config.get('gcpRegion', 'us-central1'),
network: gcpVpcNetwork.id,
privateIpGoogleAccess: false,
tags: {
environment,
managedBy: 'pulumi'
}
}, { provider: gcpConfig });
const gcpFirewall = new gcp.compute.Firewall('gcp-firewall', {
name: pulumi.interpolate `pulumi-multi-${stackName}-fw`,
network: gcpVpcNetwork.id,
allow: [{
protocol: 'tcp',
ports: ['22', '80']
}],
sourceRanges: ['0.0.0.0/0'],
description: 'Allow SSH and HTTP traffic',
tags: {
environment,
managedBy: 'pulumi'
}
}, { provider: gcpConfig });
// GCP Cloud Function
const gcpBucketSuffix = pulumi.random.RandomString('gcp-bucket-suffix', {
length: 8,
special: false,
upper: false
}).result;
const gcpBucket = new gcp.storage.Bucket('gcp-function-bucket', {
name: gcpBucketSuffix.apply(suffix => `pulumi-multi-${stackName}-bucket-${suffix}`),
location: config.get('gcpRegion', 'US-CENTRAL1'),
forceDestroy: true,
uniformBucketLevelAccess: true,
tags: {
environment,
managedBy: 'pulumi'
}
}, { provider: gcpConfig });
const gcpFunctionArchive = new gcp.storage.BucketObject('gcp-function-zip', {
name: 'function.zip',
bucket: gcpBucket.name,
source: new pulumi.asset.AssetArchive({
'index.js': new pulumi.asset.StringAsset(`
exports.handler = async (req, res) => {
res.status(200).json({
message: 'Hello from GCP Cloud Function!',
cloud: 'GCP',
region: process.env.FUNCTION_REGION,
timestamp: new Date().toISOString()
});
};
`)
})
}, { provider: gcpConfig });
const gcpFunction = new gcp.cloudfunctions.Function('gcp-function', {
name: pulumi.interpolate `pulumi-multi-${stackName}-function`,
description: pulumi.interpolate `Pulumi multi-cloud demo function in ${environment}`,
runtime: 'nodejs18',
entryPoint: 'handler',
sourceArchiveBucket: gcpBucket.name,
sourceArchiveObject: gcpFunctionArchive.name,
triggerHttp: true,
availableMemoryMb: 256,
timeout: 60,
environmentVariables: {
ENVIRONMENT: environment
},
tags: {
environment,
managedBy: 'pulumi'
}
}, { provider: gcpConfig });
// Enable Cloud Function invocations
const gcpFunctionIAM = new gcp.cloudfunctions.FunctionIamPolicy('gcp-function-iam', {
region: gcpFunction.region,
cloudFunction: gcpFunction.name,
bindings: [{
role: 'roles/cloudfunctions.invoker',
members: ['allUsers']
}]
}, { provider: gcpConfig });
// Cross-Cloud Networking (VPN connections would go here)
// This is a simplified example - in production you'd set up VPN tunnels or Direct Connect
// Monitoring Integration (using a centralized monitoring solution)
const monitoringConfig = {
aws: {
lambdaName: awsLambda.name,
region: awsRegion
},
azure: {
functionName: azureFunctionApp.name,
resourceGroup: azureResourceGroup.name
},
gcp: {
functionName: gcpFunction.name,
region: config.get('gcpRegion', 'us-central1')
}
};
// Export outputs
export const awsInfrastructure = {
vpcId: awsVpc.id,
subnetId: awsSubnet.id,
lambdaFunctionName: awsLambda.name,
lambdaArn: awsLambda.arn
};
export const azureInfrastructure = {
resourceGroupName: azureResourceGroup.name,
vnetName: azureVirtualNetwork.name,
subnetName: azureSubnet.name,
functionName: azureFunctionApp.name,
functionUrl: azureFunctionApp.defaultHostName
};
export const gcpInfrastructure = {
vpcName: gcpVpcNetwork.name,
subnetName: gcpSubnet.name,
functionName: gcpFunction.name,
functionUrl: gcpFunction.httpsTriggerUrl
};
export const monitoringSetup = monitoringConfig;
// Additional exports for easy access
pulumi.export('aws_lambda_name', awsLambda.name);
pulumi.export('azure_function_name', azureFunctionApp.name);
pulumi.export('gcp_function_name', gcpFunction.name);
pulumi.export('gcp_function_url', gcpFunction.httpsTriggerUrl);
// Stack outputs for monitoring dashboard
pulumi.export('dashboard_config', pulumi.all([
awsLambda.name,
azureFunctionApp.name,
gcpFunction.name
]).apply(([awsName, azureName, gcpName]) => JSON.stringify({
environment,
services: {
aws: awsName,
azure: azureName,
gcp: gcpName
},
monitoring: {
enabled: true,
providers: ['cloudwatch', 'azure-monitor', 'cloud-monitoring']
}
})));Tools
Tools frequently paired with this sample
Related