diff --git a/aws-ts-multi-language-lambda/.gitignore b/aws-ts-multi-language-lambda/.gitignore
new file mode 100644
index 000000000..e9a7d1d56
--- /dev/null
+++ b/aws-ts-multi-language-lambda/.gitignore
@@ -0,0 +1,3 @@
+/bin/
+node_modules
+dist
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/Pulumi.yaml b/aws-ts-multi-language-lambda/Pulumi.yaml
new file mode 100644
index 000000000..b879bb889
--- /dev/null
+++ b/aws-ts-multi-language-lambda/Pulumi.yaml
@@ -0,0 +1,10 @@
+name: aws-ts-multi-language-lambda
+runtime:
+ name: nodejs
+ options:
+ packagemanager: npm
+description: Pulumi program to demonstrate how to install dependencies and package up code for deployment to AWS Lambda functions
+config:
+ pulumi:tags:
+ value:
+ pulumi:template: aws-typescript
diff --git a/aws-ts-multi-language-lambda/README.md b/aws-ts-multi-language-lambda/README.md
new file mode 100644
index 000000000..1669cb7bb
--- /dev/null
+++ b/aws-ts-multi-language-lambda/README.md
@@ -0,0 +1,27 @@
+# Building and bundling Lambda dependencies
+
+This example shows how to install dependencies and build multiple Lambda functions in different languages and then deploy the results.
+
+## Deploying the Lambda functions
+
+To deploy the infrastructure, follow the steps below:
+
+### Prerequisites
+
+1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/)
+1. [Install NodeJS](https://www.pulumi.com/docs/clouds/aws/get-started/begin/#install-language-runtime)
+1. [Install Docker](https://docs.docker.com/engine/install/)
+1. [Configure AWS Credentials](https://www.pulumi.com/docs/clouds/aws/get-started/begin/#configure-pulumi-to-access-your-aws-account)
+
+You don't need to install any languages other than NodeJS because we'll use Docker containers to build the code.
+
+### Steps
+
+1. Clone this repo: `git clone https://github.com/pulumi/examples`
+1. Change directory to the correct folder: `cd examples/aws-ts-multi-language-lambda`
+1. Install all required packages: `pulumi install`
+1. Run `pulumi up`
+
+Once all the resources have deployed, you can run the lambdas and see the outputs.
+
+Don't forget to run `pulumi destroy` when you're done to delete the resources.
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/config.ts b/aws-ts-multi-language-lambda/config.ts
new file mode 100644
index 000000000..d266c7e9a
--- /dev/null
+++ b/aws-ts-multi-language-lambda/config.ts
@@ -0,0 +1,32 @@
+// Copyright 2016-2024, Pulumi Corporation. All rights reserved.
+
+import { Runtime } from "@pulumi/aws/lambda";
+
+interface Config {
+ language: string;
+ handler: string;
+ runtime: Runtime;
+}
+
+export const lambdaSetup: Config[] = [
+ {
+ language: "dotnet",
+ handler: "DotnetLambda::Lambda.Function::FunctionHandler",
+ runtime: Runtime.Dotnet8,
+ },
+ {
+ language: "go",
+ handler: "bootstrap",
+ runtime: Runtime.CustomAL2023,
+ },
+ {
+ language: "typescript",
+ handler: "index.handler",
+ runtime: Runtime.NodeJS20dX,
+ },
+ {
+ language: "python",
+ handler: "lambda.handler",
+ runtime: Runtime.Python3d12,
+ },
+];
diff --git a/aws-ts-multi-language-lambda/dotnet-lambda/Dockerfile b/aws-ts-multi-language-lambda/dotnet-lambda/Dockerfile
new file mode 100644
index 000000000..d0b3be921
--- /dev/null
+++ b/aws-ts-multi-language-lambda/dotnet-lambda/Dockerfile
@@ -0,0 +1,21 @@
+FROM mcr.microsoft.com/dotnet/sdk AS base
+
+WORKDIR /app
+
+FROM base AS restore
+
+COPY *.csproj .
+
+RUN dotnet restore
+
+FROM base AS builder
+
+COPY --from=restore /app/*.csproj /app
+COPY --from=restore /app/obj /app/obj
+COPY Function.cs /app
+
+RUN dotnet publish . -o dist
+
+FROM scratch
+
+COPY --from=builder /app/dist .
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/dotnet-lambda/DotnetLambda.csproj b/aws-ts-multi-language-lambda/dotnet-lambda/DotnetLambda.csproj
new file mode 100644
index 000000000..89e586816
--- /dev/null
+++ b/aws-ts-multi-language-lambda/dotnet-lambda/DotnetLambda.csproj
@@ -0,0 +1,12 @@
+
+
+ net8.0
+ enable
+ enable
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/dotnet-lambda/Function.cs b/aws-ts-multi-language-lambda/dotnet-lambda/Function.cs
new file mode 100644
index 000000000..6183b1bfd
--- /dev/null
+++ b/aws-ts-multi-language-lambda/dotnet-lambda/Function.cs
@@ -0,0 +1,23 @@
+using Amazon.Lambda.Core;
+using System;
+
+
+// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
+[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
+
+namespace Lambda;
+
+public class Function
+{
+
+ ///
+ /// A simple function that takes a string and does a ToUpper
+ ///
+ /// The event for the Lambda function handler to process.
+ /// The ILambdaContext that provides methods for logging and describing the Lambda environment.
+ ///
+ public string FunctionHandler(ILambdaContext context)
+ {
+ return "Pulumi <3 .NET Lambda";
+ }
+}
diff --git a/aws-ts-multi-language-lambda/go-lambda/Dockerfile b/aws-ts-multi-language-lambda/go-lambda/Dockerfile
new file mode 100644
index 000000000..49611ae64
--- /dev/null
+++ b/aws-ts-multi-language-lambda/go-lambda/Dockerfile
@@ -0,0 +1,21 @@
+FROM golang:1.22.5-alpine AS base
+
+WORKDIR /app
+RUN apk --no-cache add zip
+
+FROM base AS modules
+
+COPY go.* .
+COPY main.go .
+RUN go mod tidy
+
+FROM base AS builder
+
+COPY --from=modules /app/ /app/
+COPY --from=modules /go/pkg/mod/ /go/pkg/mod
+
+RUN GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o bootstrap main.go
+
+FROM scratch
+
+COPY --from=builder /app/bootstrap .
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/go-lambda/go.mod b/aws-ts-multi-language-lambda/go-lambda/go.mod
new file mode 100644
index 000000000..a3b92ab40
--- /dev/null
+++ b/aws-ts-multi-language-lambda/go-lambda/go.mod
@@ -0,0 +1,5 @@
+module github.com/pulumi/examples/aws-ts-multi-language-lambda/go-lambda
+
+go 1.22.1
+
+require github.com/aws/aws-lambda-go v1.47.0
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/go-lambda/go.sum b/aws-ts-multi-language-lambda/go-lambda/go.sum
new file mode 100644
index 000000000..3ee35928b
--- /dev/null
+++ b/aws-ts-multi-language-lambda/go-lambda/go.sum
@@ -0,0 +1,22 @@
+github.com/Code-Hex/Neo-cowsay/v2 v2.0.4 h1:y80Hd9hmB+rsEH/p4c5ti5PbO0PhBmxw4NgbpFZvoHg=
+github.com/Code-Hex/Neo-cowsay/v2 v2.0.4/go.mod h1:6k40Pwrc2FazLf1BUbmAC36E9LvT+DErjZr30isbXhg=
+github.com/Code-Hex/go-wordwrap v1.0.0 h1:yl5fLyZEz3+hPGbpTRlTQ8mQJ1HXWcTq1FCNR1ch6zM=
+github.com/Code-Hex/go-wordwrap v1.0.0/go.mod h1:/SsbgkY2Q0aPQRyvXcyQwWYTQOIwSORKe6MPjRVGIWU=
+github.com/aws/aws-lambda-go v1.47.0 h1:0H8s0vumYx/YKs4sE7YM0ktwL2eWse+kfopsRI1sXVI=
+github.com/aws/aws-lambda-go v1.47.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
+github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
+github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/aws-ts-multi-language-lambda/go-lambda/main.go b/aws-ts-multi-language-lambda/go-lambda/main.go
new file mode 100644
index 000000000..14cb032da
--- /dev/null
+++ b/aws-ts-multi-language-lambda/go-lambda/main.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "context"
+
+ "github.com/aws/aws-lambda-go/lambda"
+)
+
+type MyEvent struct {
+ Name string `json:"name"`
+}
+
+func HandleRequest(ctx context.Context) (string, error) {
+ return "Pulumi <3 Go Lambda", nil
+}
+
+func main() {
+ lambda.Start(HandleRequest)
+}
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/index.ts b/aws-ts-multi-language-lambda/index.ts
new file mode 100644
index 000000000..931ce6d7d
--- /dev/null
+++ b/aws-ts-multi-language-lambda/index.ts
@@ -0,0 +1,61 @@
+// Copyright 2016-2024, Pulumi Corporation. All rights reserved.
+
+
+import * as aws from "@pulumi/aws";
+import * as dockerBuild from "@pulumi/docker-build";
+import * as pulumi from "@pulumi/pulumi";
+import { lambdaSetup } from "./config";
+
+export = async () => {
+ const role = new aws.iam.Role("lambdarole", {
+ assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal(aws.iam.Principals.LambdaPrincipal),
+ managedPolicyArns: [
+ aws.iam.ManagedPolicies.AWSLambdaBasicExecutionRole,
+ ],
+ });
+
+ const languages = ["dotnet", "go", "python", "typescript"];
+ const lambdaNames: {[key: string]: pulumi.Output} = {};
+
+ lambdaSetup.map((lambda) => {
+ const buildLambdaCode = new dockerBuild.Image(
+ `${lambda.language}-build-code`,
+ {
+ push: false,
+ context: {
+ location: `./${lambda.language}-lambda`,
+ },
+ dockerfile: {
+ location: `./${lambda.language}-lambda/Dockerfile`,
+ },
+ exports: [
+ {
+ local: {
+ dest: `./dist/${lambda.language}`,
+ },
+ },
+ ],
+ labels: {
+ created: new Date().getTime().toString(),
+ },
+ },
+ );
+
+ const fn = new aws.lambda.Function(
+ `${lambda.language}-lambda`,
+ {
+ role: role.arn,
+ code: new pulumi.asset.AssetArchive({
+ ".": new pulumi.asset.FileArchive(`./dist/${lambda.language}`),
+ }),
+ runtime: lambda.runtime,
+ handler: lambda.handler,
+ },
+ { dependsOn: [buildLambdaCode] },
+ );
+
+ lambdaNames[`lambdaNames.${lambda.language}`] = fn.name;
+ });
+
+ return lambdaNames;
+};
diff --git a/aws-ts-multi-language-lambda/package.json b/aws-ts-multi-language-lambda/package.json
new file mode 100644
index 000000000..c86a60594
--- /dev/null
+++ b/aws-ts-multi-language-lambda/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "aws-multi-language-lambda-ts",
+ "main": "index.ts",
+ "devDependencies": {
+ "@types/node": "^18",
+ "typescript": "^5.0.0"
+ },
+ "dependencies": {
+ "@pulumi/aws": "^6.0.0",
+ "@pulumi/awsx": "^2.0.2",
+ "@pulumi/docker-build": "^0.0.4",
+ "@pulumi/pulumi": "^3.113.0"
+ },
+ "scripts": {
+ "deploy": "rm -rf ./dist && pulumi up -f"
+ }
+}
diff --git a/aws-ts-multi-language-lambda/python-lambda/Dockerfile b/aws-ts-multi-language-lambda/python-lambda/Dockerfile
new file mode 100644
index 000000000..d16489b88
--- /dev/null
+++ b/aws-ts-multi-language-lambda/python-lambda/Dockerfile
@@ -0,0 +1,12 @@
+FROM python:3.12.4-alpine AS base
+
+WORKDIR /app
+
+FROM base AS packages
+
+COPY requirements.txt .
+RUN pip install -r requirements.txt --target ./package
+
+FROM scratch
+COPY lambda.py .
+COPY --from=packages /app/package/ .
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/python-lambda/lambda.py b/aws-ts-multi-language-lambda/python-lambda/lambda.py
new file mode 100644
index 000000000..3d5461b93
--- /dev/null
+++ b/aws-ts-multi-language-lambda/python-lambda/lambda.py
@@ -0,0 +1,2 @@
+def handler(event, context):
+ return "Pulumi <3 Python Lambda"
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/python-lambda/requirements.txt b/aws-ts-multi-language-lambda/python-lambda/requirements.txt
new file mode 100644
index 000000000..432b43c18
--- /dev/null
+++ b/aws-ts-multi-language-lambda/python-lambda/requirements.txt
@@ -0,0 +1 @@
+art==6.1
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/tsconfig.json b/aws-ts-multi-language-lambda/tsconfig.json
new file mode 100644
index 000000000..f960d5171
--- /dev/null
+++ b/aws-ts-multi-language-lambda/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "strict": true,
+ "outDir": "bin",
+ "target": "es2020",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "experimentalDecorators": true,
+ "pretty": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitReturns": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "index.ts"
+ ]
+}
diff --git a/aws-ts-multi-language-lambda/typescript-lambda/Dockerfile b/aws-ts-multi-language-lambda/typescript-lambda/Dockerfile
new file mode 100644
index 000000000..774b524c7
--- /dev/null
+++ b/aws-ts-multi-language-lambda/typescript-lambda/Dockerfile
@@ -0,0 +1,23 @@
+FROM node:alpine AS base
+WORKDIR /app
+
+FROM base AS install
+
+RUN mkdir -p /tmp/install
+COPY package*.json /tmp/install
+RUN cd /tmp/install && npm ci
+
+FROM base AS build
+
+COPY --from=install /tmp/install/node_modules node_modules
+COPY --from=install /tmp/install/package*.json .
+COPY index.ts .
+COPY tsconfig.json .
+
+RUN npx tsc index.ts
+
+FROM scratch
+
+COPY --from=install /tmp/install/node_modules node_modules
+COPY --from=install /tmp/install/package*.json .
+COPY --from=build /app/index.js .
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/typescript-lambda/index.ts b/aws-ts-multi-language-lambda/typescript-lambda/index.ts
new file mode 100644
index 000000000..9e2c8ca67
--- /dev/null
+++ b/aws-ts-multi-language-lambda/typescript-lambda/index.ts
@@ -0,0 +1,3 @@
+export const handler = async (input: string) => {
+ return "Pulumi <3 Typescript Lambda";
+}
\ No newline at end of file
diff --git a/aws-ts-multi-language-lambda/typescript-lambda/package.json b/aws-ts-multi-language-lambda/typescript-lambda/package.json
new file mode 100644
index 000000000..a1c800e18
--- /dev/null
+++ b/aws-ts-multi-language-lambda/typescript-lambda/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "lambda",
+ "version": "1.0.0",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "description": "",
+ "devDependencies": {
+ "@types/node": "^22.0.0",
+ "typescript": "^5.5.4"
+ }
+}
diff --git a/aws-ts-multi-language-lambda/typescript-lambda/tsconfig.json b/aws-ts-multi-language-lambda/typescript-lambda/tsconfig.json
new file mode 100644
index 000000000..460e272e7
--- /dev/null
+++ b/aws-ts-multi-language-lambda/typescript-lambda/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "compilerOptions": {
+ "target": "es2020",
+ "strict": true,
+ "preserveConstEnums": true,
+ "noEmit": true,
+ "sourceMap": false,
+ "module":"commonjs",
+ "moduleResolution":"node",
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "isolatedModules": true,
+ },
+ "exclude": ["node_modules"]
+ }
\ No newline at end of file