lamby 1.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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"}