lamby 1.0.2 → 2.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.
- checksums.yaml +4 -4
- data/.github/workflows/cicd.yml +17 -0
- data/.gitignore +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +25 -0
- data/Dockerfile +12 -0
- data/Gemfile.lock +82 -83
- data/README.md +9 -3
- data/Rakefile +1 -0
- data/bin/_setup +6 -0
- data/bin/_test +6 -0
- data/bin/bootstrap +3 -17
- data/bin/setup +3 -3
- data/bin/test +6 -3
- data/bin/update +2 -2
- data/docker-compose.yml +14 -0
- data/lamby.gemspec +1 -1
- data/lib/lamby.rb +2 -1
- data/lib/lamby/handler.rb +16 -3
- data/lib/lamby/logger.rb +13 -9
- data/lib/lamby/rack.rb +11 -9
- data/lib/lamby/rack_alb.rb +11 -14
- data/lib/lamby/rack_http.rb +80 -0
- data/lib/lamby/{rack_api.rb → rack_rest.rb} +7 -3
- data/lib/lamby/ssm_parameter_store.rb +1 -1
- data/lib/lamby/templates.rake +4 -3
- data/lib/lamby/templates/{application_load_balancer.rb → alb.rb} +1 -1
- data/lib/lamby/templates/{application_load_balancer → alb}/app.rb +0 -0
- data/lib/lamby/templates/{application_load_balancer → alb}/build +1 -1
- data/lib/lamby/templates/{application_load_balancer → alb}/deploy +1 -1
- data/lib/lamby/templates/{application_load_balancer → alb}/template.yaml +1 -1
- data/lib/lamby/templates/{api_gateway.rb → http.rb} +2 -2
- data/lib/lamby/templates/{api_gateway → http}/app.rb +1 -1
- data/lib/lamby/templates/{api_gateway → http}/build +1 -1
- data/lib/lamby/templates/{api_gateway → http}/deploy +1 -1
- data/lib/lamby/templates/http/template.yaml +48 -0
- data/lib/lamby/templates/rest.rb +25 -0
- data/lib/lamby/templates/rest/app.rb +10 -0
- data/lib/lamby/templates/rest/build +23 -0
- data/lib/lamby/templates/rest/deploy +22 -0
- data/lib/lamby/templates/{api_gateway → rest}/template.yaml +2 -2
- data/lib/lamby/templates/shared.rb +3 -1
- data/lib/lamby/version.rb +1 -1
- data/vendor/.keep +0 -0
- metadata +29 -23
- data/.python-version +0 -1
- data/.travis.yml +0 -17
- data/Brewfile +0 -5
- data/Pipfile +0 -13
- data/Pipfile.lock +0 -370
data/docker-compose.yml
ADDED
@@ -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
|
data/lamby.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency 'bundler'
|
25
25
|
spec.add_development_dependency 'rake'
|
26
26
|
spec.add_development_dependency 'minitest'
|
27
|
+
spec.add_development_dependency 'minitest-focus'
|
27
28
|
spec.add_development_dependency 'mocha'
|
28
29
|
spec.add_development_dependency 'pry'
|
29
|
-
spec.add_development_dependency 'sqlite3'
|
30
30
|
end
|
data/lib/lamby.rb
CHANGED
@@ -6,7 +6,8 @@ require 'lamby/version'
|
|
6
6
|
require 'lamby/sam_helpers'
|
7
7
|
require 'lamby/rack'
|
8
8
|
require 'lamby/rack_alb'
|
9
|
-
require 'lamby/
|
9
|
+
require 'lamby/rack_rest'
|
10
|
+
require 'lamby/rack_http'
|
10
11
|
require 'lamby/debug'
|
11
12
|
require 'lamby/handler'
|
12
13
|
require 'rails/railtie'
|
data/lib/lamby/handler.rb
CHANGED
@@ -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::
|
53
|
-
|
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
|
|
data/lib/lamby/logger.rb
CHANGED
@@ -1,19 +1,23 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
|
-
ENV['
|
3
|
+
unless ENV['LAMBY_TEST']
|
4
4
|
|
5
|
-
|
6
|
-
module Logger
|
5
|
+
ENV['RAILS_LOG_TO_STDOUT'] = '1'
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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(
|
data/lib/lamby/rack.rb
CHANGED
@@ -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
|
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?
|
data/lib/lamby/rack_alb.rb
CHANGED
@@ -53,20 +53,17 @@ module Lamby
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def headers_multi
|
56
|
-
(event['multiValueHeaders'] || {}).
|
57
|
-
v.is_a?(Array)
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
data/lib/lamby/templates.rake
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
installers = {
|
2
|
-
'API Gateway' => :
|
3
|
-
'
|
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:
|
36
|
+
task install: 'install:http'
|
36
37
|
end
|
File without changes
|
@@ -1,7 +1,7 @@
|
|
1
|
-
$LAMBY_INSTALLER_NAME = '
|
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')
|
@@ -0,0 +1,48 @@
|
|
1
|
+
AWSTemplateFormatVersion: '2010-09-09'
|
2
|
+
Transform: AWS::Serverless-2016-10-31
|
3
|
+
Description: APPNAMEHERE Lambda (HTTP API)
|
4
|
+
|
5
|
+
Parameters:
|
6
|
+
|
7
|
+
RailsEnv:
|
8
|
+
Type: String
|
9
|
+
Default: production
|
10
|
+
AllowedValues:
|
11
|
+
- staging
|
12
|
+
- production
|
13
|
+
|
14
|
+
Resources:
|
15
|
+
|
16
|
+
RailsFunction:
|
17
|
+
Type: AWS::Serverless::Function
|
18
|
+
Properties:
|
19
|
+
CodeUri: .
|
20
|
+
Handler: app.handler
|
21
|
+
Runtime: ruby2.7
|
22
|
+
MemorySize: 512
|
23
|
+
Timeout: 30
|
24
|
+
Environment:
|
25
|
+
Variables:
|
26
|
+
RAILS_ENV: !Ref RailsEnv
|
27
|
+
FunctionName: !Join [ '', [ 'APPNAMEHERE-', !Ref RailsEnv, '-', !Ref 'AWS::Region' ] ]
|
28
|
+
Events:
|
29
|
+
RailsApiProxy:
|
30
|
+
Type: HttpApi
|
31
|
+
Properties:
|
32
|
+
ApiId: !Ref RailsApi
|
33
|
+
AutoPublishAlias: live
|
34
|
+
|
35
|
+
RailsApi:
|
36
|
+
Type: AWS::Serverless::HttpApi
|
37
|
+
Properties:
|
38
|
+
StageName: !Ref RailsEnv
|
39
|
+
|
40
|
+
Outputs:
|
41
|
+
|
42
|
+
RailsApiUrl:
|
43
|
+
Description: API Gateway Endpoint
|
44
|
+
Value: !Sub "https://${RailsApi}.execute-api.${AWS::Region}.amazonaws.com/${RailsEnv}/"
|
45
|
+
|
46
|
+
RailsFunctionArn:
|
47
|
+
Description: Lambda ARN
|
48
|
+
Value: !GetAtt RailsFunction.Arn
|
@@ -0,0 +1,25 @@
|
|
1
|
+
$LAMBY_INSTALLER_NAME = 'rest'
|
2
|
+
load 'lamby/templates/shared.rb'
|
3
|
+
|
4
|
+
say '==> Running Lamby API Gateway (REST API) installer...'
|
5
|
+
|
6
|
+
say 'Copying files...'
|
7
|
+
copy_file tpl_file('app.rb'), app_file('app.rb')
|
8
|
+
copy_file tpl_file('template.yaml'), app_file('template.yaml')
|
9
|
+
gsub_file app_file('template.yaml'), /APPNAMEHERE/, appname
|
10
|
+
|
11
|
+
say 'Adding to .gitignore...'
|
12
|
+
FileUtils.touch app_file('.gitignore')
|
13
|
+
append_to_file app_file('.gitignore'), <<-GITIGNORE.strip_heredoc
|
14
|
+
# Lamby
|
15
|
+
/.aws-sam
|
16
|
+
GITIGNORE
|
17
|
+
|
18
|
+
say 'Creating ./bin files for build and deploy...'
|
19
|
+
copy_file tpl_file('build'), app_file('bin/build')
|
20
|
+
chmod app_file('bin/build'), 0755
|
21
|
+
copy_file tpl_file('deploy'), app_file('bin/deploy')
|
22
|
+
chmod app_file('bin/deploy'), 0755
|
23
|
+
gsub_file app_file('bin/deploy'), /APPNAMEHERE/, appname.downcase
|
24
|
+
|
25
|
+
say 'Welcome to AWS Lambda and Rails 🎉', :green
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative 'config/boot'
|
2
|
+
require 'lamby'
|
3
|
+
require_relative 'config/application'
|
4
|
+
require_relative 'config/environment'
|
5
|
+
|
6
|
+
$app = Rack::Builder.new { run Rails.application }.to_app
|
7
|
+
|
8
|
+
def handler(event:, context:)
|
9
|
+
Lamby.handler $app, event, context, rack: :rest
|
10
|
+
end
|