faux-lambda 0.5.1 → 0.6.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 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