Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added multi-language build lambda #1674

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
pierskarsenbarg marked this conversation as resolved.
Show resolved Hide resolved
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.
32 changes: 32 additions & 0 deletions aws-ts-multi-language-lambda/config.ts
Original file line number Diff line number Diff line change
@@ -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,
},
];
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)
}
61 changes: 61 additions & 0 deletions aws-ts-multi-language-lambda/index.ts
Original file line number Diff line number Diff line change
@@ -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<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"]
}
Loading