aws-lambda-runner 1.8.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/js/package-lock.json +2787 -0
- data/js/package.json +9 -5
- data/js/request.js +47 -52
- data/js/startup.js +2 -3
- data/lib/lambda_runner.rb +23 -4
- data/spec/lambdarunner_runner_spec.rb +15 -6
- metadata +4 -3
data/js/package.json
CHANGED
@@ -1,26 +1,30 @@
|
|
1
1
|
{
|
2
2
|
"name": "lambda-helper",
|
3
3
|
"version": "1.0.0",
|
4
|
-
"description": "",
|
4
|
+
"description": "lambda-helper",
|
5
|
+
"repository": {
|
6
|
+
"type": "git",
|
7
|
+
"url": "https://github.com/bbc/aws-lambda-runner.git"
|
8
|
+
},
|
5
9
|
"main": "startup.js",
|
6
10
|
"scripts": {
|
7
11
|
"test": "mocha"
|
8
12
|
},
|
9
13
|
"author": "",
|
10
|
-
"license": "
|
14
|
+
"license": "Apache-2.0",
|
11
15
|
"devDependencies": {
|
12
16
|
"assert": "^1.4.1",
|
13
17
|
"jshint": "^2.9.4",
|
14
|
-
"mocha": "^
|
18
|
+
"mocha": "^5.2.0",
|
15
19
|
"mocha-jshint": "^2.3.1",
|
16
20
|
"mock-res": "^0.4.1",
|
17
21
|
"should": "^11.2.1"
|
18
22
|
},
|
19
23
|
"dependencies": {
|
24
|
+
"always-done": "^1.1.0",
|
20
25
|
"aws-sdk": "*",
|
21
|
-
"istanbul": "^0.4.5",
|
22
|
-
"merge": "^1.2.0",
|
23
26
|
"mock-req": "^0.2.0",
|
27
|
+
"nyc": "^13.1.0",
|
24
28
|
"stdio": "^0.2.7"
|
25
29
|
}
|
26
30
|
}
|
data/js/request.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
/* istanbul ignore file */
|
2
2
|
var url = require('url');
|
3
|
+
const alwaysDone = require('always-done');
|
3
4
|
|
4
5
|
var next_id = 0;
|
5
6
|
// FIXME: this object grows forever - entries are never removed. Should they
|
@@ -28,24 +29,22 @@ Job.prototype.doTimedOut = function () {
|
|
28
29
|
};
|
29
30
|
|
30
31
|
var region = function () {
|
31
|
-
|
32
|
+
return process.env.AWS_DEFAULT_REGION || process.env.AWS_REGION || process.env.AMAZON_REGION || "xx-dummy-0";
|
32
33
|
};
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
};
|
45
|
-
};
|
35
|
+
const defaultContextObject = () => ({
|
36
|
+
// Fixed, but reasonably representative
|
37
|
+
functionName: "via-aws-lambda-runner",
|
38
|
+
functionVersion: "$LATEST",
|
39
|
+
invokedFunctionArn: "arn:aws:lambda:" + region() + ":000000000000:function:via-aws-lambda-runner:$LATEST",
|
40
|
+
memoryLimitInMB: 100,
|
41
|
+
awsRequestId: "00000000-0000-0000-0000-000000000000",
|
42
|
+
logGroupName: "/aws/lambda/via-aws-lambda-runner",
|
43
|
+
logStreamName: "some-log-stream-name",
|
44
|
+
});
|
46
45
|
|
47
46
|
var makeContextObject = function (timeout, overrides) {
|
48
|
-
|
47
|
+
const context = Object.assign(defaultContextObject(), overrides);
|
49
48
|
|
50
49
|
var approximateEndTime = (new Date().getTime()) + timeout;
|
51
50
|
|
@@ -64,19 +63,24 @@ var startJob = function (job, requestObject, handler, opts) {
|
|
64
63
|
var event = requestObject.event;
|
65
64
|
|
66
65
|
var context = makeContextObject(opts.timeout, requestObject.context || {});
|
67
|
-
|
68
|
-
|
66
|
+
|
67
|
+
const done = (err, res) => {
|
69
68
|
if (err) {
|
70
69
|
console.warn('Error:', err);
|
70
|
+
job.doError(err);
|
71
|
+
} else {
|
72
|
+
job.doCompletion(err, res);
|
71
73
|
}
|
72
74
|
};
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
76
|
+
context.done = done;
|
77
|
+
|
78
|
+
const options = {
|
79
|
+
args: [event, context]
|
80
|
+
};
|
81
|
+
|
82
|
+
alwaysDone(handler, options, done);
|
83
|
+
|
80
84
|
};
|
81
85
|
|
82
86
|
var doCreateJob = function (req, res, opts, handler) {
|
@@ -112,17 +116,12 @@ var getJobStatus = function (result) {
|
|
112
116
|
var status = null;
|
113
117
|
var responseBody = null;
|
114
118
|
|
115
|
-
if (result.
|
116
|
-
if (result.completionValues[0] !== null && result.completionValues[0] !== undefined) {
|
117
|
-
status = 502;
|
118
|
-
responseBody = result.completionValues[0];
|
119
|
-
} else {
|
120
|
-
status = 201;
|
121
|
-
responseBody = result.completionValues[1];
|
122
|
-
}
|
123
|
-
} else if (result.threw) {
|
119
|
+
if (result.threw) {
|
124
120
|
status = 500;
|
125
|
-
|
121
|
+
responseBody = result.threw instanceof Error ? `Error: ${result.threw.message}` : JSON.stringify(result.threw);
|
122
|
+
} else if (result.completionValues) {
|
123
|
+
status = 201;
|
124
|
+
responseBody = result.completionValues[1];
|
126
125
|
} else if (result.timedOut) {
|
127
126
|
status = 504;
|
128
127
|
} else {
|
@@ -141,30 +140,26 @@ exports.request = function(req, res, opts, handler, server) {
|
|
141
140
|
|
142
141
|
} else if (req.method === 'DELETE') {
|
143
142
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
}
|
153
|
-
})();
|
143
|
+
// FIXME untested
|
144
|
+
res.writeHead(202, {'Content-Type': 'text/plain'});
|
145
|
+
var terminationMessage = 'Terminating server at http://[localhost]:' + opts.port + ' for ' + opts['module-path'] + ' / ' + opts.handler;
|
146
|
+
res.end(terminationMessage + '\n');
|
147
|
+
console.info(terminationMessage);
|
148
|
+
if (server) {
|
149
|
+
server.close();
|
150
|
+
}
|
154
151
|
|
155
152
|
} else if (req.method === 'GET') {
|
156
153
|
|
157
|
-
(
|
158
|
-
|
159
|
-
|
160
|
-
var answer = result ? getJobStatus(result) : { status: 404, data: null };
|
154
|
+
var request_id = parseInt(url.parse(req.url, true).query.id);
|
155
|
+
var result = jobs[request_id];
|
156
|
+
var answer = result ? getJobStatus(result) : { status: 404, data: null };
|
161
157
|
|
162
|
-
|
163
|
-
|
158
|
+
// non-standard stringification of undefined
|
159
|
+
if (answer.data === undefined) answer.data = null;
|
164
160
|
|
165
|
-
|
166
|
-
|
167
|
-
})();
|
161
|
+
res.writeHead(answer.status, {'Content-Type': 'application/json'});
|
162
|
+
res.end(JSON.stringify(answer.data) + '\n');
|
168
163
|
|
169
164
|
} else {
|
170
165
|
|
data/js/startup.js
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
/* istanbul ignore file */
|
3
2
|
var http = require('http');
|
4
3
|
var stdio = require('stdio');
|
5
4
|
var request = require('./request.js');
|
@@ -10,7 +9,7 @@ var opts = stdio.getopt({
|
|
10
9
|
'handler': {mandatory: true, args: 1, key: 'h', description: 'handler function to call'},
|
11
10
|
'timeout': {mandatory: true, args: 1, key: 't', description: 'timeout for handler function'}
|
12
11
|
});
|
13
|
-
console.info(opts);
|
12
|
+
console.info('Startup with options: ', JSON.stringify(opts, null, 2));
|
14
13
|
|
15
14
|
var module = require(opts['module-path']);
|
16
15
|
var server = http.createServer();
|
data/lib/lambda_runner.rb
CHANGED
@@ -16,10 +16,10 @@ module LambdaRunner
|
|
16
16
|
|
17
17
|
def install_deps
|
18
18
|
@npm_cwd = File.expand_path('../../js/', __FILE__)
|
19
|
-
STDOUT.puts("
|
19
|
+
STDOUT.puts("Trying to use npm install in #{@npm_cwd}")
|
20
20
|
npm_install_pid = spawn('npm', 'install', chdir: @npm_cwd)
|
21
21
|
Process.wait(npm_install_pid)
|
22
|
-
fail '
|
22
|
+
fail 'Failed to install the lambda startup' if ($CHILD_STATUS.exitstatus != 0)
|
23
23
|
end
|
24
24
|
|
25
25
|
def add_aws_sdk
|
@@ -31,6 +31,7 @@ module LambdaRunner
|
|
31
31
|
if opts[:timeout] == nil
|
32
32
|
opts[:timeout] = '30000'
|
33
33
|
end
|
34
|
+
@cover = opts[:cover]
|
34
35
|
install_deps
|
35
36
|
#copy over aws sdk only if it is not already there
|
36
37
|
if !File.directory?("#{File.dirname(@module_path)}/node_modules/aws-sdk")
|
@@ -38,9 +39,17 @@ module LambdaRunner
|
|
38
39
|
end
|
39
40
|
# start node in a way that emulates how it's run in production
|
40
41
|
cmd = ['node']
|
41
|
-
cmd = [
|
42
|
+
cmd = [
|
43
|
+
File.join(@npm_cwd, 'node_modules/.bin/nyc'),
|
44
|
+
'--cwd ', File.dirname(@module_path),
|
45
|
+
'--reporter=lcov',
|
46
|
+
'--report-dir ', File.join(Dir.pwd, 'coverage'),
|
47
|
+
'--temp-dir ', File.join(Dir.pwd, 'coverage', 'temp'),
|
48
|
+
'node'
|
49
|
+
] if opts[:cover]
|
42
50
|
cmd += [File.join(@npm_cwd, 'startup.js'), '-p', @port.to_s, '-m', @module_path, '-h', @name, '-t', opts[:timeout]]
|
43
51
|
@proc = ProcessHelper::ProcessHelper.new(print_lines: true)
|
52
|
+
puts cmd.join(' ')
|
44
53
|
@proc.start(cmd, 'Server running at http')
|
45
54
|
end
|
46
55
|
|
@@ -59,7 +68,6 @@ module LambdaRunner
|
|
59
68
|
when 200 then sleep(0.1)
|
60
69
|
when 201 then return data
|
61
70
|
when 500 then fail data
|
62
|
-
when 502 then fail data
|
63
71
|
when 504 then fail 'timeout'
|
64
72
|
else fail "unknown response #{response.code}"
|
65
73
|
end
|
@@ -67,7 +75,18 @@ module LambdaRunner
|
|
67
75
|
end
|
68
76
|
|
69
77
|
def stop
|
78
|
+
puts "Stopping Lambda Server"
|
70
79
|
RestClient.delete(url)
|
80
|
+
@proc.kill
|
81
|
+
|
82
|
+
# TODO currently coverage is not working on other projects
|
83
|
+
cmd = [
|
84
|
+
File.join(@npm_cwd, 'node_modules/.bin/nyc'),
|
85
|
+
'report',
|
86
|
+
'--report-dir ', File.join(Dir.pwd, 'coverage'),
|
87
|
+
'--temp-dir ', File.join(Dir.pwd, 'coverage', 'temp'),
|
88
|
+
]
|
89
|
+
system(cmd.join(' ')) if @cover
|
71
90
|
end
|
72
91
|
end
|
73
92
|
|
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
require_relative '../lib/lambda_runner'
|
3
3
|
|
4
|
-
|
4
|
+
|
5
|
+
shared_examples "AWS Lambda: " do |lambda_file|
|
5
6
|
|
6
7
|
before(:all) do
|
7
|
-
test_js = File.expand_path(
|
8
|
-
@under_test = LambdaRunner::Runner.new(test_js, "
|
8
|
+
test_js = File.expand_path(lambda_file, File.dirname(__FILE__))
|
9
|
+
@under_test = LambdaRunner::Runner.new(test_js, "handler")
|
9
10
|
@under_test.start
|
10
11
|
end
|
11
12
|
|
@@ -13,15 +14,23 @@ describe LambdaRunner::Runner do
|
|
13
14
|
@under_test.stop
|
14
15
|
end
|
15
16
|
|
16
|
-
it "should emulate
|
17
|
+
it "should emulate - success" do
|
17
18
|
r = @under_test.process_event({ succeed: { delay: 50, result: "ohai" } })
|
18
19
|
expect(r).to eq("ohai")
|
19
20
|
end
|
20
21
|
|
21
|
-
it "should emulate
|
22
|
+
it "should emulate - failure" do
|
22
23
|
expect {
|
23
24
|
@under_test.process_event({ fail: { delay: 50, err: "oh noes" } })
|
24
|
-
}.to raise_error("oh noes")
|
25
|
+
}.to raise_error("Error: oh noes")
|
25
26
|
end
|
26
27
|
|
27
28
|
end
|
29
|
+
|
30
|
+
describe LambdaRunner::Runner do
|
31
|
+
|
32
|
+
it_should_behave_like "AWS Lambda: ", "test_callback.js"
|
33
|
+
it_should_behave_like "AWS Lambda: ", "test_promise.js"
|
34
|
+
it_should_behave_like "AWS Lambda: ", "test_async.js"
|
35
|
+
|
36
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-lambda-runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- andrew wheat
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2018-11-21 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: process-helper
|
@@ -145,6 +145,7 @@ executables: []
|
|
145
145
|
extensions: []
|
146
146
|
extra_rdoc_files: []
|
147
147
|
files:
|
148
|
+
- js/package-lock.json
|
148
149
|
- js/package.json
|
149
150
|
- js/request.js
|
150
151
|
- js/startup.js
|
@@ -177,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
178
|
version: '0'
|
178
179
|
requirements: []
|
179
180
|
rubyforge_project:
|
180
|
-
rubygems_version: 2.5.
|
181
|
+
rubygems_version: 2.5.2.2
|
181
182
|
signing_key:
|
182
183
|
specification_version: 4
|
183
184
|
summary: AWS Lambda testing helper
|