lamby-no-rails 1.0.3

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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.python-version +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +17 -0
  6. data/Brewfile +5 -0
  7. data/CHANGELOG.md +109 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/Gemfile +3 -0
  10. data/Gemfile.lock +168 -0
  11. data/LICENSE.txt +21 -0
  12. data/Pipfile +13 -0
  13. data/Pipfile.lock +370 -0
  14. data/README.md +37 -0
  15. data/Rakefile +12 -0
  16. data/bin/bootstrap +20 -0
  17. data/bin/console +14 -0
  18. data/bin/setup +6 -0
  19. data/bin/test +5 -0
  20. data/bin/update +7 -0
  21. data/lamby.gemspec +29 -0
  22. data/lib/lamby.rb +25 -0
  23. data/lib/lamby/debug.rb +46 -0
  24. data/lib/lamby/handler.rb +71 -0
  25. data/lib/lamby/logger.rb +23 -0
  26. data/lib/lamby/rack.rb +85 -0
  27. data/lib/lamby/rack_alb.rb +73 -0
  28. data/lib/lamby/rack_api.rb +36 -0
  29. data/lib/lamby/railtie.rb +12 -0
  30. data/lib/lamby/sam_helpers.rb +9 -0
  31. data/lib/lamby/ssm_parameter_store.rb +154 -0
  32. data/lib/lamby/tasks.rake +15 -0
  33. data/lib/lamby/templates.rake +36 -0
  34. data/lib/lamby/templates/api_gateway.rb +25 -0
  35. data/lib/lamby/templates/api_gateway/app.rb +10 -0
  36. data/lib/lamby/templates/api_gateway/build +23 -0
  37. data/lib/lamby/templates/api_gateway/deploy +22 -0
  38. data/lib/lamby/templates/api_gateway/template.yaml +84 -0
  39. data/lib/lamby/templates/application_load_balancer.rb +25 -0
  40. data/lib/lamby/templates/application_load_balancer/app.rb +10 -0
  41. data/lib/lamby/templates/application_load_balancer/build +23 -0
  42. data/lib/lamby/templates/application_load_balancer/deploy +39 -0
  43. data/lib/lamby/templates/application_load_balancer/template.yaml +90 -0
  44. data/lib/lamby/templates/shared.rb +15 -0
  45. data/lib/lamby/version.rb +3 -0
  46. metadata +199 -0
@@ -0,0 +1,154 @@
1
+ require 'aws-sdk-ssm'
2
+
3
+ module Lamby
4
+ class SsmParameterStore
5
+
6
+ MAX_RESULTS = 10
7
+
8
+ Param = Struct.new :name, :env, :value
9
+
10
+ attr_reader :path, :params
11
+
12
+ class << self
13
+
14
+ def dotenv(path)
15
+ new(path).get!.to_dotenv
16
+ end
17
+
18
+ def get!(path)
19
+ parts = path.from(1).split('/')
20
+ env = parts.pop
21
+ path = "/#{parts.join('/')}"
22
+ new(path).get!.params.detect do |p|
23
+ p.env == env
24
+ end.try(:value)
25
+ end
26
+
27
+ end
28
+
29
+ def initialize(path, options = {})
30
+ @path = path
31
+ @params = []
32
+ @options = options
33
+ end
34
+
35
+ def to_env(overwrite: true)
36
+ params.each do |param|
37
+ overwrite ? ENV[param.env] = param.value : ENV[param.env] ||= param.value
38
+ end
39
+ end
40
+
41
+ def to_dotenv
42
+ File.open(dotenv_file, 'w') { |f| f.write(dotenv_contents) }
43
+ end
44
+
45
+ def get!
46
+ get_all!
47
+ get_history! if label.present?
48
+ self
49
+ end
50
+
51
+ def label
52
+ ENV['LAMBY_SSM_PARAMS_LABEL'] || @options[:label]
53
+ end
54
+
55
+ def client
56
+ @client ||= begin
57
+ options = @options[:client_options] || {}
58
+ Aws::SSM::Client.new(options)
59
+ end
60
+ end
61
+
62
+
63
+ private
64
+
65
+ def dotenv_file
66
+ @options[:dotenv_file] || ENV['LAMBY_SSM_PARAMS_FILE'] || Rails.root.join(".env.#{Rails.env}")
67
+ end
68
+
69
+ def dotenv_contents
70
+ params.each_with_object('') do |param, contents|
71
+ line = "export #{param.env}=#{param.value}\n"
72
+ contents << line
73
+ end
74
+ end
75
+
76
+ # Path
77
+
78
+ def get_all!
79
+ return params if @got_all
80
+ get_parse_all
81
+ while @all_response.next_token do get_parse_all end
82
+ @got_all = true
83
+ params
84
+ end
85
+
86
+ def get_parse_all
87
+ get_all
88
+ parse_all
89
+ end
90
+
91
+ def get_all
92
+ @all_response = client.get_parameters_by_path(get_all_options)
93
+ end
94
+
95
+ def get_all_options
96
+ { path: path,
97
+ recursive: true,
98
+ with_decryption: true,
99
+ max_results: MAX_RESULTS
100
+ }.tap { |options|
101
+ token = @all_response.try(:next_token)
102
+ options[:next_token] = token if token
103
+ }
104
+ end
105
+
106
+ def parse_all
107
+ @all_response.parameters.each do |p|
108
+ env = p.name.split('/').last
109
+ params << Param.new(p.name, env, p.value)
110
+ end
111
+ end
112
+
113
+ # History
114
+
115
+ def get_history!
116
+ return params if @got_history
117
+ params.each do |param|
118
+ name = param.name
119
+ get_parse_history(name)
120
+ while @hist_response.next_token do get_parse_history(name) end
121
+ end
122
+ @got_history = true
123
+ params
124
+ end
125
+
126
+ def get_parse_history(name)
127
+ get_history(name)
128
+ parse_history(name)
129
+ end
130
+
131
+ def get_history(name)
132
+ @hist_response = client.get_parameter_history(get_history_options(name))
133
+ end
134
+
135
+ def get_history_options(name)
136
+ { name: name,
137
+ with_decryption: true,
138
+ max_results: MAX_RESULTS
139
+ }.tap { |options|
140
+ token = @hist_response.try(:next_token)
141
+ options[:next_token] = token if token
142
+ }
143
+ end
144
+
145
+ def parse_history(name)
146
+ @hist_response.parameters.each do |p|
147
+ next unless p.labels.include? label
148
+ param = params.detect { |param| param.name == name }
149
+ param.value = p.value
150
+ end
151
+ end
152
+
153
+ end
154
+ end
@@ -0,0 +1,15 @@
1
+ namespace :lamby do
2
+
3
+ namespace :ssm do
4
+
5
+ desc 'Create a Dotenv file.'
6
+ task :dotenv do
7
+ require 'lamby/ssm_parameter_store'
8
+ path = ENV['LAMBY_SSM_PARAMS_PATH']
9
+ raise ArgumentError, 'The LAMBY_SSM_PARAMS_PATH env is required.' unless path
10
+ Lamby::SsmParameterStore.dotenv(path)
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,36 @@
1
+ installers = {
2
+ 'API Gateway' => :api_gateway,
3
+ 'Application Load Balancer' => :application_load_balancer
4
+ }.freeze
5
+
6
+ namespace :lamby do
7
+ namespace :install do
8
+
9
+ installers.each do |name, task_name|
10
+ desc "Install Lamby files for #{name}"
11
+ task task_name do
12
+ exec "#{base_path} LOCATION=#{template(task_name)}"
13
+ end
14
+ end
15
+
16
+ def template(task_name)
17
+ File.expand_path "../lamby/templates/#{task_name}.rb", __dir__
18
+ end
19
+
20
+ def bin_path
21
+ ENV['BUNDLE_BIN'] || './bin'
22
+ end
23
+
24
+ def base_path
25
+ if Rails::VERSION::MAJOR >= 5
26
+ "#{RbConfig.ruby} #{bin_path}/rails app:template"
27
+ else
28
+ "#{RbConfig.ruby} #{bin_path}/rake rails:template"
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ desc "Install Lamby files for #{installers.first.first}"
35
+ task install: 'install:application_load_balancer'
36
+ end
@@ -0,0 +1,25 @@
1
+ $LAMBY_INSTALLER_NAME = 'api_gateway'
2
+ load 'lamby/templates/shared.rb'
3
+
4
+ say '==> Running Lamby API Gateway 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: :api
10
+ end
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ # Clean any previous bundle/builds.
5
+ rm -rf ./.aws-sam/build
6
+
7
+ # Ensure native extensions built for platform.
8
+ sam build --use-container
9
+
10
+ # [HOOK] Environments & Configuration
11
+ # https://lamby.custominktech.com/docs/environment_and_configuration
12
+
13
+ # [HOOK] Asset Hosts & Precompiling
14
+ # https://lamby.custominktech.com/docs/asset_host_and_precompiling
15
+
16
+ # Clean un-needed artifacts.
17
+ pushd ./.aws-sam/build/RailsFunction/
18
+ rm -rf .aws-sam \
19
+ .git \
20
+ log \
21
+ test \
22
+ tmp
23
+ popd
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ export RAILS_ENV=${RAILS_ENV:="production"}
5
+ export AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:=us-east-1}
6
+ export CLOUDFORMATION_BUCKET=${CLOUDFORMATION_BUCKET:="lamby.cloudformation.$(whoami)"}
7
+
8
+ ./bin/build
9
+
10
+ sam package \
11
+ --region ${AWS_DEFAULT_REGION} \
12
+ --template-file ./.aws-sam/build/template.yaml \
13
+ --output-template-file ./.aws-sam/build/packaged.yaml \
14
+ --s3-bucket $CLOUDFORMATION_BUCKET \
15
+ --s3-prefix "APPNAMEHERE-${RAILS_ENV}"
16
+
17
+ sam deploy \
18
+ --template-file ./.aws-sam/build/packaged.yaml \
19
+ --stack-name "APPNAMEHERE-${RAILS_ENV}-${AWS_DEFAULT_REGION}" \
20
+ --capabilities "CAPABILITY_IAM" \
21
+ --parameter-overrides \
22
+ RailsEnv=${RAILS_ENV}
@@ -0,0 +1,84 @@
1
+ AWSTemplateFormatVersion: '2010-09-09'
2
+ Transform: AWS::Serverless-2016-10-31
3
+ Description: APPNAMEHERE Lambda (API)
4
+
5
+ Parameters:
6
+
7
+ RailsEnv:
8
+ Type: String
9
+ Default: production
10
+ AllowedValues:
11
+ - staging
12
+ - production
13
+
14
+ Resources:
15
+
16
+ RailsApi:
17
+ Type: AWS::Serverless::Api
18
+ Properties:
19
+ StageName: !Ref RailsEnv
20
+ EndpointConfiguration: REGIONAL
21
+ DefinitionBody:
22
+ swagger: 2.0
23
+ info: { title: !Ref 'AWS::StackName' }
24
+ basePath: !Join [ '', [ '/', !Ref RailsEnv ] ]
25
+ schemes: [ 'https' ]
26
+ paths:
27
+ /:
28
+ x-amazon-apigateway-any-method:
29
+ x-amazon-apigateway-integration:
30
+ uri:
31
+ Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${RailsFunction.Arn}:live/invocations
32
+ httpMethod: POST
33
+ type: aws_proxy
34
+ /{resource+}:
35
+ x-amazon-apigateway-any-method:
36
+ parameters:
37
+ - name: resource
38
+ in: path
39
+ required: true
40
+ type: string
41
+ x-amazon-apigateway-integration:
42
+ uri:
43
+ Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${RailsFunction.Arn}:live/invocations
44
+ httpMethod: POST
45
+ type: aws_proxy
46
+ x-amazon-apigateway-binary-media-types:
47
+ - '*/*'
48
+
49
+ RailsFunction:
50
+ Type: AWS::Serverless::Function
51
+ Properties:
52
+ CodeUri: .
53
+ Handler: app.handler
54
+ Runtime: ruby2.5
55
+ MemorySize: 512
56
+ Timeout: 30
57
+ Environment:
58
+ Variables:
59
+ RAILS_ENV: !Ref RailsEnv
60
+ FunctionName: !Join [ '', [ 'APPNAMEHERE-', !Ref RailsEnv, '-', !Ref 'AWS::Region' ] ]
61
+ Events:
62
+ Root:
63
+ Type: Api
64
+ Properties:
65
+ Path: /
66
+ Method: ANY
67
+ RestApiId: !Ref RailsApi
68
+ RailsAppAll:
69
+ Type: Api
70
+ Properties:
71
+ Path: /{resource+}
72
+ Method: ANY
73
+ RestApiId: !Ref RailsApi
74
+ AutoPublishAlias: live
75
+
76
+ Outputs:
77
+
78
+ RailsApiUrl:
79
+ Description: API Gateway Endpoint
80
+ Value: !Sub "https://${RailsApi}.execute-api.${AWS::Region}.amazonaws.com/${RailsEnv}/"
81
+
82
+ RailsFunctionArn:
83
+ Description: Lambda ARN
84
+ Value: !GetAtt RailsFunction.Arn
@@ -0,0 +1,25 @@
1
+ $LAMBY_INSTALLER_NAME = 'application_load_balancer'
2
+ load 'lamby/templates/shared.rb'
3
+
4
+ say '==> Running Lamby Application Load Balancer 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: :alb
10
+ end
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ # Clean any previous bundle/builds.
5
+ rm -rf ./.aws-sam/build
6
+
7
+ # Ensure native extensions built for platform.
8
+ sam build --use-container
9
+
10
+ # [HOOK] Environments & Configuration
11
+ # https://lamby.custominktech.com/docs/environment_and_configuration
12
+
13
+ # [HOOK] Asset Hosts & Precompiling
14
+ # https://lamby.custominktech.com/docs/asset_host_and_precompiling
15
+
16
+ # Clean un-needed artifacts.
17
+ pushd ./.aws-sam/build/RailsFunction/
18
+ rm -rf .aws-sam \
19
+ .git \
20
+ log \
21
+ test \
22
+ tmp
23
+ popd
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ export RAILS_ENV=${RAILS_ENV:="production"}
5
+ export AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:=us-east-1}
6
+ export CLOUDFORMATION_BUCKET=${CLOUDFORMATION_BUCKET:="lamby.cloudformation.$(whoami)"}
7
+
8
+ ./bin/build
9
+
10
+ export VPCID=${VPCID:=$(
11
+ aws ec2 describe-vpcs \
12
+ --output text \
13
+ --filters 'Name=state,Values=available' \
14
+ --query 'Vpcs[0].VpcId'
15
+ )}
16
+
17
+ export SUBNETS=${SUBNETS:=$(
18
+ aws ec2 describe-subnets \
19
+ --output text \
20
+ --filters "Name=state,Values=available,Name=vpc-id,Values=$VPCID" \
21
+ --query 'Subnets[*].SubnetId' | \
22
+ tr -s '[:blank:]' ','
23
+ )}
24
+
25
+ sam package \
26
+ --region ${AWS_DEFAULT_REGION} \
27
+ --template-file ./.aws-sam/build/template.yaml \
28
+ --output-template-file ./.aws-sam/build/packaged.yaml \
29
+ --s3-bucket $CLOUDFORMATION_BUCKET \
30
+ --s3-prefix "APPNAMEHERE-${RAILS_ENV}"
31
+
32
+ sam deploy \
33
+ --template-file ./.aws-sam/build/packaged.yaml \
34
+ --stack-name "APPNAMEHERE-${RAILS_ENV}-${AWS_DEFAULT_REGION}" \
35
+ --capabilities "CAPABILITY_IAM" \
36
+ --parameter-overrides \
37
+ RailsEnv=${RAILS_ENV} \
38
+ VpcId=${VPCID} \
39
+ Subnets=${SUBNETS}