Adding example for AWS SAM
This commit is contained in:
parent
efecce8736
commit
18ca3735ea
|
|
@ -0,0 +1,207 @@
|
||||||
|
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/osx,node,linux,windows,sam
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=osx,node,linux,windows,sam
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### Node ###
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Storybook build outputs
|
||||||
|
.out
|
||||||
|
.storybook-out
|
||||||
|
storybook-static
|
||||||
|
|
||||||
|
# rollup.js default build output
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# Temporary folders
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
|
||||||
|
### OSX ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### SAM ###
|
||||||
|
# Ignore build directories for the AWS Serverless Application Model (SAM)
|
||||||
|
# Info: https://aws.amazon.com/serverless/sam/
|
||||||
|
# Docs: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-reference.html
|
||||||
|
|
||||||
|
**/.aws-sam
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/osx,node,linux,windows,sam
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
# aws-sam-example
|
||||||
|
|
||||||
|
This project is an example of using chromium inside aws sam written from sam init Hello World template with nodeJS 16 as runtime.
|
||||||
|
|
||||||
|
### Changes from hello world template
|
||||||
|
|
||||||
|
- Installed puppeteer and @sparticuz/chromium
|
||||||
|
- Note: it must not be in dev-dependencies
|
||||||
|
- Modified the handler to instantiate the browser pointing to the AWS layer directory (`/opt/nodejs/node_modules/@sparticuz/chromium/bin`)
|
||||||
|
- Added layer in template and fixed timeout and
|
||||||
|
- Running same example as README
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
You must create a layer with the chromium binary and replace its arn inside `template.yaml`. You can see an example on how to create it in the main project README.
|
||||||
|
|
||||||
|
### Running
|
||||||
|
|
||||||
|
Build and invoke the function.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sam build
|
||||||
|
sam local invoke
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
.aws-sam
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
module.exports = {
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
|
||||||
|
sourceType: "module"
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
"plugin:@typescript-eslint/recommended", // recommended rules from the @typescript-eslint/eslint-plugin
|
||||||
|
"plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
|
||||||
|
// e.g. "@typescript-eslint/explicit-function-return-type": "off",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
tests/*
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
module.exports = {
|
||||||
|
semi: true,
|
||||||
|
trailingComma: "all",
|
||||||
|
singleQuote: true,
|
||||||
|
printWidth: 120,
|
||||||
|
tabWidth: 4
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
|
||||||
|
import chromium from '@sparticuz/chromium';
|
||||||
|
import puppeteer from 'puppeteer-core';
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
|
||||||
|
* @param {Object} event - API Gateway Lambda Proxy Input Format
|
||||||
|
*
|
||||||
|
* Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
|
||||||
|
* @returns {Object} object - API Gateway Lambda Proxy Output Format
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
|
||||||
|
const browser = await puppeteer.launch({
|
||||||
|
args: chromium.args,
|
||||||
|
defaultViewport: chromium.defaultViewport,
|
||||||
|
executablePath: await chromium.executablePath('/opt/nodejs/node_modules/@sparticuz/chromium/bin'),
|
||||||
|
headless: chromium.headless,
|
||||||
|
ignoreHTTPSErrors: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const page = await browser.newPage();
|
||||||
|
await page.goto("https://example.com");
|
||||||
|
const pageTitle = await page.title();
|
||||||
|
await browser.close();
|
||||||
|
let response: APIGatewayProxyResult;
|
||||||
|
|
||||||
|
try {
|
||||||
|
response = {
|
||||||
|
statusCode: 200,
|
||||||
|
body: JSON.stringify({
|
||||||
|
message: pageTitle,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
} catch (err: unknown) {
|
||||||
|
console.error(err);
|
||||||
|
response = {
|
||||||
|
statusCode: 500,
|
||||||
|
body: JSON.stringify({
|
||||||
|
message: err instanceof Error ? err.message : 'some error happened',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* For a detailed explanation regarding each configuration property and type check, visit:
|
||||||
|
* https://jestjs.io/docs/configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
transform: {
|
||||||
|
'^.+\\.ts?$': 'esbuild-jest',
|
||||||
|
},
|
||||||
|
clearMocks: true,
|
||||||
|
collectCoverage: true,
|
||||||
|
coverageDirectory: 'coverage',
|
||||||
|
coverageProvider: 'v8',
|
||||||
|
testMatch: ['**/tests/unit/*.test.ts'],
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"name": "hello_world",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "hello world sample for NodeJS",
|
||||||
|
"main": "app.js",
|
||||||
|
"repository": "https://github.com/awslabs/aws-sam-cli/tree/develop/samcli/local/init/templates/cookiecutter-aws-sam-hello-nodejs",
|
||||||
|
"author": "SAM CLI",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sparticuz/chromium": "110.0.0",
|
||||||
|
"esbuild": "^0.14.14",
|
||||||
|
"puppeteer-core": "19.6.3"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"unit": "jest",
|
||||||
|
"lint": "eslint '*.ts' --quiet --fix",
|
||||||
|
"compile": "tsc",
|
||||||
|
"test": "npm run compile && npm run unit"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/aws-lambda": "^8.10.92",
|
||||||
|
"@types/jest": "^27.4.0",
|
||||||
|
"@types/node": "^17.0.13",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||||
|
"@typescript-eslint/parser": "^5.10.2",
|
||||||
|
"esbuild-jest": "^0.5.0",
|
||||||
|
"eslint": "^8.8.0",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
|
"jest": "^27.5.0",
|
||||||
|
"prettier": "^2.5.1",
|
||||||
|
"ts-node": "^10.4.0",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
|
||||||
|
import { lambdaHandler } from '../../app';
|
||||||
|
|
||||||
|
describe('Unit test for app handler', function () {
|
||||||
|
it('verifies successful response', async () => {
|
||||||
|
const event: APIGatewayProxyEvent = {
|
||||||
|
httpMethod: 'get',
|
||||||
|
body: '',
|
||||||
|
headers: {},
|
||||||
|
isBase64Encoded: false,
|
||||||
|
multiValueHeaders: {},
|
||||||
|
multiValueQueryStringParameters: {},
|
||||||
|
path: '/hello',
|
||||||
|
pathParameters: {},
|
||||||
|
queryStringParameters: {},
|
||||||
|
requestContext: {
|
||||||
|
accountId: '123456789012',
|
||||||
|
apiId: '1234',
|
||||||
|
authorizer: {},
|
||||||
|
httpMethod: 'get',
|
||||||
|
identity: {
|
||||||
|
accessKey: '',
|
||||||
|
accountId: '',
|
||||||
|
apiKey: '',
|
||||||
|
apiKeyId: '',
|
||||||
|
caller: '',
|
||||||
|
clientCert: {
|
||||||
|
clientCertPem: '',
|
||||||
|
issuerDN: '',
|
||||||
|
serialNumber: '',
|
||||||
|
subjectDN: '',
|
||||||
|
validity: { notAfter: '', notBefore: '' },
|
||||||
|
},
|
||||||
|
cognitoAuthenticationProvider: '',
|
||||||
|
cognitoAuthenticationType: '',
|
||||||
|
cognitoIdentityId: '',
|
||||||
|
cognitoIdentityPoolId: '',
|
||||||
|
principalOrgId: '',
|
||||||
|
sourceIp: '',
|
||||||
|
user: '',
|
||||||
|
userAgent: '',
|
||||||
|
userArn: '',
|
||||||
|
},
|
||||||
|
path: '/hello',
|
||||||
|
protocol: 'HTTP/1.1',
|
||||||
|
requestId: 'c6af9ac6-7b61-11e6-9a41-93e8deadbeef',
|
||||||
|
requestTimeEpoch: 1428582896000,
|
||||||
|
resourceId: '123456',
|
||||||
|
resourcePath: '/hello',
|
||||||
|
stage: 'dev',
|
||||||
|
},
|
||||||
|
resource: '',
|
||||||
|
stageVariables: {},
|
||||||
|
};
|
||||||
|
const result: APIGatewayProxyResult = await lambdaHandler(event);
|
||||||
|
|
||||||
|
expect(result.statusCode).toEqual(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2020",
|
||||||
|
"strict": true,
|
||||||
|
"preserveConstEnums": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"sourceMap": false,
|
||||||
|
"module":"es2015",
|
||||||
|
"moduleResolution":"node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules", "**/*.test.ts"]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
AWSTemplateFormatVersion: "2010-09-09"
|
||||||
|
Transform: AWS::Serverless-2016-10-31
|
||||||
|
Description: >
|
||||||
|
aws-sam
|
||||||
|
|
||||||
|
Sample SAM Template for aws-sam
|
||||||
|
|
||||||
|
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
|
||||||
|
Globals:
|
||||||
|
Function:
|
||||||
|
Timeout: 90
|
||||||
|
MemorySize: 512
|
||||||
|
|
||||||
|
Resources:
|
||||||
|
HelloWorldFunction:
|
||||||
|
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
|
||||||
|
Properties:
|
||||||
|
Layers:
|
||||||
|
- <YOUR_LAYER_ARN_HERE (arn:aws:lambda:...)>
|
||||||
|
CodeUri: hello-world/
|
||||||
|
Handler: app.lambdaHandler
|
||||||
|
Runtime: nodejs16.x
|
||||||
|
Architectures:
|
||||||
|
- x86_64
|
||||||
|
Events:
|
||||||
|
HelloWorld:
|
||||||
|
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
|
||||||
|
Properties:
|
||||||
|
Path: /hello
|
||||||
|
Method: get
|
||||||
|
Metadata: # Manage esbuild properties
|
||||||
|
BuildMethod: esbuild
|
||||||
|
BuildProperties:
|
||||||
|
Minify: true
|
||||||
|
Target: "es2020"
|
||||||
|
# Sourcemap: true # Enabling source maps will create the required NODE_OPTIONS environment variables on your lambda function during sam build
|
||||||
|
EntryPoints:
|
||||||
|
- app.ts
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
|
||||||
|
# Find out more about other implicit resources you can reference within SAM
|
||||||
|
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
|
||||||
|
HelloWorldApi:
|
||||||
|
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
|
||||||
|
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
|
||||||
|
HelloWorldFunction:
|
||||||
|
Description: "Hello World Lambda Function ARN"
|
||||||
|
Value: !GetAtt HelloWorldFunction.Arn
|
||||||
|
HelloWorldFunctionIamRole:
|
||||||
|
Description: "Implicit IAM Role created for Hello World function"
|
||||||
|
Value: !GetAtt HelloWorldFunctionRole.Arn
|
||||||
Loading…
Reference in New Issue