├── tests ├── python │ └── lambda_function.py ├── nodejs │ └── index.js └── java │ ├── build.gradle │ ├── src │ └── main │ │ └── java │ │ └── example │ │ └── Example.java │ └── .gitignore ├── config └── regions.txt ├── Dockerfile ├── LICENSE ├── .gitignore ├── arns ├── 0.12.5 │ └── wkhtmltopdf.csv └── 0.12.6 │ └── wkhtmltopdf.csv ├── publish.sh ├── README.md └── test.sh /tests/python/lambda_function.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | def lambda_handler(event, context): 4 | subprocess.run("ldd /opt/bin/wkhtmltopdf".split(), check=True) 5 | 6 | subprocess.run("wkhtmltopdf -V".split(), check=True) -------------------------------------------------------------------------------- /tests/nodejs/index.js: -------------------------------------------------------------------------------- 1 | const { execSync } = require("child_process"); 2 | 3 | exports.handler = async event => { 4 | execSync("ldd /opt/bin/wkhtmltopdf", { encoding: "utf8", stdio: "inherit" }); 5 | 6 | execSync("wkhtmltopdf -V", { encoding: "utf8", stdio: "inherit" }); 7 | }; 8 | -------------------------------------------------------------------------------- /config/regions.txt: -------------------------------------------------------------------------------- 1 | ap-east-1 2 | ap-northeast-1 3 | ap-northeast-2 4 | ap-south-1 5 | ap-southeast-1 6 | ap-southeast-2 7 | ca-central-1 8 | eu-central-1 9 | eu-north-1 10 | eu-west-1 11 | eu-west-2 12 | eu-west-3 13 | sa-east-1 14 | us-east-1 15 | us-east-2 16 | us-west-1 17 | us-west-2 18 | -------------------------------------------------------------------------------- /tests/java/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | compile ( 9 | 'com.amazonaws:aws-lambda-java-core:1.2.0', 10 | 'com.amazonaws:aws-lambda-java-events:2.2.7' 11 | ) 12 | } 13 | 14 | task buildZip(type: Zip) { 15 | from compileJava 16 | from processResources 17 | into('lib') { 18 | from configurations.runtimeClasspath 19 | } 20 | } 21 | 22 | task buildPackage(type: Copy) { 23 | from compileJava 24 | from processResources 25 | into('lib') { 26 | from configurations.runtimeClasspath 27 | } 28 | into 'build/package' 29 | } 30 | 31 | build.dependsOn buildPackage -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM amazonlinux:2 2 | 3 | RUN yum install -y \ 4 | rpmdevtools \ 5 | wget \ 6 | yum-utils 7 | 8 | WORKDIR /tmp 9 | 10 | # Download wkhtmltopdf and its dependencies. Then extract all rpm files. 11 | ENV WKHTMLTOPDF_BIN="wkhtmltopdf.rpm" 12 | RUN wget -O $WKHTMLTOPDF_BIN https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox-0.12.6-1.centos7.$(arch).rpm \ 13 | && yum install --downloadonly --downloaddir=/tmp $WKHTMLTOPDF_BIN \ 14 | && yumdownloader --archlist=$(arch) \ 15 | bzip2-libs \ 16 | expat \ 17 | libuuid \ 18 | && rpmdev-extract *rpm 19 | 20 | WORKDIR /layer 21 | 22 | # Copy wkhtmltopdf binary and dependency libraries for packaging 23 | RUN mkdir -p {bin,lib} \ 24 | && cp /tmp/wkhtml*/usr/local/bin/* bin \ 25 | && cp /tmp/*/usr/lib64/* lib || : 26 | 27 | # Zip files 28 | ENV LAYER_ZIP="layer.zip" 29 | RUN zip -r $LAYER_ZIP bin lib \ 30 | && mv $LAYER_ZIP / -------------------------------------------------------------------------------- /tests/java/src/main/java/example/Example.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import com.amazonaws.services.lambda.runtime.Context; 8 | 9 | public class Example { 10 | public void handleRequest(Object input, Context context) throws Exception { 11 | List> commands = new ArrayList>(); 12 | commands.add(Arrays.asList("ldd", "/opt/bin/wkhtmltopdf")); 13 | commands.add(Arrays.asList("wkhtmltopdf", "-V")); 14 | 15 | ProcessBuilder builder = new ProcessBuilder(); 16 | builder.inheritIO(); 17 | for (List command : commands) { 18 | builder.command(command); 19 | Process process = builder.start(); 20 | if (process.waitFor() != 0) { 21 | throw new Exception(String.format("Command failed: %s", command.toString())); 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Brandon Lim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | # build output 64 | layer 65 | layer.zip 66 | -------------------------------------------------------------------------------- /arns/0.12.5/wkhtmltopdf.csv: -------------------------------------------------------------------------------- 1 | Region,ARN 2 | ap-east-1,arn:aws:lambda:ap-east-1:347599033421:layer:wkhtmltopdf-0_12_5:1 3 | ap-northeast-1,arn:aws:lambda:ap-northeast-1:347599033421:layer:wkhtmltopdf-0_12_5:1 4 | ap-northeast-2,arn:aws:lambda:ap-northeast-2:347599033421:layer:wkhtmltopdf-0_12_5:1 5 | ap-south-1,arn:aws:lambda:ap-south-1:347599033421:layer:wkhtmltopdf-0_12_5:1 6 | ap-southeast-1,arn:aws:lambda:ap-southeast-1:347599033421:layer:wkhtmltopdf-0_12_5:1 7 | ap-southeast-2,arn:aws:lambda:ap-southeast-2:347599033421:layer:wkhtmltopdf-0_12_5:1 8 | ca-central-1,arn:aws:lambda:ca-central-1:347599033421:layer:wkhtmltopdf-0_12_5:1 9 | eu-central-1,arn:aws:lambda:eu-central-1:347599033421:layer:wkhtmltopdf-0_12_5:1 10 | eu-north-1,arn:aws:lambda:eu-north-1:347599033421:layer:wkhtmltopdf-0_12_5:1 11 | eu-west-1,arn:aws:lambda:eu-west-1:347599033421:layer:wkhtmltopdf-0_12_5:1 12 | eu-west-2,arn:aws:lambda:eu-west-2:347599033421:layer:wkhtmltopdf-0_12_5:1 13 | eu-west-3,arn:aws:lambda:eu-west-3:347599033421:layer:wkhtmltopdf-0_12_5:1 14 | sa-east-1,arn:aws:lambda:sa-east-1:347599033421:layer:wkhtmltopdf-0_12_5:1 15 | us-east-1,arn:aws:lambda:us-east-1:347599033421:layer:wkhtmltopdf-0_12_5:1 16 | us-east-2,arn:aws:lambda:us-east-2:347599033421:layer:wkhtmltopdf-0_12_5:1 17 | us-west-1,arn:aws:lambda:us-west-1:347599033421:layer:wkhtmltopdf-0_12_5:1 18 | us-west-2,arn:aws:lambda:us-west-2:347599033421:layer:wkhtmltopdf-0_12_5:1 19 | -------------------------------------------------------------------------------- /arns/0.12.6/wkhtmltopdf.csv: -------------------------------------------------------------------------------- 1 | Region,ARN 2 | ap-east-1,arn:aws:lambda:ap-east-1:347599033421:layer:wkhtmltopdf-0_12_6:1 3 | ap-northeast-1,arn:aws:lambda:ap-northeast-1:347599033421:layer:wkhtmltopdf-0_12_6:1 4 | ap-northeast-2,arn:aws:lambda:ap-northeast-2:347599033421:layer:wkhtmltopdf-0_12_6:1 5 | ap-south-1,arn:aws:lambda:ap-south-1:347599033421:layer:wkhtmltopdf-0_12_6:1 6 | ap-southeast-1,arn:aws:lambda:ap-southeast-1:347599033421:layer:wkhtmltopdf-0_12_6:1 7 | ap-southeast-2,arn:aws:lambda:ap-southeast-2:347599033421:layer:wkhtmltopdf-0_12_6:1 8 | ca-central-1,arn:aws:lambda:ca-central-1:347599033421:layer:wkhtmltopdf-0_12_6:1 9 | eu-central-1,arn:aws:lambda:eu-central-1:347599033421:layer:wkhtmltopdf-0_12_6:1 10 | eu-north-1,arn:aws:lambda:eu-north-1:347599033421:layer:wkhtmltopdf-0_12_6:1 11 | eu-west-1,arn:aws:lambda:eu-west-1:347599033421:layer:wkhtmltopdf-0_12_6:1 12 | eu-west-2,arn:aws:lambda:eu-west-2:347599033421:layer:wkhtmltopdf-0_12_6:1 13 | eu-west-3,arn:aws:lambda:eu-west-3:347599033421:layer:wkhtmltopdf-0_12_6:1 14 | sa-east-1,arn:aws:lambda:sa-east-1:347599033421:layer:wkhtmltopdf-0_12_6:1 15 | us-east-1,arn:aws:lambda:us-east-1:347599033421:layer:wkhtmltopdf-0_12_6:1 16 | us-east-2,arn:aws:lambda:us-east-2:347599033421:layer:wkhtmltopdf-0_12_6:1 17 | us-west-1,arn:aws:lambda:us-west-1:347599033421:layer:wkhtmltopdf-0_12_6:1 18 | us-west-2,arn:aws:lambda:us-west-2:347599033421:layer:wkhtmltopdf-0_12_6:1 19 | -------------------------------------------------------------------------------- /publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VERSION="0.12.6" 4 | ARN_DIR="arns/$VERSION" 5 | ARN_FILE="$ARN_DIR/wkhtmltopdf.csv" 6 | LAYER_NAME="wkhtmltopdf-$VERSION" 7 | LAYER_NAME=${LAYER_NAME//./_} # Replace . with _ , since . is not allow 8 | LAYER_ZIP="layer.zip" 9 | REGIONS=$(cat config/regions.txt) 10 | 11 | # Exit if aws cli is not available 12 | if ! aws --version 1>/dev/null; then 13 | exit 1 14 | fi 15 | 16 | rm -rf $ARN_DIR && mkdir -p $ARN_DIR 17 | 18 | echo "Region,ARN" >$ARN_FILE 19 | for region in $REGIONS; do 20 | printf "%s\n" "Region: $region" 21 | OUTPUT=$( 22 | aws lambda publish-layer-version \ 23 | --description "wkhtmltopdf $VERSION (with patched qt)" \ 24 | --layer-name $LAYER_NAME \ 25 | --output text \ 26 | --query "[LayerVersionArn, Version]" \ 27 | --region $region \ 28 | --zip-file fileb://$LAYER_ZIP 29 | ) 30 | LAYER_VERSION_ARN=$(echo $OUTPUT | awk '{print $1}') 31 | LAYER_VERSION=$(echo $OUTPUT | awk '{print $2}') 32 | aws lambda add-layer-version-permission \ 33 | --action lambda:GetLayerVersion \ 34 | --layer-name $LAYER_NAME \ 35 | --output text \ 36 | --principal "*" \ 37 | --query "Statement" \ 38 | --region "$region" \ 39 | --statement-id public \ 40 | --version-number "$LAYER_VERSION" \ 41 | &>/dev/null 42 | echo "$region,$LAYER_VERSION_ARN" >>$ARN_FILE 43 | printf "\n" 44 | done 45 | -------------------------------------------------------------------------------- /tests/java/.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle 2 | # ------ 3 | .gradle 4 | /build 5 | /buildSrc/build 6 | /buildSrc/subprojects/*/build 7 | /subprojects/*/build 8 | /subprojects/docs/src/samples/**/build 9 | /subprojects/docs/src/snippets/**/build 10 | /subprojects/internal-android-performance-testing/build-android-libs 11 | 12 | # IDEA 13 | # ---- 14 | !/.idea 15 | /.idea/* 16 | !/.idea/codeStyles 17 | !/.idea/inspectionProfiles 18 | */**/.idea 19 | .shelf 20 | /*.iml 21 | /*.ipr 22 | /*.iws 23 | /buildSrc/.idea 24 | /buildSrc/.shelf 25 | /buildSrc/*.iml 26 | /buildSrc/*.ipr 27 | /buildSrc/*.iws 28 | /buildSrc/out 29 | /buildSrc/subprojects/*/*.iml 30 | /buildSrc/subprojects/*/out 31 | /out 32 | /subprojects/*/*.iml 33 | /subprojects/*/out 34 | /.teamcity/*.iml 35 | /.teamcity/target 36 | 37 | # Eclipse 38 | # ------- 39 | *.classpath 40 | *.project 41 | *.settings 42 | /bin 43 | /subprojects/*/bin 44 | atlassian-ide-plugin.xml 45 | .metadata/ 46 | 47 | # NetBeans 48 | # -------- 49 | .nb-gradle 50 | .nb-gradle-properties 51 | 52 | # Vim 53 | # --- 54 | *.sw[nop] 55 | 56 | # Emacs 57 | # ----- 58 | *~ 59 | \#*\# 60 | .\#* 61 | 62 | # Textmate 63 | # -------- 64 | .textmate 65 | 66 | # Sublime Text 67 | # ------------ 68 | *.sublime-* 69 | 70 | # jEnv 71 | # ---- 72 | .java-version 73 | 74 | # macOS 75 | # ---- 76 | .DS_Store 77 | 78 | # HPROF 79 | # ----- 80 | *.hprof 81 | 82 | # Work dirs 83 | # --------- 84 | /incoming-distributions 85 | /intTestHomeDir 86 | 87 | # Logs 88 | # ---- 89 | /*.log 90 | 91 | # oh-my-zsh gradle plugin 92 | .gradletasknamecache -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wkhtmltopdf as AWS Lambda Layer 2 | 3 | [wkhtmltopdf](https://wkhtmltopdf.org/) with dependencies published as [AWS Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html). 4 | 5 | ## Operating Systems 6 | 7 | This layer supports both _Amazon Linux_ and _Amazon Linux 2_. 8 | 9 | ## Getting Started 10 | 11 | Add this layer to Lambda function by providing the [layer version ARN](#version-arns). 12 | 13 | ## Version ARNs 14 | 15 | | Region | ARN | 16 | | -------------- | --------------------------------------------------------------------- | 17 | | ap-east-1 | arn:aws:lambda:ap-east-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 18 | | ap-northeast-1 | arn:aws:lambda:ap-northeast-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 19 | | ap-northeast-2 | arn:aws:lambda:ap-northeast-2:347599033421:layer:wkhtmltopdf-0_12_6:1 | 20 | | ap-south-1 | arn:aws:lambda:ap-south-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 21 | | ap-southeast-1 | arn:aws:lambda:ap-southeast-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 22 | | ap-southeast-2 | arn:aws:lambda:ap-southeast-2:347599033421:layer:wkhtmltopdf-0_12_6:1 | 23 | | ca-central-1 | arn:aws:lambda:ca-central-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 24 | | eu-central-1 | arn:aws:lambda:eu-central-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 25 | | eu-north-1 | arn:aws:lambda:eu-north-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 26 | | eu-west-1 | arn:aws:lambda:eu-west-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 27 | | eu-west-2 | arn:aws:lambda:eu-west-2:347599033421:layer:wkhtmltopdf-0_12_6:1 | 28 | | eu-west-3 | arn:aws:lambda:eu-west-3:347599033421:layer:wkhtmltopdf-0_12_6:1 | 29 | | sa-east-1 | arn:aws:lambda:sa-east-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 30 | | us-east-1 | arn:aws:lambda:us-east-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 31 | | us-east-2 | arn:aws:lambda:us-east-2:347599033421:layer:wkhtmltopdf-0_12_6:1 | 32 | | us-west-1 | arn:aws:lambda:us-west-1:347599033421:layer:wkhtmltopdf-0_12_6:1 | 33 | | us-west-2 | arn:aws:lambda:us-west-2:347599033421:layer:wkhtmltopdf-0_12_6:1 | 34 | 35 | See `/arns` directory for other wkhtmltopdf versions. 36 | 37 | ## Usage 38 | 39 | wkhtmltopdf binary will be extracted to the `/opt/bin`. 40 | 41 | wkhtmltopdf can be executed directly as a command line binary, or via a wrapper. 42 | 43 | Refer to `/tests` directory for example usage. 44 | 45 | ## Build, Test, Publish 46 | 47 | Refer to the following scripts to build and publish your own wkhtmltopdf layer. 48 | 49 | 1. Run `./build.sh` to build a new layer zip. 50 | 2. Run `./test.sh` to test the layer zip. 51 | 3. Run `./publish.sh` to publish the layer zip to regions specified in `/config/regions.txt`. 52 | 53 | ## Fonts 54 | 55 | See [fonts-aws-lambda-layer](https://github.com/brandonlim-hs/fonts-aws-lambda-layer) to use fonts on AWS Lambda. 56 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | declare -i ERRORS 4 | ERRORS=0 5 | LAYER_DIR="$PWD/layer" 6 | LAYER_ZIP="layer.zip" 7 | 8 | if [ ! -s $LAYER_ZIP ]; then 9 | printf "\e[31m%s\n\e[0m" "cannot find or open $LAYER_ZIP" 10 | exit 1 11 | fi 12 | 13 | rm -rf $LAYER_DIR && unzip $LAYER_ZIP -d $LAYER_DIR 1>/dev/null 14 | 15 | # Invoke lambda function with wkhtmltopdf layer 16 | invoke_lambda_function() { 17 | while [[ "$#" -gt 0 ]]; do 18 | case $1 in 19 | -c | --code) 20 | local CODE_DIR="$2" 21 | shift 22 | ;; 23 | -h | --handler) 24 | local HANDLER="$2" 25 | shift 26 | ;; 27 | -r | --runtime) 28 | local RUNTIME="$2" 29 | shift 30 | ;; 31 | *) 32 | echo "Unknown parameter: $1" >&2 33 | return 1 34 | ;; 35 | esac 36 | shift 37 | done 38 | 39 | printf "%s\n" "Runtime: $RUNTIME" 40 | docker run --rm \ 41 | -v "$CODE_DIR":/var/task:ro,delegated \ 42 | -v "$LAYER_DIR":/opt:ro,delegated \ 43 | lambci/lambda:$RUNTIME \ 44 | $HANDLER 45 | if [ $? -ne 0 ]; then ERRORS+=1; fi 46 | printf "\n" 47 | } 48 | 49 | # Test layer on: 50 | # operating system: Amazon Linux, runtime: Java 8 51 | # operating system: Amazon Linux 2, runtime: Java 11 52 | JAVA_RUNTIMES="java8 java11" 53 | JAVA_DIR="$PWD/tests/java" 54 | 55 | # Package Java file. See: https://docs.aws.amazon.com/lambda/latest/dg/create-deployment-pkg-zip-java.html 56 | rm -rf "$JAVA_DIR/build" && docker run --rm -v "$JAVA_DIR":/app -w /app gradle:6.0 gradle build -q 57 | 58 | for runtime in $JAVA_RUNTIMES; do 59 | invoke_lambda_function \ 60 | --code "$JAVA_DIR/build/package" \ 61 | --handler "example.Example::handleRequest" \ 62 | --runtime $runtime 63 | done 64 | 65 | # Test layer on: 66 | # operating system: Amazon Linux, runtime: Node.js 8.10 67 | # operating system: Amazon Linux 2, runtime: Node.js 10 68 | # operating system: Amazon Linux 2, runtime: Node.js 12 69 | NODEJS_RUNTIMES="nodejs8.10 nodejs10.x nodejs12.x" 70 | 71 | for runtime in $NODEJS_RUNTIMES; do 72 | invoke_lambda_function \ 73 | --code "$PWD/tests/nodejs" \ 74 | --handler "index.handler" \ 75 | --runtime $runtime 76 | done 77 | 78 | # Test layer on: 79 | # operating system: Amazon Linux, runtime: Python 3.6 80 | # operating system: Amazon Linux, runtime: Python 3.7 81 | # operating system: Amazon Linux 2, runtime: Python 3.8 82 | PYTHON_RUNTIMES="python3.6 python3.7 python3.8" 83 | 84 | for runtime in $PYTHON_RUNTIMES; do 85 | invoke_lambda_function \ 86 | --code "$PWD/tests/python" \ 87 | --handler "lambda_function.lambda_handler" \ 88 | --runtime $runtime 89 | done 90 | 91 | rm -rf $LAYER_DIR 92 | 93 | if [ $ERRORS -gt 0 ]; then 94 | printf "\e[31m%s\n\e[0m" "Errors: $ERRORS" 95 | exit 1 96 | else 97 | printf "\e[32m%s\n\e[0m" "OK" 98 | exit 0 99 | fi 100 | --------------------------------------------------------------------------------