Skip to content

Commit

Permalink
Added multi-language build lambda
Browse files Browse the repository at this point in the history
Uses docker build provider to install dependencies and compile where necessary
  • Loading branch information
pierskarsenbarg committed Jul 31, 2024
1 parent 31e3fe5 commit dbac2b3
Show file tree
Hide file tree
Showing 21 changed files with 364 additions and 0 deletions.
3 changes: 3 additions & 0 deletions aws-ts-multi-language-lambda/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/bin/
node_modules
dist
10 changes: 10 additions & 0 deletions aws-ts-multi-language-lambda/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: aws-ts-multi-language-lambda
runtime:
name: nodejs
options:
packagemanager: npm
description: A minimal AWS TypeScript Pulumi program
config:
pulumi:tags:
value:
pulumi:template: aws-typescript
27 changes: 27 additions & 0 deletions aws-ts-multi-language-lambda/README.md
Original file line number Diff line number Diff line change
@@ -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.
30 changes: 30 additions & 0 deletions aws-ts-multi-language-lambda/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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
}
];
21 changes: 21 additions & 0 deletions aws-ts-multi-language-lambda/dotnet-lambda/Dockerfile
Original file line number Diff line number Diff line change
@@ -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 .
12 changes: 12 additions & 0 deletions aws-ts-multi-language-lambda/dotnet-lambda/DotnetLambda.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Amazon.Lambda.Core" Version="2.2.0" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.1" />
</ItemGroup>
</Project>
23 changes: 23 additions & 0 deletions aws-ts-multi-language-lambda/dotnet-lambda/Function.cs
Original file line number Diff line number Diff line change
@@ -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
{

/// <summary>
/// A simple function that takes a string and does a ToUpper
/// </summary>
/// <param name="input">The event for the Lambda function handler to process.</param>
/// <param name="context">The ILambdaContext that provides methods for logging and describing the Lambda environment.</param>
/// <returns></returns>
public string FunctionHandler(ILambdaContext context)
{
return "Pulumi <3 .NET Lambda";
}
}
21 changes: 21 additions & 0 deletions aws-ts-multi-language-lambda/go-lambda/Dockerfile
Original file line number Diff line number Diff line change
@@ -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 .
5 changes: 5 additions & 0 deletions aws-ts-multi-language-lambda/go-lambda/go.mod
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions aws-ts-multi-language-lambda/go-lambda/go.sum
Original file line number Diff line number Diff line change
@@ -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=
19 changes: 19 additions & 0 deletions aws-ts-multi-language-lambda/go-lambda/main.go
Original file line number Diff line number Diff line change
@@ -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)
}
63 changes: 63 additions & 0 deletions aws-ts-multi-language-lambda/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as dockerBuild from "@pulumi/docker-build";
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"];
let lambdaNames: {[key: string]: pulumi.Output<string>} = {};
// let lambdaNames: pulumi.Output<string>[] = [];

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
};
17 changes: 17 additions & 0 deletions aws-ts-multi-language-lambda/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
12 changes: 12 additions & 0 deletions aws-ts-multi-language-lambda/python-lambda/Dockerfile
Original file line number Diff line number Diff line change
@@ -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/ .
2 changes: 2 additions & 0 deletions aws-ts-multi-language-lambda/python-lambda/lambda.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def handler(event, context):
return "Pulumi <3 Python Lambda"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
art==6.1
18 changes: 18 additions & 0 deletions aws-ts-multi-language-lambda/tsconfig.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
23 changes: 23 additions & 0 deletions aws-ts-multi-language-lambda/typescript-lambda/Dockerfile
Original file line number Diff line number Diff line change
@@ -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 .
3 changes: 3 additions & 0 deletions aws-ts-multi-language-lambda/typescript-lambda/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const handler = async (input: string) => {
return "Pulumi <3 Typescript Lambda";
}
16 changes: 16 additions & 0 deletions aws-ts-multi-language-lambda/typescript-lambda/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
16 changes: 16 additions & 0 deletions aws-ts-multi-language-lambda/typescript-lambda/tsconfig.json
Original file line number Diff line number Diff line change
@@ -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"]
}

0 comments on commit dbac2b3

Please sign in to comment.