lamby 1.0.0 → 2.1.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/cicd.yml +17 -0
  3. data/.gitignore +1 -1
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +51 -0
  6. data/Dockerfile +12 -0
  7. data/Gemfile +2 -0
  8. data/Gemfile.lock +94 -79
  9. data/README.md +10 -4
  10. data/Rakefile +1 -0
  11. data/bin/_setup +6 -0
  12. data/bin/_test +6 -0
  13. data/bin/bootstrap +3 -17
  14. data/bin/setup +3 -3
  15. data/bin/test +6 -3
  16. data/bin/update +2 -2
  17. data/docker-compose.yml +14 -0
  18. data/lamby.gemspec +1 -2
  19. data/lib/lamby.rb +7 -3
  20. data/lib/lamby/handler.rb +16 -3
  21. data/lib/lamby/logger.rb +13 -9
  22. data/lib/lamby/rack.rb +11 -9
  23. data/lib/lamby/rack_alb.rb +11 -14
  24. data/lib/lamby/rack_http.rb +80 -0
  25. data/lib/lamby/{rack_api.rb → rack_rest.rb} +7 -3
  26. data/lib/lamby/ssm_parameter_store.rb +3 -3
  27. data/lib/lamby/templates.rake +4 -3
  28. data/lib/lamby/templates/{application_load_balancer.rb → alb.rb} +1 -1
  29. data/lib/lamby/templates/{application_load_balancer → alb}/app.rb +0 -0
  30. data/lib/lamby/templates/{application_load_balancer → alb}/build +3 -3
  31. data/lib/lamby/templates/{application_load_balancer → alb}/deploy +1 -1
  32. data/lib/lamby/templates/{application_load_balancer → alb}/template.yaml +1 -1
  33. data/lib/lamby/templates/{api_gateway.rb → http.rb} +2 -2
  34. data/lib/lamby/templates/{api_gateway → http}/app.rb +1 -1
  35. data/lib/lamby/templates/{api_gateway → http}/build +3 -3
  36. data/lib/lamby/templates/{api_gateway → http}/deploy +1 -1
  37. data/lib/lamby/templates/http/template.yaml +48 -0
  38. data/lib/lamby/templates/rest.rb +25 -0
  39. data/lib/lamby/templates/rest/app.rb +10 -0
  40. data/lib/lamby/templates/rest/build +23 -0
  41. data/lib/lamby/templates/rest/deploy +22 -0
  42. data/lib/lamby/templates/{api_gateway → rest}/template.yaml +2 -2
  43. data/lib/lamby/templates/shared.rb +3 -1
  44. data/lib/lamby/version.rb +1 -1
  45. data/vendor/.keep +0 -0
  46. metadata +29 -37
  47. data/.python-version +0 -1
  48. data/.travis.yml +0 -17
  49. data/Brewfile +0 -5
  50. data/Pipfile +0 -13
  51. data/Pipfile.lock +0 -370
data/bin/setup CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
-
3
2
  set -e
4
3
 
5
- bundle install
6
- pipenv install
4
+ docker-compose run \
5
+ cicd \
6
+ ./bin/_setup
data/bin/test CHANGED
@@ -1,5 +1,8 @@
1
- #!/usr/bin/env bash
2
-
1
+ #!/bin/bash
3
2
  set -e
4
3
 
5
- bundle exec rake test
4
+ export RAILS_ENV="test"
5
+
6
+ docker-compose run \
7
+ cicd \
8
+ ./bin/_test
data/bin/update CHANGED
@@ -1,7 +1,7 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
 
3
3
  set -e
4
4
 
5
- pipenv --rm
5
+ rm -rf ./vendor/bundle
6
6
 
7
7
  ./bin/setup
@@ -0,0 +1,14 @@
1
+ version: '3.7'
2
+ services:
3
+ cicd:
4
+ build: .
5
+ environment:
6
+ - AWS_PROFILE=${AWS_PROFILE-default}
7
+ - RAILS_ENV=${RAILS_ENV-test}
8
+ - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION-us-east-1}
9
+ - SAM_CLI_TELEMETRY=0
10
+ - DIDPWD=${PWD}
11
+ volumes:
12
+ - ~/.aws:/root/.aws:delegated
13
+ - .:/var/task:delegated
14
+ - /var/run/docker.sock:/var/run/docker.sock
@@ -19,12 +19,11 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
  spec.add_dependency 'rack'
22
- spec.add_dependency 'rails'
23
22
  spec.add_development_dependency 'aws-sdk-ssm'
24
23
  spec.add_development_dependency 'bundler'
25
24
  spec.add_development_dependency 'rake'
26
25
  spec.add_development_dependency 'minitest'
26
+ spec.add_development_dependency 'minitest-focus'
27
27
  spec.add_development_dependency 'mocha'
28
28
  spec.add_development_dependency 'pry'
29
- spec.add_development_dependency 'sqlite3'
30
29
  end
@@ -6,11 +6,15 @@ require 'lamby/version'
6
6
  require 'lamby/sam_helpers'
7
7
  require 'lamby/rack'
8
8
  require 'lamby/rack_alb'
9
- require 'lamby/rack_api'
9
+ require 'lamby/rack_rest'
10
+ require 'lamby/rack_http'
10
11
  require 'lamby/debug'
11
12
  require 'lamby/handler'
12
- require 'rails/railtie'
13
- require 'lamby/railtie'
13
+
14
+ if defined?(Rails)
15
+ require 'rails/railtie'
16
+ require 'lamby/railtie'
17
+ end
14
18
 
15
19
  module Lamby
16
20
 
@@ -44,14 +44,27 @@ module Lamby
44
44
  self
45
45
  end
46
46
 
47
+ def base64_encodeable?
48
+ @headers && (
49
+ @headers['Content-Transfer-Encoding'] == 'binary' ||
50
+ @headers['X-Lamby-Base64'] == '1'
51
+ )
52
+ end
53
+
54
+ def body64
55
+ Base64.strict_encode64(body)
56
+ end
57
+
47
58
  private
48
59
 
49
60
  def rack
50
61
  @rack ||= case @options[:rack]
51
- when :api
52
- Lamby::RackApi.new @event, @context
53
- else
62
+ when :rest, :api
63
+ Lamby::RackRest.new @event, @context
64
+ when :alb
54
65
  Lamby::RackAlb.new @event, @context
66
+ else
67
+ Lamby::RackHttp.new @event, @context
55
68
  end
56
69
  end
57
70
 
@@ -1,19 +1,23 @@
1
1
  require 'logger'
2
2
 
3
- ENV['RAILS_LOG_TO_STDOUT'] = '1'
3
+ unless ENV['LAMBY_TEST']
4
4
 
5
- module Lamby
6
- module Logger
5
+ ENV['RAILS_LOG_TO_STDOUT'] = '1'
7
6
 
8
- def initialize(*args)
9
- args[0] = STDOUT
10
- super(*args)
11
- end
7
+ module Lamby
8
+ module Logger
9
+
10
+ def initialize(*args)
11
+ args[0] = STDOUT
12
+ super(*args)
13
+ end
12
14
 
15
+ end
13
16
  end
14
- end
15
17
 
16
- Logger.prepend Lamby::Logger
18
+ Logger.prepend Lamby::Logger
19
+
20
+ end
17
21
 
18
22
  # TODO: Railtie initializer
19
23
  # Rails.application.config.logger = ActiveSupport::TaggedLogging.new(
@@ -6,6 +6,7 @@ module Lamby
6
6
  LAMBDA_EVENT = 'lambda.event'.freeze
7
7
  LAMBDA_CONTEXT = 'lambda.context'.freeze
8
8
  HTTP_X_REQUESTID = 'HTTP_X_REQUEST_ID'.freeze
9
+ HTTP_COOKIE = 'HTTP_COOKIE'.freeze
9
10
 
10
11
  attr_reader :event, :context
11
12
 
@@ -22,14 +23,6 @@ module Lamby
22
23
  {}
23
24
  end
24
25
 
25
- def api?
26
- false
27
- end
28
-
29
- def alb?
30
- false
31
- end
32
-
33
26
  def multi_value?
34
27
  false
35
28
  end
@@ -70,7 +63,16 @@ module Lamby
70
63
  end
71
64
 
72
65
  def query_string
73
- @query_string ||= event['queryStringParameters'].try(:to_query)
66
+ @query_string ||= if event.key?('rawQueryString')
67
+ event['rawQueryString']
68
+ elsif event.key?('multiValueQueryStringParameters')
69
+ query = event['multiValueQueryStringParameters'] || {}
70
+ query.map do |key, value|
71
+ value.map{ |v| "#{key}=#{v}" }.join('&')
72
+ end.flatten.join('&')
73
+ else
74
+ event['queryStringParameters'].try(:to_query)
75
+ end
74
76
  end
75
77
 
76
78
  def base64_encoded?
@@ -53,20 +53,17 @@ module Lamby
53
53
  end
54
54
 
55
55
  def headers_multi
56
- (event['multiValueHeaders'] || {}).transform_values do |v|
57
- v.is_a?(Array) ? v.first : v
58
- end
59
- end
60
-
61
- def query_string
62
- @query_string ||= multi_value? ? query_string_multi : super
63
- end
64
-
65
- def query_string_multi
66
- query = event['multiValueQueryStringParameters'] || {}
67
- string = query.map do |key, value|
68
- value.map{ |v| "#{key}=#{v}" }.join('&')
69
- end.flatten.join('&')
56
+ Hash[(event['multiValueHeaders'] || {}).map do |k,v|
57
+ if v.is_a?(Array)
58
+ if k == 'x-forwarded-for'
59
+ [k, v.join(', ')]
60
+ else
61
+ [k, v.first]
62
+ end
63
+ else
64
+ [k,v]
65
+ end
66
+ end]
70
67
  end
71
68
 
72
69
  end
@@ -0,0 +1,80 @@
1
+ module Lamby
2
+ class RackHttp < Lamby::Rack
3
+
4
+ def response(handler)
5
+ if handler.base64_encodeable?
6
+ { isBase64Encoded: true, body: handler.body64 }
7
+ else
8
+ super
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def env_base
15
+ { ::Rack::REQUEST_METHOD => request_method,
16
+ ::Rack::SCRIPT_NAME => '',
17
+ ::Rack::PATH_INFO => path_info,
18
+ ::Rack::QUERY_STRING => query_string,
19
+ ::Rack::SERVER_NAME => server_name,
20
+ ::Rack::SERVER_PORT => server_port,
21
+ ::Rack::SERVER_PROTOCOL => server_protocol,
22
+ ::Rack::RACK_VERSION => ::Rack::VERSION,
23
+ ::Rack::RACK_URL_SCHEME => 'https',
24
+ ::Rack::RACK_INPUT => StringIO.new(body || ''),
25
+ ::Rack::RACK_ERRORS => $stderr,
26
+ ::Rack::RACK_MULTITHREAD => false,
27
+ ::Rack::RACK_MULTIPROCESS => false,
28
+ ::Rack::RACK_RUNONCE => false,
29
+ LAMBDA_EVENT => event,
30
+ LAMBDA_CONTEXT => context
31
+ }.tap do |env|
32
+ ct = content_type
33
+ cl = content_length
34
+ env['CONTENT_TYPE'] = ct if ct
35
+ env['CONTENT_LENGTH'] = cl if cl
36
+ end
37
+ end
38
+
39
+ def env_headers
40
+ super.tap do |hdrs|
41
+ if event['cookies'].present?
42
+ hdrs[HTTP_COOKIE] = event['cookies'].join('; ')
43
+ end
44
+ end
45
+ end
46
+
47
+ def request_method
48
+ event.dig('requestContext', 'http', 'method') || event['httpMethod']
49
+ end
50
+
51
+ # Using custom domain names with v1.0 yields a good `path` parameter sans
52
+ # stage. However, v2.0 and others do not. So we are just going to remove stage
53
+ # no matter waht from other places for both.
54
+ #
55
+ def path_info
56
+ stage = event.dig('requestContext', 'stage')
57
+ spath = event.dig('requestContext', 'http', 'path') || event.dig('requestContext', 'path')
58
+ spath.sub /\A\/#{stage}/, ''
59
+ end
60
+
61
+ def server_name
62
+ headers['x-forwarded-host'] ||
63
+ headers['X-Forwarded-Host'] ||
64
+ headers['host'] ||
65
+ headers['Host']
66
+ end
67
+
68
+ def server_port
69
+ headers['x-forwarded-port'] || headers['X-Forwarded-Port']
70
+ end
71
+
72
+ def server_protocol
73
+ event.dig('requestContext', 'http', 'protocol') ||
74
+ event.dig('requestContext', 'protocol') ||
75
+ 'HTTP/1.1'
76
+ end
77
+
78
+
79
+ end
80
+ end
@@ -1,8 +1,12 @@
1
1
  module Lamby
2
- class RackApi < Lamby::Rack
2
+ class RackRest < Lamby::Rack
3
3
 
4
- def api?
5
- true
4
+ def response(handler)
5
+ if handler.base64_encodeable?
6
+ { isBase64Encoded: true, body: handler.body64 }
7
+ else
8
+ super
9
+ end
6
10
  end
7
11
 
8
12
  private
@@ -32,9 +32,9 @@ module Lamby
32
32
  @options = options
33
33
  end
34
34
 
35
- def to_env
35
+ def to_env(overwrite: true)
36
36
  params.each do |param|
37
- ENV[param.env] = param.value
37
+ overwrite ? ENV[param.env] = param.value : ENV[param.env] ||= param.value
38
38
  end
39
39
  end
40
40
 
@@ -68,7 +68,7 @@ module Lamby
68
68
 
69
69
  def dotenv_contents
70
70
  params.each_with_object('') do |param, contents|
71
- line = "export #{param.env}=#{param.value}\n"
71
+ line = "#{param.env}=#{param.value}\n"
72
72
  contents << line
73
73
  end
74
74
  end
@@ -1,6 +1,7 @@
1
1
  installers = {
2
- 'API Gateway' => :api_gateway,
3
- 'Application Load Balancer' => :application_load_balancer
2
+ 'API Gateway (HTTP API)' => :http,
3
+ 'API Gateway (REST API)' => :rest,
4
+ 'Application Load Balancer' => :alb
4
5
  }.freeze
5
6
 
6
7
  namespace :lamby do
@@ -32,5 +33,5 @@ namespace :lamby do
32
33
  end
33
34
 
34
35
  desc "Install Lamby files for #{installers.first.first}"
35
- task install: 'install:application_load_balancer'
36
+ task install: 'install:http'
36
37
  end
@@ -1,4 +1,4 @@
1
- $LAMBY_INSTALLER_NAME = 'application_load_balancer'
1
+ $LAMBY_INSTALLER_NAME = 'alb'
2
2
  load 'lamby/templates/shared.rb'
3
3
 
4
4
  say '==> Running Lamby Application Load Balancer installer...'
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -e
3
3
 
4
4
  # Clean any previous bundle/builds.
@@ -8,10 +8,10 @@ rm -rf ./.aws-sam/build
8
8
  sam build --use-container
9
9
 
10
10
  # [HOOK] Environments & Configuration
11
- # https://github.com/customink/lamby/issues/28
11
+ # https://lamby.custominktech.com/docs/environment_and_configuration
12
12
 
13
13
  # [HOOK] Asset Hosts & Precompiling
14
- # https://github.com/customink/lamby/issues/29
14
+ # https://lamby.custominktech.com/docs/asset_host_and_precompiling
15
15
 
16
16
  # Clean un-needed artifacts.
17
17
  pushd ./.aws-sam/build/RailsFunction/
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -e
3
3
 
4
4
  export RAILS_ENV=${RAILS_ENV:="production"}
@@ -70,7 +70,7 @@ Resources:
70
70
  Properties:
71
71
  CodeUri: .
72
72
  Handler: app.handler
73
- Runtime: ruby2.5
73
+ Runtime: ruby2.7
74
74
  MemorySize: 512
75
75
  Timeout: 30
76
76
  Environment:
@@ -1,7 +1,7 @@
1
- $LAMBY_INSTALLER_NAME = 'api_gateway'
1
+ $LAMBY_INSTALLER_NAME = 'http'
2
2
  load 'lamby/templates/shared.rb'
3
3
 
4
- say '==> Running Lamby API Gateway installer...'
4
+ say '==> Running Lamby API Gateway (HTTP API) installer...'
5
5
 
6
6
  say 'Copying files...'
7
7
  copy_file tpl_file('app.rb'), app_file('app.rb')
@@ -6,5 +6,5 @@ require_relative 'config/environment'
6
6
  $app = Rack::Builder.new { run Rails.application }.to_app
7
7
 
8
8
  def handler(event:, context:)
9
- Lamby.handler $app, event, context, rack: :api
9
+ Lamby.handler $app, event, context, rack: :http
10
10
  end
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -e
3
3
 
4
4
  # Clean any previous bundle/builds.
@@ -8,10 +8,10 @@ rm -rf ./.aws-sam/build
8
8
  sam build --use-container
9
9
 
10
10
  # [HOOK] Environments & Configuration
11
- # https://github.com/customink/lamby/issues/28
11
+ # https://lamby.custominktech.com/docs/environment_and_configuration
12
12
 
13
13
  # [HOOK] Asset Hosts & Precompiling
14
- # https://github.com/customink/lamby/issues/29
14
+ # https://lamby.custominktech.com/docs/asset_host_and_precompiling
15
15
 
16
16
  # Clean un-needed artifacts.
17
17
  pushd ./.aws-sam/build/RailsFunction/
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -e
3
3
 
4
4
  export RAILS_ENV=${RAILS_ENV:="production"}