modulator 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2702e54f413b5629b9dd99073b1367e8837991782974fc5451f8e0505f0beb0c
4
- data.tar.gz: 4fba3f0efa51536a050d05ce5b5c7874d0d1c1576050463e132f2dc4b33d0129
3
+ metadata.gz: b1a99c918b27ea88351705275d5657942b07efb8b9e87662318e4e15e2e5da08
4
+ data.tar.gz: f78e0d6e3cd7ac9e1d0767e4e91b2b3bfa475dc3d0569d32f94c4349cd249dda
5
5
  SHA512:
6
- metadata.gz: 9314246a7e0398717674b4a535d88f705766cb5e36c94b472cfdb7583da0c5971f8b8a46aab7da7d0168168b2601f3eca04e609c50a512c37a5f4a75705fe044
7
- data.tar.gz: 1b969a118871276f3be2c41b7e38ee5cc9063524047efecb918b507e2179787ddf3dcbe795a87066161da9e2e4aaaafdf72c220cf6febc60bad736a5a8137daf
6
+ metadata.gz: 3177cbde9f6c198c23dec0216cbbe8b8acc6b74a866c3225e0cf11a1494f1752da82d3011cc990d7fb0e4715a2b47f7c9b87f9da60d9d7f0f389d3c17cc26e79
7
+ data.tar.gz: 3e89b602c5a48491f267efc3dd88b8f6b5a6d98ac154936dc2c1763bde164fa9358c5126f6687862c5c2f78d61b4bb80c2a988b1539cb18e00a8948a06ed30b2
data/.gitignore CHANGED
@@ -10,3 +10,9 @@
10
10
 
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
+
14
+ # build artifacts
15
+ .bundle
16
+ .modulator
17
+
18
+
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.3.0] - 2019-06-07
10
+
11
+ ### Added
12
+
13
+ - This file
14
+ - Modulator#wrap_with
15
+
16
+ ### Changed
17
+
18
+ - Use symbolize_names when parsing json instead custom helper
19
+ - Updated readme file with examples
data/Gemfile CHANGED
@@ -1,7 +1,3 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}"}
4
-
5
- gem 'humidifier', github: 'damir/humidifier'
6
-
7
3
  gemspec
@@ -1,15 +1,8 @@
1
- GIT
2
- remote: https://github.com/damir/humidifier
3
- revision: 81a75bbd4b47aadaaed5f967fb3527a2175dec82
4
- specs:
5
- humidifier (2.15.0)
6
-
7
1
  PATH
8
2
  remote: .
9
3
  specs:
10
- modulator (0.2.2)
11
- aws-sdk-cloudformation
12
- aws-sdk-s3
4
+ modulator (0.3.0)
5
+ humidifier
13
6
  puma
14
7
  rerun
15
8
  roda
@@ -19,26 +12,34 @@ GEM
19
12
  remote: https://rubygems.org/
20
13
  specs:
21
14
  aws-eventstream (1.0.3)
22
- aws-partitions (1.156.0)
23
- aws-sdk-cloudformation (1.19.0)
24
- aws-sdk-core (~> 3, >= 3.48.2)
15
+ aws-partitions (1.173.0)
16
+ aws-sdk-cloudformation (1.22.0)
17
+ aws-sdk-core (~> 3, >= 3.53.0)
25
18
  aws-sigv4 (~> 1.1)
26
- aws-sdk-core (3.49.0)
19
+ aws-sdk-core (3.54.2)
27
20
  aws-eventstream (~> 1.0, >= 1.0.2)
28
21
  aws-partitions (~> 1.0)
29
22
  aws-sigv4 (~> 1.1)
30
23
  jmespath (~> 1.0)
31
- aws-sdk-kms (1.17.0)
32
- aws-sdk-core (~> 3, >= 3.48.2)
24
+ aws-sdk-kms (1.21.0)
25
+ aws-sdk-core (~> 3, >= 3.53.0)
33
26
  aws-sigv4 (~> 1.1)
34
- aws-sdk-s3 (1.36.1)
35
- aws-sdk-core (~> 3, >= 3.48.2)
27
+ aws-sdk-s3 (1.42.0)
28
+ aws-sdk-core (~> 3, >= 3.53.0)
36
29
  aws-sdk-kms (~> 1)
37
- aws-sigv4 (~> 1.0)
30
+ aws-sigv4 (~> 1.1)
38
31
  aws-sigv4 (1.1.0)
39
32
  aws-eventstream (~> 1.0, >= 1.0.2)
40
33
  diff-lcs (1.3)
41
- ffi (1.10.0)
34
+ fast_underscore (0.3.1)
35
+ ffi (1.11.1)
36
+ hollaback (0.1.0)
37
+ humidifier (3.3.0)
38
+ aws-sdk-cloudformation (~> 1.19)
39
+ aws-sdk-s3 (~> 1.36)
40
+ fast_underscore (~> 0.3)
41
+ thor (~> 0.20)
42
+ thor-hollaback (~> 0.1)
42
43
  jmespath (1.4.0)
43
44
  listen (3.1.5)
44
45
  rb-fsevent (~> 0.9, >= 0.9.4)
@@ -54,7 +55,7 @@ GEM
54
55
  ffi (~> 1.0)
55
56
  rerun (0.13.0)
56
57
  listen (~> 3.0)
57
- roda (3.19.0)
58
+ roda (3.20.0)
58
59
  rack
59
60
  rspec (3.8.0)
60
61
  rspec-core (~> 3.8.0)
@@ -70,14 +71,17 @@ GEM
70
71
  rspec-support (~> 3.8.0)
71
72
  rspec-support (3.8.0)
72
73
  ruby_dep (1.5.0)
73
- rubyzip (1.2.2)
74
+ rubyzip (1.2.3)
75
+ thor (0.20.3)
76
+ thor-hollaback (0.1.2)
77
+ hollaback (~> 0.1.0)
78
+ thor (~> 0.20, >= 0.19.1)
74
79
 
75
80
  PLATFORMS
76
81
  ruby
77
82
 
78
83
  DEPENDENCIES
79
84
  bundler (~> 2.0)
80
- humidifier!
81
85
  modulator!
82
86
  rack-test (~> 1.1)
83
87
  rake (~> 10.0)
data/README.md CHANGED
@@ -1,28 +1,264 @@
1
1
  # Modulator
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/modulator`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Modulator is a tool for adding HTTP layer on top of your application using AWS Lambda and API Gateway services. You register the methods you want to publish and run the deploy script. CloudFormation engine will then provision the necessary infrastructure and deploy your application in seconds.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ Because your application is isolated form HTTP handling you will write regular Ruby code without polluting it with framework or HTTP specific details. This is possible by reflecting on method signatures to construct API Gateway endpoints and consuming its events in predictable way.
6
+
7
+ Code is deployed in two lambda layers, one for the gems and one for the application code. You will need a writable bucket to store the files and ability to manage CloudFormation stacks.
6
8
 
7
9
  ## Installation
8
10
 
9
11
  Add this line to your application's Gemfile:
10
12
 
11
13
  ```ruby
12
- gem 'modulator'
14
+ gem 'modulator', group: :development
13
15
  ```
14
16
 
15
17
  And then execute:
16
18
 
17
19
  $ bundle
18
20
 
19
- Or install it yourself as:
20
-
21
- $ gem install modulator
21
+ NOTE: do not put modulator entry outside the group, the tool will bundle default group for deployment and the gem is not required in lambda runtime
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ ### Quick example
26
+
27
+ Write Ruby application:
28
+
29
+ ```ruby
30
+ # calculator/algebra.rb:
31
+
32
+ module Calculator
33
+ module Algebra
34
+ def self.sum(x, y)
35
+ {
36
+ x: x,
37
+ y: y,
38
+ sum: x + y
39
+ }
40
+ end
41
+
42
+ def self.square(x, ip = nil)
43
+ {
44
+ x: x,
45
+ ip: ip,
46
+ square: x * x
47
+ }
48
+ end
49
+ end
50
+ end
51
+ ```
52
+
53
+ Add deploy script to working directory:
54
+
55
+ ```ruby
56
+ # stack.rb
57
+
58
+ require 'modulator'
59
+ require_relative 'calculator/algebra'
60
+
61
+ # register module methods
62
+ Modulator.register(Calculator::Algebra)
63
+
64
+ # initialize and deploy the stack
65
+ stack = Modulator.init_stack s3_bucket: 'my-modulator-apps' # bucket for code and gems layers
66
+ puts stack.valid?
67
+ puts stack.to_cf(:yaml)
68
+ puts stack.deploy_and_wait capabilities: ['CAPABILITY_IAM'], parameters: [
69
+ {parameter_key: 'AppEnvironment', parameter_value: 'development'},
70
+ {parameter_key: 'ApiGatewayStageName', parameter_value: 'v1'}
71
+ ]
72
+ ```
73
+
74
+ Run the script then visit CloudFormation page in AWS console and navigate to created stack, click on Outputs tab and copy ApiGatewayInvokeURL:
75
+
76
+ - https://some-api-id.execute-api.us-east-1.amazonaws.com/v1
77
+
78
+ Then Invoke your methods using the browser or postman:
79
+
80
+ - https://some-api-id.execute-api.us-east-1.amazonaws.com/v1/algebra/2/square
81
+ - https://some-api-id.execute-api.us-east-1.amazonaws.com/v1/algebra/2/3/sum
82
+
83
+ These URLs are also available in lambda page when clicking on API Gateway icon:
84
+
85
+ ```
86
+ ModulatorGatewayApp
87
+ arn:aws:execute-api:us-east-1:your-account-id:some-api-id/*/GET/calculator/algebra/*/square
88
+
89
+ Details
90
+ API endpoint: https://some-api-id.execute-api.us-east-1.amazonaws.com/v1/calculator/algebra/{x}/square
91
+ Authorization: NONE
92
+ Method: GET
93
+ Resource path: /calculator/algebra/{x}/square
94
+ Stage: v1
95
+ ```
96
+
97
+ You can save CF template to a file by capturing output of stack.to\_cf(:yaml) or stack.to\_cf(:json.)
98
+
99
+ ### Wrapping the method to get data from lambda event and context
100
+
101
+ Data from the request can be extracted using wrapper method which will pass the values to wrapped method as optional arguments. This example will wrap Calculator::Algebra#square with Wrappers::Authorizer#call to autorize request and provide optional ip argument:
102
+
103
+ ```ruby
104
+ # wrappers/authorizer.rb
105
+
106
+ module Wrappers
107
+ module Authorizer
108
+ module_function
109
+
110
+ def call(event:, context:)
111
+ token = event.dig('headers', 'Authorization').to_s.split(' ').last
112
+ if token == 'block'
113
+ {status: 401, body: {error: 'Blocking token'}}
114
+ elsif token == 'pass'
115
+ {ip: event.dig('requestContext', 'identity', 'sourceIp')}
116
+ else
117
+ # block with generic 403
118
+ end
119
+ end
120
+ end
121
+ end
122
+ ```
123
+
124
+ ```ruby
125
+ # stack.rb
126
+ require_relative 'wrappers/authorizer'
127
+ Modulator.register(Calculator::Algebra).wrap_with(Wrappers::Authorizer, only: :square)
128
+ ```
129
+
130
+ This method can be invoked only when Aurhorization header is set to 'pass', otherwise it will print explcit 401 with custom message when the value is 'block', or will default to 403 with generic message.
131
+
132
+ Available options are :only and :except where value is the method name or an array of names.
133
+
134
+ ### Registering and configuring methods
135
+
136
+ Registering module will add configuration entry to Modulator::LAMBDAS. Each entry is a plain hash which can be overriden. From this configuration a CloudFormation template is generated with all necessary resources for API Gateway endpoints and their lambdas, including function policies and execution roles.
137
+
138
+ Consider this example:
139
+
140
+ ```ruby
141
+ Modulator
142
+ .register(Calculator::Algebra, sum: {
143
+ gateway: {path: 'calc/:x/add/:y'},
144
+ settings: {timeout: 1, memory_size: 256},
145
+ env: {custom_var: 123}
146
+ }
147
+ )
148
+ .wrap_with(Wrappers::Authorizer, only: [:square])
149
+ ```
150
+
151
+ For that example Modulator::LAMBDAS will print this configuration:
152
+
153
+ ```ruby
154
+ {"calculator-algebra-square"=>
155
+ {:name=>"calculator-algebra-square",
156
+ :gateway=>{:verb=>"GET", :path=>"calculator/algebra/:x/square"},
157
+ :module=>
158
+ {:name=>"Calculator::Algebra",
159
+ :method=>"square",
160
+ :path=>"calculator/algebra"},
161
+ :wrapper=>
162
+ {:name=>"Wrappers::Authorizer",
163
+ :path=>"wrappers/authorizer",
164
+ :method=>"call"},
165
+ :env=>{},
166
+ :settings=>{}},
167
+ "calculator-algebra-sum"=>
168
+ {:name=>"calculator-algebra-sum",
169
+ :gateway=>{:verb=>"GET", :path=>"calc/:x/add/:y"},
170
+ :module=>
171
+ {:name=>"Calculator::Algebra",
172
+ :method=>"sum",
173
+ :path=>"calculator/algebra"},
174
+ :wrapper=>{},
175
+ :env=>{:custom_var=>123},
176
+ :settings=>{:timeout=>1, :memory_size=>256}}}
177
+ ```
178
+
179
+ - :gateway is used to construct API Gateway endpoint, it has :path key from which the URL is constructed and :verb which sets the HTTP method for that URL
180
+ - :wrapper defines wrapping method, :name is the module namespace, :method is the method name from that namespace and :path is the relative file path where the code is
181
+ - :settings holds lambda settings values, :timeout and :memory_size
182
+ - :env will add extra environment variables to lambda runtime
183
+
184
+ Any value can be changed manualy during or after the config is generated if you want to override defaults. For example you can change :verb from GET to DELETE or you can rearrange static and dynamic URL path fragments.
185
+
186
+ ### Rules for mapping URL paths and HTTP methods to method signatures
187
+
188
+ - Methods will be invoked with GET unless:
189
+ - the method name is delete, remove, or destroy for which DELETE is set
190
+ - the method has optional key paramater for which POST is set and payload is passed as its value
191
+ - Required positional parameters are mapped as dinamic URL fragments, numbers are type casted to ruby classes
192
+ - Module namespace and method name are mapped as static URL fragments
193
+
194
+ For examples please check the spec folder and the sample application code there.
195
+
196
+ ### Local API gateway for development
197
+
198
+ It is possible to run code locally as it would run in the cloud. You need to add config.ru and register some modules:
199
+
200
+ ```ruby
201
+ # config.ru
202
+
203
+ require 'modulator/gateway/gateway'
204
+ require_relative 'calculator/algebra'
205
+ require_relative 'wrappers/authorizer'
206
+ Modulator.register(Calculator::Algebra).wrap_with(Wrappers::Authorizer, only: [:square])
207
+ ```
208
+
209
+ Then start the server with this command:
210
+
211
+ rerun -- puma gateway.ru
212
+
213
+ NOTE: rerun will restart the server when code changes.
214
+
215
+ Visiting localhost:9292/calculator/algebra/2/square should give this result:
216
+
217
+ ```ruby
218
+ {
219
+ "x": 2,
220
+ "ip": "127.0.0.1",
221
+ "square": 4
222
+ }
223
+ ```
224
+
225
+ Server log will print detailed information about request and method invocation:
226
+
227
+ ```
228
+ Method: GET
229
+ Path: /calculator/algebra/2/square
230
+ Headers: {
231
+ "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "Authorization"=>"pass",
232
+ "Cache-Control"=>"no-cache", "Connection"=>"keep-alive", "Host"=>"localhost:9292",
233
+ "Postman-Token"=>"8708ee60-a156-4ca2-9937-f1f408a568e2",
234
+ "User-Agent"=>"PostmanRuntime/7.13.0", "Version"=>"HTTP/1.1"}
235
+ Path params: {"x"=>"2"}
236
+ Calling wrapper Wrappers::Authorizer.call
237
+ Resolving GET calculator/algebra/:x/square to Calculator::Algebra.square with [[:req, :x], [:opt, :ip]]
238
+ Matched path: /calculator/algebra/2/square
239
+ Status: 200
240
+ Took: 0.00117 seconds
241
+ ```
242
+
243
+ Local gateway is implemented with [Roda](https://github.com/jeremyevans/roda).
244
+
245
+ ### Manipulating generated CloudFormation template
246
+
247
+ Modulator#init_stack will return [Humidifier](https://github.com/kddeisz/humidifier) instance which allows for easy manipulation of generated CF template. If you need to add more resources or tweak existing ones please consult its documentation.
248
+
249
+ One example of extending the template is Modulator#add_policy which adds extra policies to lambdas by passing optional values to init method:
250
+
251
+ ```ruby
252
+ Modulator.init_stack(
253
+ lambda_policies: [{name: :dynamo_db, prefixes: ['my-app']}],
254
+ )
255
+ ```
256
+
257
+ This will give lambdas an access to DynamoDB tables prefixed by 'my-app'. Alternatively you could do it directly by providing your own policy:
258
+
259
+ ```ruby
260
+ stack.resources['LambdaRole'].properties['policies'] << my_policy_template
261
+ ```
26
262
 
27
263
  ## Development
28
264
 
@@ -1,38 +1,56 @@
1
1
  require 'json'
2
2
 
3
- require 'modulator/lambda/aws_lambda_handler'
4
- require 'modulator/lambda/aws_stack_builder'
3
+ require 'modulator/lambda_handler'
4
+ require 'modulator/stack/builder'
5
5
  require 'utils'
6
6
 
7
7
  module Modulator
8
8
  module_function
9
- LAMBDAS = {}
9
+ LAMBDAS = {}
10
10
 
11
- def add_lambda(lambda_def, **opts) # opts are for overrides
11
+ class << self
12
+ attr_accessor :stack, :registering_module
13
+ end
14
+
15
+ def register(lambda_def, **opts) # opts are for overrides
12
16
  if lambda_def.is_a?(Hash)
13
- add_lambda_from_hash(lambda_def)
17
+ register_from_hash(lambda_def)
14
18
  else
15
- add_lambda_from_module(lambda_def, **opts)
19
+ register_from_module(lambda_def, **opts)
20
+ self.registering_module = lambda_def
21
+ self
22
+ end
23
+ end
24
+
25
+ def wrap_with(wrapper_mod, only: nil, except: nil)
26
+ registering_module.singleton_methods.sort.each do |module_method|
27
+ next if only && !Array(only).include?(module_method)
28
+ next if except && Array(except).include?(module_method)
29
+ LAMBDAS[calculate_registry_key(registering_module, module_method)][:wrapper] = {
30
+ name: wrapper_mod.to_s,
31
+ path: wrapper_mod.to_s.split('::').map(&:downcase).join('/'), # file name
32
+ method: 'call'
33
+ }
16
34
  end
17
35
  end
18
36
 
19
- def add_lambda_from_hash(hash)
37
+ def register_from_hash(hash)
20
38
  LAMBDAS[hash[:name]] = {
21
- name: hash[:name],
22
- gateway: hash[:gateway],
23
- module: hash[:module],
24
- wrapper: hash[:wrapper] || {},
25
- env: hash[:env] || {},
39
+ name: hash[:name],
40
+ gateway: hash[:gateway],
41
+ module: hash[:module],
42
+ wrapper: hash[:wrapper] || {},
43
+ env: hash[:env] || {},
26
44
  settings: hash[:settings] || {}
27
45
  }
28
46
  end
29
47
 
30
- def add_lambda_from_module(mod, **opts)
48
+ def register_from_module(mod, **opts)
31
49
  mod.singleton_methods.sort.each do |module_method|
32
- module_name = mod.to_s
33
- module_names = module_name.split('::').map(&:downcase)
34
- verb = 'GET'
35
- path_fragments = module_names.dup
50
+ module_name = mod.to_s
51
+ module_names = module_name.split('::').map(&:downcase)
52
+ verb = 'GET'
53
+ path_fragments = module_names.dup
36
54
 
37
55
  # process parameters
38
56
  # method(a, b, c = 1, *args, d:, e: 2, **opts)
@@ -48,67 +66,85 @@ module Modulator
48
66
  verb = 'POST' if param_type == :key
49
67
  end
50
68
 
51
- # delete is special case based on method name
69
+ # delete is a special case based on method name
52
70
  verb = 'DELETE' if %w[destroy delete remove implode].include? module_method.to_s
53
71
 
54
72
  # finalize path
55
73
  path_fragments << module_method
56
74
  path = path_fragments.join('/')
75
+ registry_key = calculate_registry_key(mod, module_method)
57
76
 
58
- add_lambda_from_hash(
77
+ register_from_hash(
59
78
  {
60
- name: "#{module_names.join('-')}-#{module_method}",
79
+ name: registry_key,
61
80
  gateway: {
62
81
  verb: opts.dig(module_method, :gateway, :verb) || verb,
63
82
  path: opts.dig(module_method, :gateway, :path) || path
64
83
  },
65
84
  module: {
66
- name: module_name,
85
+ name: module_name,
67
86
  method: module_method.to_s,
68
- path: module_names.join('/') # file name
87
+ path: module_names.join('/') # file name
69
88
  },
70
- wrapper: opts.dig(module_method, :wrapper) || opts[:wrapper],
71
- env: opts.dig(module_method, :env),
89
+ wrapper: opts.dig(module_method, :wrapper) || opts[:wrapper],
90
+ env: opts.dig(module_method, :env),
72
91
  settings: opts.dig(module_method, :settings)
73
92
  }
74
93
  )
75
94
  end
76
95
  end
77
96
 
78
- def set_env(lambda_def)
97
+ # lambda definition reference
98
+ def calculate_registry_key(mod, module_method)
99
+ module_names = mod.to_s.split('::').map(&:downcase)
100
+ "#{module_names.join('-')}-#{module_method}"
101
+ end
102
+
103
+ # local gateway helper
104
+ def set_env_values(lambda_def)
79
105
  # remove wrapper if already set
80
- %w(name method path).each{|name| ENV.delete('wrapper_' + name)}
81
- # set env values
82
- lambda_def[:module].each{|name, value| ENV['module_' + name.to_s] = value.to_s}
83
- lambda_def[:gateway].each{|name, value| ENV['gateway_' + name.to_s] = value.to_s}
84
- lambda_def[:wrapper]&.each{|name, value| ENV['wrapper_' + name.to_s] = value.to_s}
85
- lambda_def[:env]&.each{|name, value| ENV[name.to_s] = value.to_s} # custom values
106
+ %i(name method path).each{|key| ENV.delete("wrapper_#{key}")}
107
+
108
+ # set env for each group
109
+ %i(module gateway wrapper env).each do |group_key|
110
+ lambda_def[group_key]&.each do |key, value|
111
+ key = "#{group_key}_#{key}" if group_key != :env
112
+ ENV[key.to_s] = value.to_s
113
+ end
114
+ end
86
115
  end
87
116
 
88
- def init_stack(app_name:, bucket:, **stack_opts)
89
- stack = AwsStackBuilder.init({
90
- app_name: app_name.camelize,
91
- bucket: bucket,
117
+ # init humidifier stack instance
118
+ def init_stack(app_name: Pathname.getwd.basename.to_s, s3_bucket:, **stack_opts)
119
+ stack = StackBuilder.init({
120
+ app_name: app_name.camelize,
121
+ s3_bucket: s3_bucket,
92
122
  }.merge(stack_opts))
93
123
 
124
+ # validate stack
125
+ # puts 'Validating stack'
126
+ # puts '- it is valid' if stack.valid?
127
+
128
+ self.stack = stack
129
+ generate_endoints if LAMBDAS.any?
130
+
131
+ # return instance
132
+ stack
133
+ end
134
+
135
+ # delegate to stack instance
136
+ def generate_endoints
94
137
  # add lambdas to stack
95
138
  puts 'Generating endpoints'
96
139
  LAMBDAS.each do |name, config|
97
140
  puts "- adding #{config.dig(:module, :name)}.#{config.dig(:module, :method)} to #{config.dig(:gateway, :path)}"
98
141
  stack.add_lambda_endpoint(
99
- gateway: config[:gateway],
100
- mod: config[:module],
101
- wrapper: config[:wrapper] || {},
102
- env: config[:env] || {},
142
+ gateway: config[:gateway],
143
+ mod: config[:module],
144
+ wrapper: config[:wrapper] || {},
145
+ env: config[:env] || {},
103
146
  settings: config[:settings] || {}
104
147
  )
105
148
  end
106
-
107
- # validate stack
108
- # puts 'Validating stack'
109
- # puts '- it is valid' if stack.valid?
110
-
111
- # return humidifier instance
112
- stack
113
149
  end
114
150
  end