Skip to content

Commit 72fe9b5

Browse files
author
Dimkir Mars
committed
initial commit
0 parents  commit 72fe9b5

19 files changed

+1141
-0
lines changed

.gitignore

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/tmp/
2+
/node_modules/
3+
/dist/
4+
5+
/var/dist/*
6+
!/var/dist/.gitkeep
7+
/var/log/*
8+
!/var/log/.gitkeep
9+
#/var/*
10+
11+
12+
*.bak

README.md

+265
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
How to run NightmareJS on AWS Lambda
2+
=====
3+
4+
5+
In order to help you running NightmareJS o AWS Lambda we have created this package.
6+
7+
First clone the package into your home directory.
8+
9+
10+
```
11+
git clone http://github.com/dimkir/nightmare-lambda-tutorial.git
12+
cd nightmare-lambda-tutorial
13+
```
14+
15+
16+
17+
#### Install and configure AWS CLI
18+
19+
Before we are able to create You have to have AWS CLI installed
20+
```
21+
sudo pip install awscli
22+
23+
aws configure
24+
25+
```
26+
27+
Make sure that you can execute under user credentials which have at least Admin Policy
28+
(because creating Lambda Function requires creating IAM role and only Admin Policy can do that).
29+
30+
31+
32+
33+
34+
#### Choose your function/project name
35+
36+
When your lambda function is published on AWS it should have a name. Please edit file `projectname.txt` and set
37+
the contents of the file to what you want your lambda called (remember to only use alphanumerical values and underscore).
38+
Or you can leave default name `nightmare-tutorial`.
39+
40+
41+
42+
#### Create your AWS Lambda function
43+
44+
There's a lot of ways to create lambda function: by clicking through AWS Web console, using AWS CLI or use the helper scripts from `bin/` directory.
45+
46+
First let's call
47+
48+
```
49+
[nightmare-lambda-tutorial]$ bin/install/create-function.sh
50+
51+
```
52+
53+
54+
You will get similar looking help output, which suggest that as a second parameter,
55+
we should use id (ARN) of the role under which lambda function will be executed.
56+
57+
```
58+
20:02 $ bin/install/create-function.sh
59+
Number of parameters is 0
60+
61+
Usage:
62+
63+
./create-function.sh <function-name-or-alias> <role-arn> <function-package.zip>
64+
65+
Example:
66+
67+
./create-function.sh nightmare-tutorial arn:xxxx var/dist/nightmare-tutorial.zip
68+
69+
```
70+
71+
72+
In order to get id (ARN) of the role, we first have to create this role.
73+
74+
Let's use another utility - `bin/install/create-role-with-policy.sh`:
75+
76+
```
77+
✘-1 ~/l/nightmare-tutorial [master L|…14]
78+
20:02 $ bin/install/create-role-with-policy.sh
79+
Number of parameters is 0
80+
81+
---------------------------------------------
82+
Utility for creating lambda functions.
83+
Creates a role for a particular function name,
84+
and adds policy to read from source bucket and write to target bucket.
85+
----------------------------------------------
86+
87+
88+
Usage:
89+
./create-role-with-policy.sh <function-name-or-alias> <source_bucket> <target_bucket>
90+
91+
92+
93+
94+
```
95+
96+
97+
The source code from this tutorial will take a screenshot of a website using Nightmare and will save it to S3,
98+
this is why we need to specify buckets which lambda function will be able to read and write.
99+
100+
So go ahead and create a bucket (manually or via `aws s3 mb s3://my-fancy-bucket-777 --region eu-west-1`) and once
101+
the bucket is ready let's create a role:
102+
103+
104+
```
105+
bin/install/create-role-with-policy.sh nightmare-tutorial my-fancy-bucket-777 my-fancy-bucket-777
106+
```
107+
108+
You will get output similar to this, what is important for us is arn of the role:
109+
`arn:aws:iam::326625058526:role/lambda-nightmare-tutorial-execution-role`
110+
111+
112+
```
113+
✔ ~/l/nightmare-tutorial [master L|…14]
114+
20:12 $ bin/install/create-role-with-policy.sh nightmare-tutorial my-fancy-bucket-777 my-fancy-bucket-777
115+
Number of parameters is 3
116+
Lambda function alias: [nightmare-tutorial2], source bucket [my-fancy-bucket-777], target bucket: [my-fancy-bucket-777]
117+
lambda_execution_role_arn=arn:aws:iam::326625058526:role/lambda-nightmare-tutorial-execution-role
118+
119+
```
120+
121+
122+
123+
Before we make a function, we have create a zip package. In simple words we will include the source files
124+
and most of dependencies from `node_modules` folder. For running on Lambda we will not need `electron/dist` folder
125+
and it will be excluded from the archive. For more details on how package is zipped see `bin/zip-package.sh`.
126+
127+
```
128+
bin/zip-package.zip
129+
```
130+
131+
You will see the list of files added to the package and total size of the zip. In my case it is ~1Mb.
132+
The zip-will be stored in the folder `var/dist`.
133+
134+
```
135+
adding: .....
136+
adding: .....
137+
adding: .....
138+
adding: .....
139+
adding: .....
140+
141+
-rw-rw-r-- 1 mars mars 1.1M Mar 13 20:21 var/dist/nightmare-tutorial.zip
142+
143+
```
144+
145+
146+
Now, as we finally have role ID (ARN) and zipped function source, we can finally create our function. We choose `nodejs4.3` runtime
147+
and create function with 1024Mb of Memory (they work and boot up faster and it is rarely worth using lambdas with less memory).
148+
149+
```
150+
[nightmare-lambda-tutorial]$ bin/install/create-function.sh nightmare-tutorial \
151+
arn:aws:iam::326625058526:role/lambda-nightmare-tutorial-execution-role \
152+
var/dist/nightmare-tutorial.zip
153+
```
154+
155+
156+
```
157+
✔ ~/l/nightmare-tutorial [master L|…14]
158+
20:24 $ bin/install/create-function.sh nightmare-tutorial arn:aws:iam::326625058526:role/lambda-nightmare-tutorial-execution-role var/dist/nightmare-tutorial.zip
159+
Number of parameters is 3
160+
Function alias:\t nightmare-tutorial
161+
Role ARN: \t arn:aws:iam::326625058526:role/lambda-nightmare-tutorial2-execution-role
162+
Function package:\t var/dist/nightmare-tutorial.zip
163+
{
164+
"CodeSha256": "QedKlzWH0A9jPumkuuyleINFDNdqkqANy9hA2ysjoUA=",
165+
"FunctionName": "nightmare-tutorial",
166+
"CodeSize": 1062573,
167+
"MemorySize": 1024,
168+
"FunctionArn": "arn:aws:lambda:eu-west-1:326625058526:function:nightmare-tutorial",
169+
"Version": "$LATEST",
170+
"Role": "arn:aws:iam::326625058526:role/lambda-nightmare-tutorial-execution-role",
171+
"Timeout": 3,
172+
"LastModified": "2017-03-13T20:24:43.112+0000",
173+
"Handler": "index.handler",
174+
"Runtime": "nodejs4.3",
175+
"Description": ""
176+
}
177+
178+
179+
```
180+
181+
182+
183+
#### Run your lambda function
184+
185+
Now you can invoke your lambda function either by calling `bin/run.sh http://www.yahoo.com`.
186+
If you have configured everything correctly, you will see similar output.
187+
188+
```
189+
20:24 $ bin/run.sh http://www.yahoo.com
190+
{
191+
"StatusCode": 200
192+
}
193+
Returned with retval [0]
194+
"http://s3-eu-west-1.amazonaws.com/my-fancy-bucket-777/test/store/image-1489436927266.png"
195+
JQ returned 0
196+
✔ ~/l/nightmare-tutorial [master L|…14]
197+
198+
```
199+
200+
201+
202+
203+
204+
or if you prefer to invoke the lambda manually, you can do that via AWS CLI. Note that last parameter
205+
is the name of the log file (no need for output redirects like `>`!). And to see the result you would have to `cat var/log/logfile.txt`
206+
207+
```
208+
aws lambda invoke-function \
209+
--function-name nightmare-tutorial \
210+
--payload '{ "url" : "http://www.yahoo.com" }' \
211+
var/log/logfile.txt
212+
213+
```
214+
215+
216+
217+
218+
219+
220+
221+
#### Let's review the magic which allows nightmare to run
222+
223+
In the very header of `index.js` you can find the following code,
224+
which takes care of pulling and installing all required native dependencies:
225+
226+
227+
```
228+
/***********************************************************
229+
* This magic code runs once per boot-up of lambda container
230+
* and pulls all the electron and Xvfb binaries and stores
231+
* them in /tmp/pck folder.
232+
*
233+
* Later on business logic should be called within xvfb.start()
234+
* callback, so that when Nightmare calls Electron there is
235+
* a virtual framebuffer available.
236+
*
237+
* Variable electronPath starts as undefined and is only
238+
* overridden on Lambda environment. Which simplifies testing
239+
* lambda in local environment.
240+
*
241+
***********************************************************/
242+
console.log('Lambda executes global code upon container boot-up');
243+
244+
var electronPath, pack, isOnLambda, Xvfb;
245+
246+
pack = require('./lib/bootstrap/nightmare-lambda-pack');
247+
isOnLambda = pack.isOnLambda;
248+
Xvfb = require('./lib/bootstrap/xvfb');
249+
if ( isOnLambda ){
250+
electronPath = pack.installNightmare();
251+
}
252+
253+
254+
/** ************************************************************** */
255+
256+
257+
```
258+
259+
260+
Also business logic is running within callback to `xvfb.start()`
261+
which allows to start using Nightmare/Electron only when virtual framebuffer is available.
262+
263+
264+
265+

bin/install/create-function.sh

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/bash
2+
3+
# get project name from file
4+
PROJECT_NAME=$(cat projectname.txt)
5+
6+
if [ "" == "$PROJECT_NAME" ]
7+
then
8+
# Fallback to using project directory name as project name
9+
PROJECT_DIR_RELATIVE=$(dirname $(dirname $(dirname $0)))
10+
pushd . > /dev/null
11+
PROJECT_NAME=$(basename $(cd $PROJECT_DIR_RELATIVE && pwd))
12+
popd > /dev/null
13+
fi
14+
15+
16+
17+
echo "Number of parameters is $#"
18+
if [ $# -ne 3 ]
19+
then
20+
CMD="./$(basename $0)"
21+
echo
22+
echo " Usage:"
23+
echo
24+
echo " $CMD <function-name-or-alias> <role-arn> <function-package.zip>"
25+
echo
26+
echo " Example: "
27+
echo
28+
echo " $CMD $PROJECT_NAME arn:xxxx var/dist/$PROJECT_NAME.zip"
29+
echo
30+
echo
31+
32+
exit 1
33+
fi
34+
35+
function=$1
36+
role_arn=$2
37+
package=$3
38+
echo "Function alias:\t $function"
39+
echo "Role ARN: \t $role_arn "
40+
echo "Function package:\t $package"
41+
42+
43+
aws lambda create-function \
44+
--function $function \
45+
--memory-size 1024 \
46+
--runtime nodejs4.3 \
47+
--handler index.handler \
48+
--role $role_arn \
49+
--zip-file fileb://./$package
50+

0 commit comments

Comments
 (0)