3
votes

I need to upload an executable file ( i.e. wkhtmltopdf to be exact) along with my function code in aws lambda. I'm using serverless framework. I tried different ways but the exe is not uploaded. The function works well when the code is zipped and uploaded via the aws dashboard.

Given below is the directory structure of the function that need to be uploaded

node_modules index.js wkhtmltopdf

This is my serverless.yml

service: consult-payment-api

frameworkVersion: ">=1.1.0 <2.0.0"

package:
  individually: true  

provider:
  name: aws
  region: us-west-2
  runtime: nodejs8.10
  stage: dev
  timeout: 300
  
functions:

  UserPackageCharge:
        handler:  payment/module/chargePackage.create
        package:
          include: 
            - packages/wkhtmltopdf
        events:
          - http:
              path: payment/module/package
              method: post
              cors: 
                origin: '*'
                headers:
                  - Content-Type
                  - X-Amz-Date
                  - Authorization
                  - X-Api-Key
                  - X-Amz-Security-Token
                  - X-Amz-User-Agent
                  - My-Custom-Header

This is my index.js (handler)

var wkhtmltopdf = require('wkhtmltopdf');
var MemoryStream = require('memorystream');

process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'];

exports.handler = function(event, context) {
	var memStream = new MemoryStream();
	var html_utf8 = new Buffer(event.html_base64, 'base64').toString('utf8');
	wkhtmltopdf(html_utf8, event.options, function(code, signal) { context.done(null, { pdf_base64: memStream.read().toString('base64') }); }).pipe(memStream);	
};

But I still get the error 'Error: /bin/bash: wkhtmltopdf: command not found' How to get this working in serverless?

2
What OS are you using? - Erndob
Everything that you include in your lambda zip file is deployed in /var/task in the lambda execution. By this way, you can add your binary in the zip and retrieve it in your code invoking the path /var/task/. Remember that your binary should be compiled with static option, to avoid errors due dependencies. - Biswa
Including your own executables is easy; just package them in the ZIP file you upload, and then reference them (including the relative path within the ZIP file you created) when you call them from Node.js or from other processes that you’ve previously started. Ensure that you include the following at the start of your function code: process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'] - Biswa
@Erndob Lambda uses Amazon Linux I guess - Yasith Prabuddhaka
Thanks for the suggestions. But these do not help me to get this working on serverless framework - Yasith Prabuddhaka

2 Answers

2
votes

I did get a version working.

Here's what I did:

1) Created a package.json and added:

"dependencies": {
"wkhtmltopdf": "^0.3.4",
"memorystream": "^0.3.1"
},

2) Ran ndm install

3) Added WKhtmltopdf in the directory:
enter image description here

4) Added this in serverless.yml
package:
include:
- wkhtmltopdf

5) Added this in the lambda:
var wkhtmltopdf = require('wkhtmltopdf');
var MemoryStream = require('memorystream');


That's about it. Hope it helps.

0
votes

Well I can suggest for Python as that's what I've implemented recently in my project. I've all my lambda scripts and dependency python scripts in one zip and put those on my bastion server. To make those easier to execute and upload I've implemented cattle+click cli which ensure correct version of zips are picked up which are then uploaded to s3 bucket location. When the lambda is triggered based on s3 event it looks for the required parameter file or the input file in the repository(which is nothing but an s3 bucket only).