faux-lambda 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 87764a85a01fcb5d17b6f530c6bd937351b250ba
4
- data.tar.gz: 812b5811990bfe757370e139303d4635ad3261c6
3
+ metadata.gz: b3624a8f9bbfff9b594edf213d4f9879c1b38cba
4
+ data.tar.gz: ecc9b19c5c464d049ec7fc6b3281fda34d1b56d1
5
5
  SHA512:
6
- metadata.gz: bc6796056d6448cc034e558d353804526ea77e6c33550a575caacd7f20b0ca2a4895efd8eff99523172dcd8d7f38ca1006e96de72a8e23ff4649cdca28e784e8
7
- data.tar.gz: 9c1b1505f25c727db6f60636d6bf80c70bfd4bed1102aa05eef05b91f710c25349fb20e16a5a4a8e68be044ae4ac9c46d988f2559ea5ba0d8d2808ab1bb9c03b
6
+ metadata.gz: c585de977a32487ef44156bda0feeca5b195b58b2b7966c231ac7f366241f4f2240f0d56338f6ae492651c81c22775530b548f999c751eff824912304948cc18
7
+ data.tar.gz: 24a329756a002fc97ed78127248f90df81e68b059c074535295c20c71e268143bc5cdf2c4cbc8c85cbea550f106641b4d3bb220a150f7275db9df5ab8ac3f567
@@ -1,92 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rack'
4
- require 'webrick'
5
- require 'optparse'
6
- require_relative '../lib/faux_lambda/version'
3
+ require 'faux_lambda'
4
+ require 'faux_lambda/cli_handler'
7
5
 
8
- options = {
9
- port: 9123,
10
- bind: '127.0.0.1',
11
- }
6
+ cli_handler = FauxLambda::CliHandler.new
7
+ cli_handler.parse_options(ARGV)
12
8
 
13
- functions = {
14
- default: {
15
- invocation_type: nil,
16
- replies: []
17
- }
18
- }
19
-
20
- current_function = :default
21
- parser = OptionParser.new do |opts|
22
- opts.banner = "AWS Lambda debugging endpoint, version #{FauxLambda::VERSION}."
23
- opts.separator('')
24
- opts.separator('Usage: faux-lambda --reply "Hello world!"')
25
- opts.separator('Query specifiers:')
26
- opts.on('--function name', '-f name', 'Name of function to expect, optionally with :<qualifier>') do |function_name|
27
- current_function = function_name
28
- functions[current_function] = {replies: []}
29
- end
30
- opts.separator('Reply specifiers:')
31
- opts.on('--reply payload', '-r payload', 'Data to respond with') do |payload|
32
- functions[current_function][:replies] << payload
33
- end
34
- opts.on('--fail', 'AWS Lambda framework gives 400') do
35
- functions[current_function][:replies] << :fail
36
- end
37
- end
38
- parser.parse!
39
-
40
- def reply_from(replies)
41
- if replies.size > 1
42
- replies.shift
43
- elsif replies.size == 1
44
- replies.last
45
- else
46
- nil
47
- end
48
- end
49
-
50
- def function_data(functions, function_name, qualifier)
51
- qualified_function_name = if qualifier
52
- "#{function_name}:#{qualifier}"
53
- end
54
- functions[qualified_function_name] || functions[function_name] || functions[:default]
55
- end
56
-
57
- def log(function_name, qualifier, payload, status_code, reply)
58
- qualifier ||= "$LATEST"
59
- puts "#{function_name}:#{qualifier} called with #{payload}, replying #{status_code}: #{reply}"
60
- end
61
-
62
- app = Proc.new do |env|
63
- _, version, _, function_name, _ = env['REQUEST_PATH'].split('/')
64
- raise "Unknown version #{version}" unless version == '2015-03-31'
65
- qs = Rack::Utils.parse_nested_query(env["QUERY_STRING"])
66
- qualifier = qs["Qualifier"]
67
- payload = env['rack.input'].read
68
-
69
- data = function_data(functions, function_name, qualifier)
70
- reply = reply_from(data[:replies])
71
- if reply.nil?
72
- status_code = '404'
73
- reply = 'Not found'
74
- elsif reply == :fail
75
- status_code = '400'
76
- reply = 'Failed'
77
- else
78
- status_code = '200'
79
- end
80
-
81
- log(function_name, qualifier, payload, status_code, reply)
82
- headers = {'Content-Type' => 'application/octet-stream'}
83
- [status_code, headers, [reply]]
9
+ begin
10
+ faux = FauxLambda.new(cli_handler.options)
11
+ faux.handle(&cli_handler.method(:handler))
12
+ rescue Interrupt
13
+ exit 130
84
14
  end
85
-
86
- Rack::Handler::WEBrick.run(
87
- app,
88
- Port: options[:port],
89
- BindAddress: options[:bind],
90
- Logger: WEBrick::Log.new($stderr, WEBrick::Log::ERROR),
91
- AccessLog: [['/dev/null', WEBrick::AccessLog::COMMON_LOG_FORMAT]]
92
- )
@@ -0,0 +1,59 @@
1
+ require 'rack'
2
+ require 'webrick'
3
+
4
+ class FauxLambda
5
+ Call = Struct.new(
6
+ :function_name,
7
+ :qualifier,
8
+ :payload
9
+ )
10
+
11
+ def initialize(options)
12
+ @bind = options[:bind] || '127.0.0.1'
13
+ @port = options[:port] || 9123
14
+ end
15
+
16
+ def handle(&block)
17
+ Rack::Handler::WEBrick.run(
18
+ lambda do |env|
19
+ _, version, _, function_name, _ = env['REQUEST_PATH'].split('/')
20
+ raise "Unknown version #{version}" unless version == '2015-03-31'
21
+ qs = Rack::Utils.parse_nested_query(env["QUERY_STRING"])
22
+ qualifier = qs["Qualifier"]
23
+ payload = env['rack.input'].read
24
+
25
+ call = Call.new(function_name, qualifier, payload)
26
+ begin
27
+ reply = block.call(call)
28
+ if reply.nil?
29
+ status_code = '404'
30
+ reply = 'Not found'
31
+ elsif reply == :fail
32
+ status_code = '400'
33
+ reply = 'Failed'
34
+ else
35
+ status_code = '200'
36
+ end
37
+ log(function_name, qualifier, payload, status_code, reply)
38
+ rescue => e
39
+ reply = ''
40
+ log(function_name, qualifier, payload, '200', e)
41
+ end
42
+
43
+ headers = {'Content-Type' => 'application/octet-stream'}
44
+ [status_code, headers, [reply]]
45
+ end,
46
+ Host: @bind,
47
+ Port: @port,
48
+ Logger: WEBrick::Log.new($stderr, WEBrick::Log::ERROR),
49
+ AccessLog: [['/dev/null', WEBrick::AccessLog::COMMON_LOG_FORMAT]]
50
+ )
51
+ end
52
+
53
+ private
54
+
55
+ def log(function_name, qualifier, payload, status_code, reply)
56
+ qualifier ||= "$LATEST"
57
+ puts "#{function_name}:#{qualifier} called with '#{payload}', replying #{status_code}: '#{reply}'"
58
+ end
59
+ end
@@ -0,0 +1,78 @@
1
+ require 'optparse'
2
+
3
+ class FauxLambda::CliHandler
4
+ attr_reader :options
5
+
6
+ def initialize
7
+ @functions = {
8
+ default: {
9
+ invocation_type: nil,
10
+ replies: []
11
+ }
12
+ }
13
+ @options = {}
14
+ end
15
+
16
+ def parse_options(argv)
17
+ current_function = :default
18
+ parser = OptionParser.new do |opts|
19
+ opts.banner = "AWS Lambda debugging endpoint, version #{FauxLambda::VERSION}."
20
+ opts.separator('')
21
+ opts.separator('Usage: faux-lambda --reply "Hello world!"')
22
+ opts.separator('Query specifiers:')
23
+ opts.on('--function name', '-f name', 'Name of function to expect, optionally with :<qualifier>') do |function_name|
24
+ current_function = function_name
25
+ @functions[current_function] = {replies: []}
26
+ end
27
+ opts.separator('Reply specifiers:')
28
+ opts.on('--reply payload', '-r payload', 'Data to respond with') do |payload|
29
+ @functions[current_function][:replies] << lambda {|_| payload }
30
+ end
31
+ opts.on('--handler script.rb', '-h script.rb', 'Ruby script is eval:ed to produce reply') do |script|
32
+ @functions[current_function][:replies] << make_handler(script)
33
+ end
34
+ opts.on('--fail', 'AWS Lambda framework gives 400') do
35
+ @functions[current_function][:replies] << lambda {|_| :fail }
36
+ end
37
+ opts.separator('Control options')
38
+ opts.on('--port port', 'TCP port to bind, 9123 by default') do |port|
39
+ @options[:port] = port
40
+ end
41
+ opts.on('--bind address', 'Interface to bind to, localhost by default') do |bindaddress|
42
+ @options[:bind] = bindaddress
43
+ end
44
+ end
45
+ parser.parse!(argv)
46
+ end
47
+
48
+ def handler(call)
49
+ data = function_data(call)
50
+ reply_from(data[:replies], call)
51
+ end
52
+
53
+ private
54
+
55
+ def make_handler(script)
56
+ code = File.read(script)
57
+ lambda do |call|
58
+ eval(code, binding(), script)
59
+ end
60
+ end
61
+
62
+ def reply_from(replies, call)
63
+ if replies.size > 1
64
+ replies.shift.call(call)
65
+ elsif replies.size == 1
66
+ replies.last.call(call)
67
+ else
68
+ nil
69
+ end
70
+ end
71
+
72
+ def function_data(call)
73
+ qualified_function_name = if call.qualifier
74
+ "#{call.function_name}:#{call.qualifier}"
75
+ end
76
+ @functions[qualified_function_name] || @functions[call.function_name] || @functions[:default]
77
+ end
78
+ end
@@ -1,3 +1,3 @@
1
- module FauxLambda
2
- VERSION = '0.5.1'
1
+ class FauxLambda
2
+ VERSION = '0.6.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faux-lambda
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anders Qvist
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-01 00:00:00.000000000 Z
11
+ date: 2017-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -33,12 +33,9 @@ executables:
33
33
  extensions: []
34
34
  extra_rdoc_files: []
35
35
  files:
36
- - ".gitignore"
37
- - Gemfile
38
- - Gemfile.lock
39
- - README.md
40
36
  - bin/faux-lambda
41
- - faux-lambda.gemspec
37
+ - lib/faux_lambda.rb
38
+ - lib/faux_lambda/cli_handler.rb
42
39
  - lib/faux_lambda/version.rb
43
40
  homepage: https://github.com/bittrance/faux-lambda
44
41
  licenses:
data/.gitignore DELETED
@@ -1,2 +0,0 @@
1
- .bundle/
2
- .ruby-version
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
- source "https://rubygems.org"
3
-
4
- gemspec
@@ -1,19 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- faux-lambda (0.5.1)
5
- rack (~> 2.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- rack (2.0.3)
11
-
12
- PLATFORMS
13
- ruby
14
-
15
- DEPENDENCIES
16
- faux-lambda!
17
-
18
- BUNDLED WITH
19
- 1.15.4
data/README.md DELETED
@@ -1,78 +0,0 @@
1
- # Faux Lambda server for testing
2
-
3
- Lambda service mock implementation for testing and exploration. It starts a simple web server (default is http://localhost:9123) and processes Lambda invocation requests. It can be used both programmatically and as a command line tool.
4
-
5
- ## As a command line tool
6
-
7
- In its simplest form:
8
- ```
9
- gem install faux-lambda
10
- faux-lambda --reply='{}' &
11
- aws --endpoint http://localhost:9123 lambda invoke --function-name whatever /dev/stdout
12
- ```
13
-
14
- The CLI can also simulate specific scenarios:
15
- ```
16
- $ faux-lambda --function=foo --reply='{}' --function=bar --reply='{}' --reply='{}' --fail &
17
- $ aws --endpoint http://localhost:12345 lambda invoke --function-name foo /dev/stdout
18
- Called foo with ...
19
- {}
20
- ```
21
- Here, each call to function `foo` gets reply `{}`, first call to function `bar` gets `{}`, second gets `{}` and third will fail.
22
-
23
- You can also pipe in replies from `stdin`, one reply per object (may contain newlines):
24
- ```
25
- faux-lambda --function=foo <<<EOF
26
- {}
27
- {}
28
- EOF
29
- ```
30
- In this mode, the CLI will accept only one function, but may prove useful where there are numerous or large replies.
31
-
32
- ```
33
- Usage: faux-lambda [options]
34
- Query specifiers:
35
- --function-name=regex
36
- --async Require invocation to be async
37
- --sync Require invocation to be sync
38
- Reply specifiers:
39
- --reply=json Send this reply
40
- --fail ...
41
- Various:
42
- --quiet Don't log sent and received messages
43
- --version
44
- ```
45
-
46
- ## faux-lambda as a library
47
-
48
- You can use `faux-lambda` programmatically too, like so:
49
- ```
50
- require `faux-lambda`
51
- lambda = FauxLambda.new(port: 12345).handle do |call|
52
- return if call.async
53
- if call.function_name == 'foo'
54
- '{}'
55
- end
56
- end
57
-
58
- Aws::Lambda.new(endpoint: lambda.endpoint).invoke(...)
59
- ```
60
-
61
- ## faux-lambda in your specs
62
-
63
- Or in your specs as if FauxLambda were an `rspec-mocks` double:
64
- ```
65
- let(:lambda) { FauxLambda.new }
66
- before do
67
- allow(lambda).to receive(:incrementer).and_return(43)
68
- end
69
-
70
- subject do
71
- ThingUnderTest.new(lambda.endpoint).do_math(42)
72
- end
73
-
74
- it 'invokes lambda and returns its value' do
75
- expect(subject).to equal(43)
76
- expect(lambda).to have_received(:incrementer).with(value: 42)
77
- end
78
- ```
@@ -1,19 +0,0 @@
1
- require File.expand_path('../lib/faux_lambda/version', __FILE__)
2
-
3
- Gem::Specification.new do |spec|
4
- spec.name = 'faux-lambda'
5
- spec.version = FauxLambda::VERSION
6
- spec.summary = 'faux-lambda provides a simple tool to mock AWS Lambda endpoint'
7
- spec.description = 'faux-lambda is a toolbox to make it easier to develop client that call AWS Lambda functions. A simple CLI lets you mock AWS Lambda and specify replies for specific function as well as simulate AWS Lambda framework failures.'
8
- spec.authors = ['Anders Qvist']
9
- spec.email = 'quest@lysator.liu.se'
10
- spec.homepage = 'https://github.com/bittrance/faux-lambda'
11
- spec.license = 'MIT'
12
-
13
- spec.executables = ['faux-lambda']
14
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(/^spec/) }
15
-
16
- spec.required_ruby_version = '>= 2.0.0'
17
-
18
- spec.add_runtime_dependency 'rack', '~> 2.0'
19
- end