aws-lambda-runner 1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0bcd4937c0e10b5e7a0601406c1eb22f36da5d85
4
+ data.tar.gz: 105b4d4144d2bd73de84bb9f50ce02e63087b0f2
5
+ SHA512:
6
+ metadata.gz: 51002e44f87ac3d99a319a1495a62a936c00ea0cd1cc9fe8fb485d66e01a667f235a9eee4d9a1b45115e6963d8f2ffac4c084a74c08c134bb803673114e6e8a6
7
+ data.tar.gz: d650889fb646cce2254ab8c9a25a9a5e57584c41ef2cdd8bc94c086b522616301db56ef31103340b65193e00a9a35a60ee37834f2b1ba6dc36aca5309fa246d0
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "lambda-helper",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "startup.js",
6
+ "scripts": {
7
+ "test": "mocha"
8
+ },
9
+ "author": "",
10
+ "license": " ",
11
+ "devDependencies": {
12
+ "jshint": "^2.5.11",
13
+ "mocha": "^2.1.0",
14
+ "mocha-jshint": "0.0.9",
15
+ "mock-res": "^0.2.1",
16
+ "should": "^4.6.0"
17
+ },
18
+ "dependencies": {
19
+ "aws-sdk": "^2.1.34",
20
+ "istanbul": "^0.3.6",
21
+ "mock-req": "^0.1.0",
22
+ "stdio": "^0.2.7"
23
+ }
24
+ }
@@ -0,0 +1,60 @@
1
+
2
+ var url = require('url');
3
+
4
+ var next_id = 0;
5
+ var done = {};
6
+ var errors = {};
7
+ var timeout = {};
8
+
9
+ exports.request = function(req, res, opts, handler) {
10
+ if (req.method === 'POST') {
11
+ var id = next_id;
12
+ var output = '';
13
+ next_id += 1;
14
+ req.on('data', function(chunk) {
15
+ setTimeout(function() {
16
+ if (!done[id]) {
17
+ timeout[id] = true;
18
+ }
19
+ }, opts.timeout);
20
+ output += chunk.toString()
21
+ });
22
+ req.on('end', function(chunk) {
23
+ handler(JSON.parse(output), {
24
+ done: function(err, message) {
25
+ if (err) {
26
+ errors[id] = err;
27
+ console.warn('Error:', err);
28
+ }
29
+ console.info('Finished:', message);
30
+ done[id] = true;
31
+ }
32
+ });
33
+ });
34
+ res.writeHead(200, {'Content-Type': 'text/plain'});
35
+ res.end(String(id));
36
+ } else if (req.method === 'DELETE') {
37
+ res.writeHead(202, {'Content-Type': 'text/plain'});
38
+ var terminationMessage = 'Terminating server at http://[localhost]:' + opts.port + ' for ' + opts['module-path'] + ' / ' + opts.handler;
39
+ res.end(terminationMessage + '\n');
40
+ console.info(terminationMessage);
41
+ server.close();
42
+ } else if (req.method === 'GET') {
43
+ var request_id = parseInt(url.parse(req.url, true).query.id);
44
+ var status = 200;
45
+ var output = '';
46
+ if (timeout[request_id]) {
47
+ status = 504;
48
+ } else if (errors[request_id]) {
49
+ status = 502;
50
+ output = errors[request_id];
51
+ } else if (done[request_id]) {
52
+ status = 201;
53
+ }
54
+ res.writeHead(status, {'Content-Type': 'text/plain'});
55
+ res.end(output + '\n');
56
+ } else {
57
+ res.writeHead(500, {'Content-Type': 'text/plain'});
58
+ res.end('Not implemented: ' + req.method + '\n');
59
+ }
60
+ };
@@ -0,0 +1,19 @@
1
+
2
+
3
+ var http = require('http');
4
+ var stdio = require('stdio');
5
+ var request = require('./request.js');
6
+
7
+ var opts = stdio.getopt({
8
+ 'port': {mandatory: true, args: 1, key: 'p', description: 'Listen port'},
9
+ 'module-path': {mandatory: true, args: 1, key: 'm', description: 'Path to the lambda module'},
10
+ 'handler': {mandatory: true, args: 1, key: 'h', description: 'handler function to call'},
11
+ 'timeout': {mandatory: true, args: 1, key: 't', description: 'timeout for handler function'}
12
+ });
13
+ console.info(opts);
14
+
15
+ var module = require(opts['module-path']);
16
+ var server = http.createServer(function (req, res) {
17
+ request.request(req, res, opts, module[opts.handler]);
18
+ }).listen(opts.port);
19
+ console.info('Server running at http://[localhost]:' + opts.port + ' for ' + opts['module-path'] + ' / ' + opts.handler);
@@ -0,0 +1,100 @@
1
+ require 'process-helper'
2
+ require 'rest-client'
3
+ require 'json'
4
+ require 'English'
5
+ require 'fileutils'
6
+
7
+ def load_json(name)
8
+ File.open(File.join(File.dirname(__FILE__), name)) { |file| return JSON.load(file) }
9
+ end
10
+
11
+ # runs a nodejs lambda program so the s3 events can be sent to it via http post
12
+ module LambdaRunner
13
+ # abstract for running the program
14
+ class Runner
15
+ def initialize(module_path, name)
16
+ @module_path = module_path
17
+ @name = name
18
+ @port = 8897
19
+ end
20
+
21
+ def install_deps
22
+ @npm_cwd = File.expand_path('../../js/', __FILE__)
23
+ STDOUT.puts("trying to use npm install in #{@npm_cwd}")
24
+ npm_install_pid = spawn('npm', 'install', chdir: @npm_cwd)
25
+ Process.wait(npm_install_pid)
26
+ fail 'failed to install the lambda startup' if ($CHILD_STATUS.exitstatus != 0)
27
+ end
28
+
29
+ def add_aws_sdk
30
+ STDOUT.puts("Copying aws-sdk into the lambda function's node_modules.")
31
+ # cp -r File.expand_path(../../js/node_modules/aws-sdk, __FILE__) $(dirname @module_path)/node_modules
32
+ FileUtils.cp_r File.expand_path('../../js/node_modules/aws-sdk', __FILE__), "#{File.dirname(@module_path)}/node_modules"
33
+ end
34
+
35
+ def start(opts = { cover: true })
36
+ install_deps
37
+ add_aws_sdk
38
+ # start node in a way that emulates how it's run in production
39
+ cmd = ['node']
40
+ cmd = [File.join(@npm_cwd, 'node_modules/.bin/istanbul'), 'cover', '--root', File.dirname(@module_path), '--'] if opts[:cover]
41
+ cmd += [File.join(@npm_cwd, 'startup.js'), '-p', @port.to_s, '-m', @module_path, '-h', @name, '-t', '1000']
42
+ @proc = ProcessHelper::ProcessHelper.new(print_lines: true)
43
+ @proc.start(cmd, 'Server running at http')
44
+ end
45
+
46
+ def url
47
+ "http://localhost:#{@port}/"
48
+ end
49
+
50
+ def wait(response)
51
+ case response.code
52
+ when 201 then false
53
+ when 200 then true
54
+ when 504 then fail 'timeout'
55
+ when 502 then fail response
56
+ else fail "unknown response #{response.code}"
57
+ end
58
+ end
59
+
60
+ def send(message)
61
+ id = RestClient.post(url, message, content_type: :json).to_str
62
+ loop do
63
+ wait(RestClient.get(url, params: { id: id })) || break
64
+ sleep(0.1)
65
+ end
66
+ end
67
+
68
+ def stop
69
+ RestClient.delete(url)
70
+ end
71
+ end
72
+
73
+ # aws events
74
+ class Events
75
+ def self.s3_event(bucket, key, local_path)
76
+ event = load_json('sample_req.json')
77
+ event['Records'].each do |record|
78
+ record['file'] = { 'path' => local_path }
79
+ record['s3']['bucket'].update('name' => bucket,
80
+ 'arn' => 'arn:aws:s3:::' + bucket)
81
+ record['s3']['object']['key'] = key
82
+ record
83
+ end
84
+ event.to_json
85
+ end
86
+
87
+ def self.sns_event(topicArn, messageId, timestamp, messageBody)
88
+ event = load_json('sample_sns_req.json')
89
+ event['Records'].each do |record|
90
+ record['Sns']['topicArn'] = topicArn
91
+ record['Sns']['messageId'] = messageId
92
+ record['Sns']['timestamp'] = timestamp
93
+ record['Sns']['messageBody'] = messageBody
94
+ end
95
+ event.to_json
96
+ end
97
+ end
98
+ end
99
+
100
+ # vi: tabstop=2:softtabstop=2:shiftwidth=2:expandtab
@@ -0,0 +1,37 @@
1
+ {
2
+ "Records": [
3
+ {
4
+ "eventVersion": "2.0",
5
+ "eventSource": "aws:s3",
6
+ "awsRegion": "eu-west-1",
7
+ "eventTime": "1970-01-01T00:00:00.000Z",
8
+ "eventName": "ObjectCreated:Put",
9
+ "userIdentity": {
10
+ "principalId": "1"
11
+ },
12
+ "requestParameters": {
13
+ "sourceIPAddress": "1"
14
+ },
15
+ "responseElements": {
16
+ "x-amz-request-id": "1",
17
+ "x-amz-id-2": "1"
18
+ },
19
+ "s3": {
20
+ "s3SchemaVersion": "1.0",
21
+ "configurationId": "1",
22
+ "bucket": {
23
+ "name": "example-bucket",
24
+ "ownerIdentity": {
25
+ "principalId": "1"
26
+ },
27
+ "arn": "arn:aws:s3:::example-bucket"
28
+ },
29
+ "object": {
30
+ "key": "key/to/file.xml",
31
+ "size": 1,
32
+ "eTag": "1"
33
+ }
34
+ }
35
+ }
36
+ ]
37
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "Records":[
3
+ {
4
+ "EventSource":"aws:sns",
5
+ "EventVersion": "1.0",
6
+ "EventSubscriptionArn": "arn:aws:sns:eu-west-1:1:lambda_topic:0123456789abcd",
7
+ "Sns":{
8
+ "Type": "Notification",
9
+ "MessageId":"95df01b4-ee98-5cb9-9903-4c221d41eb5e",
10
+ "TopicArn":"arn:aws:sns:eu-west-1:123456789012:lambda_topic",
11
+ "Subject":"TestInvoke",
12
+ "Message":"<message payload>",
13
+ "Timestamp":"2015-04-02T07:36:57.451Z",
14
+ "SignatureVersion":"1",
15
+ "Signature":"r0Dc5YVHuAglGcmZ9Q7SpFb2PuRDFmJNprJlAEEk8CzSq9Btu8U7dxOu++uU",
16
+ "SigningCertUrl":"http://sns.eu-west-1.amazonaws.com/SimpleNotificationService-d6d679a1d18e95c2f9ffcf11f4f9e198.pem",
17
+ "UnsubscribeUrl":"http://cloudcast.amazon.com/?foo",
18
+ "MessageAttributes":{"key":{"Type":"String","Value":"value"}}
19
+ }
20
+ }
21
+ ]
22
+ }
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aws-lambda-runner
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - andrew wheat
8
+ - tristan hill
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-01-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: process-helper
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rest-client
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: file_utils
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rubocop
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: minitest
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '5.0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '5.0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rake
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '10.0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '10.0'
98
+ description: Trigger AWS Lambda functions without deploying to AWS
99
+ email: []
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - js/package.json
105
+ - js/request.js
106
+ - js/startup.js
107
+ - lib/lambda_runner.rb
108
+ - lib/sample_req.json
109
+ - lib/sample_sns_req.json
110
+ homepage: https://github.com/bbc/aws-lambda-runner
111
+ licenses:
112
+ - Apache 2
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.2.2
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: AWS Lambda testing helper
134
+ test_files: []