lambda_wrap 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/lambda_wrap/api_gateway_manager.rb +26 -22
- data/lib/lambda_wrap/dynamo_db_manager.rb +31 -18
- data/lib/lambda_wrap/lambda_manager.rb +43 -39
- data/lib/lambda_wrap/version.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dcab068ec4b93c5c11e66bdd0686aad997b52e48573e5e581f8363c56dbc96f0
|
4
|
+
data.tar.gz: 267570d242c1343f5c1d9197272eecdce1f9ce658cf73c960791c4a83afb8674
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78708a6551a1ff4296d156b941489e5782163e01f79ba96ffca23cbc1af9abc609ae8fc9c835b8de01908a6d7ad54247bf4df1e103361f4af79ab69bc1186a2a
|
7
|
+
data.tar.gz: 1d5c73b0c6054339e74f6566937a2e18064443c23f68085ab900d505a2ecd820f6a43167ef9eea3546729581e7fa0b54378879ac50aade775eb72e768d2a3c2e
|
@@ -39,20 +39,20 @@ module LambdaWrap
|
|
39
39
|
api_id = get_id_for_api(@api_name)
|
40
40
|
service_response =
|
41
41
|
if api_id
|
42
|
-
|
42
|
+
options = {
|
43
43
|
fail_on_warnings: false, mode: @import_mode, rest_api_id:
|
44
|
-
api_id, body: File.
|
45
|
-
|
44
|
+
api_id, body: File.binread(@path_to_swagger_file)
|
45
|
+
}
|
46
|
+
@client.put_rest_api(options)
|
46
47
|
else
|
47
|
-
|
48
|
+
options = {
|
48
49
|
fail_on_warnings: false,
|
49
|
-
body: File.
|
50
|
-
|
50
|
+
body: File.binread(@path_to_swagger_file)
|
51
|
+
}
|
52
|
+
@client.import_rest_api(options)
|
51
53
|
end
|
52
54
|
|
53
|
-
if service_response.nil? || service_response.id.nil?
|
54
|
-
raise "Failed to create API gateway with name #{@api_name}"
|
55
|
-
end
|
55
|
+
raise "Failed to create API gateway with name #{@api_name}" if service_response.nil? || service_response.id.nil?
|
56
56
|
|
57
57
|
if api_id
|
58
58
|
"Created API Gateway Object: #{@api_name} having id #{service_response.id}"
|
@@ -92,7 +92,10 @@ module LambdaWrap
|
|
92
92
|
super
|
93
93
|
api_id = get_id_for_api(@api_name)
|
94
94
|
if api_id
|
95
|
-
|
95
|
+
options = {
|
96
|
+
rest_api_id: api_id
|
97
|
+
}
|
98
|
+
@client.delete_rest_api(options)
|
96
99
|
puts "Deleted API: #{@api_name} ID:#{api_id}"
|
97
100
|
else
|
98
101
|
puts "API Gateway Object #{@api_name} not found. Nothing to delete."
|
@@ -108,7 +111,10 @@ module LambdaWrap
|
|
108
111
|
private
|
109
112
|
|
110
113
|
def delete_stage(api_id, env)
|
111
|
-
|
114
|
+
options = {
|
115
|
+
rest_api_id: api_id, stage_name: env
|
116
|
+
}
|
117
|
+
@client.delete_stage(options)
|
112
118
|
puts 'Deleted API gateway stage ' + env
|
113
119
|
rescue Aws::APIGateway::Errors::NotFoundException
|
114
120
|
puts "API Gateway stage #{env} does not exist. Nothing to delete."
|
@@ -118,17 +124,16 @@ module LambdaWrap
|
|
118
124
|
deployment_description = "Deploying API #{@api_name} v#{@api_version}\
|
119
125
|
to Environment:#{environment_options.name}"
|
120
126
|
stage_description = "#{environment_options.name} - #{environment_options.description}"
|
121
|
-
|
127
|
+
options = {
|
122
128
|
rest_api_id: api_id, stage_name: environment_options.name,
|
123
129
|
stage_description: stage_description, description: deployment_description,
|
124
130
|
cache_cluster_enabled: false, variables: environment_options.variables
|
125
|
-
|
131
|
+
}
|
132
|
+
@client.create_deployment(options)
|
126
133
|
end
|
127
134
|
|
128
135
|
def extract_specification(file_path)
|
129
|
-
unless File.exist?(file_path)
|
130
|
-
raise ArgumentError, "Open API Spec (Swagger) File does not exist: #{file_path}!"
|
131
|
-
end
|
136
|
+
raise ArgumentError, "Open API Spec (Swagger) File does not exist: #{file_path}!" unless File.exist?(file_path)
|
132
137
|
spec = Psych.load_file(file_path)
|
133
138
|
raise ArgumentError, 'LambdaWrap only supports swagger v2.0' unless spec['swagger'] == '2.0'
|
134
139
|
raise ArgumentError, 'Invalid Title field in the OAPISpec' unless spec['info']['title'] =~ /[A-Za-z0-9]{1,1024}/
|
@@ -138,12 +143,11 @@ module LambdaWrap
|
|
138
143
|
def get_id_for_api(api_name)
|
139
144
|
response = nil
|
140
145
|
loop do
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
end
|
146
|
+
options = {
|
147
|
+
limit: 500
|
148
|
+
}
|
149
|
+
options[:position] = response.position unless !response || response.position.nil?
|
150
|
+
response = @client.get_rest_apis(options)
|
147
151
|
api = response.items.detect { |item| item.name == api_name }
|
148
152
|
return api.id if api
|
149
153
|
return if response.items.empty? || response.position.nil? || response.position.empty?
|
@@ -213,7 +213,10 @@ module LambdaWrap
|
|
213
213
|
def retrieve_table_details(full_table_name)
|
214
214
|
table_details = nil
|
215
215
|
begin
|
216
|
-
|
216
|
+
options = {
|
217
|
+
table_name: full_table_name
|
218
|
+
}
|
219
|
+
table_details = @client.describe_table(options).table
|
217
220
|
rescue Aws::DynamoDB::Errors::ResourceNotFoundException
|
218
221
|
puts "Table #{full_table_name} does not exist."
|
219
222
|
end
|
@@ -309,11 +312,12 @@ module LambdaWrap
|
|
309
312
|
puts "Updating Provisioned Throughtput for #{full_table_name}"
|
310
313
|
puts "Setting Read Capacity Units From: #{old_read} To: #{@read_capacity_units}"
|
311
314
|
puts "Setting Write Capacty Units From: #{old_write} To: #{@write_capacity_units}"
|
312
|
-
|
315
|
+
options = {
|
313
316
|
table_name: full_table_name,
|
314
317
|
provisioned_throughput: { read_capacity_units: @read_capacity_units,
|
315
318
|
write_capacity_units: @write_capacity_units }
|
316
|
-
|
319
|
+
}
|
320
|
+
@client.update_table(options)
|
317
321
|
end
|
318
322
|
|
319
323
|
def build_global_index_deletes_array(current_global_indexes)
|
@@ -325,10 +329,11 @@ module LambdaWrap
|
|
325
329
|
|
326
330
|
def delete_global_index(full_table_name, index_to_delete)
|
327
331
|
puts "Deleting Global Secondary Index: #{index_to_delete} from Table: #{full_table_name}"
|
328
|
-
|
332
|
+
options = {
|
329
333
|
table_name: full_table_name,
|
330
334
|
global_secondary_index_updates: [{ delete: { index_name: index_to_delete } }]
|
331
|
-
|
335
|
+
}
|
336
|
+
@client.update_table(options)
|
332
337
|
end
|
333
338
|
|
334
339
|
# Looks through the list current of Global Secondary Indexes and builds an array if the Provisioned Throughput
|
@@ -363,10 +368,12 @@ module LambdaWrap
|
|
363
368
|
end
|
364
369
|
)
|
365
370
|
|
366
|
-
|
371
|
+
options = {
|
367
372
|
table_name: full_table_name,
|
368
373
|
global_secondary_index_updates: global_secondary_index_updates.map { |index| { update: index } }
|
369
|
-
|
374
|
+
}
|
375
|
+
|
376
|
+
@client.update_table(options)
|
370
377
|
end
|
371
378
|
|
372
379
|
def build_new_global_indexes_array(current_global_indexes)
|
@@ -383,22 +390,24 @@ module LambdaWrap
|
|
383
390
|
def create_global_indexes(full_table_name, new_global_secondary_indexes)
|
384
391
|
puts "Creating new Global Indexes for Table: #{full_table_name}"
|
385
392
|
puts(new_global_secondary_indexes.map { |index| index[:index_name].to_s })
|
386
|
-
|
393
|
+
options = {
|
387
394
|
table_name: full_table_name,
|
388
395
|
global_secondary_index_updates: new_global_secondary_indexes.map { |index| { create: index } }
|
389
|
-
|
396
|
+
}
|
397
|
+
@client.update_table(options)
|
390
398
|
end
|
391
399
|
|
392
400
|
def create_table(full_table_name)
|
393
401
|
puts "Creating table #{full_table_name}..."
|
394
|
-
|
402
|
+
options = {
|
395
403
|
table_name: full_table_name, attribute_definitions: @attribute_definitions,
|
396
404
|
key_schema: @key_schema,
|
397
405
|
provisioned_throughput: { read_capacity_units: @read_capacity_units,
|
398
406
|
write_capacity_units: @write_capacity_units },
|
399
407
|
local_secondary_indexes: @local_secondary_indexes,
|
400
408
|
global_secondary_indexes: @global_secondary_indexes
|
401
|
-
|
409
|
+
}
|
410
|
+
@client.create_table(options)
|
402
411
|
# Wait 60 seconds because "DescribeTable uses an eventually consistent query"
|
403
412
|
puts 'Sleeping for 60 seconds...'
|
404
413
|
Kernel.sleep(60)
|
@@ -415,7 +424,10 @@ module LambdaWrap
|
|
415
424
|
else
|
416
425
|
# Wait up to 30m
|
417
426
|
wait_until_table_available(full_table_name, 5, 360) if table_details.table_status != 'ACTIVE'
|
418
|
-
|
427
|
+
options = {
|
428
|
+
table_name: full_table_name
|
429
|
+
}
|
430
|
+
@client.delete_table(options)
|
419
431
|
end
|
420
432
|
end
|
421
433
|
|
@@ -427,12 +439,13 @@ module LambdaWrap
|
|
427
439
|
tables = []
|
428
440
|
response = nil
|
429
441
|
loop do
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
442
|
+
options = {
|
443
|
+
limit: 100
|
444
|
+
}
|
445
|
+
unless !response || response.last_evaluated_table_name.nil? || response.last_evaluated_table_name.empty?
|
446
|
+
options[:exclusive_start_table_name] = response.last_evaluated_table_name
|
447
|
+
end
|
448
|
+
response = @client.list_tables(options)
|
436
449
|
tables.concat(response.table_names)
|
437
450
|
if response.table_names.empty? || response.last_evaluated_table_name.nil? ||
|
438
451
|
response.last_evaluated_table_name.empty?
|
@@ -24,7 +24,7 @@ module LambdaWrap
|
|
24
24
|
# @option options [Integer] :timeout (30) The function execution time at which Lambda should terminate the function.
|
25
25
|
# @option options [Integer] :memory_size (128) The amount of memory, in MB, your Lambda function is given. Lambda
|
26
26
|
# uses this memory size to infer the amount of CPU and memory allocated to your function. The value must be a
|
27
|
-
# multiple of 64MB. Minimum: 128, Maximum:
|
27
|
+
# multiple of 64MB. Minimum: 128, Maximum: 3008.
|
28
28
|
# @option options [Array<String>] :subnet_ids ([]) If your Lambda function accesses resources in a VPC, you provide
|
29
29
|
# this parameter identifying the list of subnet IDs. These must belong to the same VPC. You must provide at least
|
30
30
|
# one security group and one subnet ID to configure VPC access.
|
@@ -79,7 +79,7 @@ nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-
|
|
79
79
|
@timeout = options_with_defaults[:timeout]
|
80
80
|
|
81
81
|
unless (options_with_defaults[:memory_size] % 64).zero? && (options_with_defaults[:memory_size] >= 128) &&
|
82
|
-
(options_with_defaults[:memory_size] <=
|
82
|
+
(options_with_defaults[:memory_size] <= 3008)
|
83
83
|
raise ArgumentError, 'Invalid Memory Size.'
|
84
84
|
end
|
85
85
|
@memory_size = options_with_defaults[:memory_size]
|
@@ -156,7 +156,8 @@ nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-
|
|
156
156
|
if lambda_details.nil?
|
157
157
|
puts 'No Lambda to delete.'
|
158
158
|
else
|
159
|
-
|
159
|
+
options = { function_name: @lambda_name }
|
160
|
+
@client.delete_function(options)
|
160
161
|
puts "Lambda #{@lambda_name} and all Versions & Aliases have been deleted."
|
161
162
|
end
|
162
163
|
true
|
@@ -172,7 +173,8 @@ nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-
|
|
172
173
|
def retrieve_lambda_details
|
173
174
|
lambda_details = nil
|
174
175
|
begin
|
175
|
-
|
176
|
+
options = { function_name: @lambda_name }
|
177
|
+
lambda_details = @client.get_function(options).configuration
|
176
178
|
rescue Aws::Lambda::Errors::ResourceNotFoundException, Aws::Lambda::Errors::NotFound
|
177
179
|
puts "Lambda #{@lambda_name} does not exist."
|
178
180
|
end
|
@@ -182,12 +184,12 @@ nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-
|
|
182
184
|
def create_lambda
|
183
185
|
puts "Creating New Lambda Function: #{@lambda_name}...."
|
184
186
|
puts "Runtime Engine: #{@runtime}, Timeout: #{@timeout}, Memory Size: #{@memory_size}."
|
185
|
-
|
186
|
-
lambda_version = @client.create_function(
|
187
|
+
options = {
|
187
188
|
function_name: @lambda_name, runtime: @runtime, role: @role_arn, handler: @handler,
|
188
|
-
code: { zip_file: File.
|
189
|
+
code: { zip_file: File.binread(@path_to_zip_file) }, description: @description, timeout: @timeout,
|
189
190
|
memory_size: @memory_size, vpc_config: @vpc_configuration, publish: true
|
190
|
-
|
191
|
+
}
|
192
|
+
lambda_version = @client.create_function(options).version
|
191
193
|
puts "Successfully created Lambda: #{@lambda_name}!"
|
192
194
|
lambda_version
|
193
195
|
end
|
@@ -200,45 +202,47 @@ nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-
|
|
200
202
|
#{@vpc_configuration[:security_group_ids]}"
|
201
203
|
end
|
202
204
|
|
203
|
-
|
205
|
+
options = {
|
204
206
|
function_name: @lambda_name, role: @role_arn, handler: @handler, description: @description, timeout: @timeout,
|
205
207
|
memory_size: @memory_size, vpc_config: @vpc_configuration, runtime: @runtime
|
206
|
-
|
208
|
+
}
|
209
|
+
|
210
|
+
@client.update_function_configuration(options)
|
207
211
|
|
208
212
|
puts "Successfully updated Lambda configuration for #{@lambda_name}"
|
209
213
|
end
|
210
214
|
|
211
215
|
def update_lambda_code
|
212
216
|
puts "Updating Lambda Code for #{@lambda_name}...."
|
213
|
-
|
214
|
-
response = @client.update_function_code(
|
217
|
+
options = {
|
215
218
|
function_name: @lambda_name,
|
216
|
-
zip_file: File.
|
219
|
+
zip_file: File.binread(@path_to_zip_file),
|
217
220
|
publish: true
|
218
|
-
|
221
|
+
}
|
222
|
+
|
223
|
+
response = @client.update_function_code(options)
|
219
224
|
|
220
225
|
puts "Successully updated Lambda #{@lambda_name} code to version: #{response.version}"
|
221
226
|
response.version
|
222
227
|
end
|
223
228
|
|
224
229
|
def create_alias(func_version, alias_name, alias_description)
|
230
|
+
options = {
|
231
|
+
function_name: @lambda_name, name: alias_name, function_version: func_version,
|
232
|
+
description: alias_description || 'Alias managed by LambdaWrap'
|
233
|
+
}
|
225
234
|
if alias_exist?(alias_name)
|
226
|
-
@client.update_alias(
|
227
|
-
function_name: @lambda_name, name: alias_name, function_version: func_version,
|
228
|
-
description: alias_description || 'Alias managed by LambdaWrap'
|
229
|
-
)
|
235
|
+
@client.update_alias(options)
|
230
236
|
else
|
231
|
-
@client.create_alias(
|
232
|
-
function_name: @lambda_name, name: alias_name, function_version: func_version,
|
233
|
-
description: alias_description || 'Alias managed by LambdaWrap'
|
234
|
-
)
|
237
|
+
@client.create_alias(options)
|
235
238
|
end
|
236
239
|
puts "Created Alias: #{alias_name} for Lambda: #{@lambda_name} v#{func_version}."
|
237
240
|
end
|
238
241
|
|
239
242
|
def remove_alias(alias_name)
|
240
243
|
puts "Deleting Alias: #{alias_name} for #{@lambda_name}"
|
241
|
-
|
244
|
+
options = { function_name: @lambda_name, name: alias_name }
|
245
|
+
@client.delete_alias(options)
|
242
246
|
end
|
243
247
|
|
244
248
|
def cleanup_unused_versions
|
@@ -250,7 +254,8 @@ nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-
|
|
250
254
|
|
251
255
|
function_versions_to_be_deleted.each do |version|
|
252
256
|
puts "Deleting function version: #{version}."
|
253
|
-
|
257
|
+
options = { function_name: @lambda_name, qualifier: version }
|
258
|
+
@client.delete_function(options)
|
254
259
|
end
|
255
260
|
|
256
261
|
puts "Cleaned up #{function_versions_to_be_deleted.length} unused versions."
|
@@ -260,12 +265,13 @@ nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-
|
|
260
265
|
function_versions = []
|
261
266
|
response = nil
|
262
267
|
loop do
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
268
|
+
options = {
|
269
|
+
function_name: @lambda_name
|
270
|
+
}
|
271
|
+
unless !response || response.next_marker.nil? || response.next_marker.empty?
|
272
|
+
options[:marker] = response.next_marker
|
273
|
+
end
|
274
|
+
response = @client.list_versions_by_function(options)
|
269
275
|
function_versions.concat(response.versions.map(&:version))
|
270
276
|
if response.next_marker.nil? || response.next_marker.empty?
|
271
277
|
return function_versions.reject { |v| v == '$LATEST' }
|
@@ -277,7 +283,13 @@ nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-
|
|
277
283
|
aliases = []
|
278
284
|
response = nil
|
279
285
|
loop do
|
280
|
-
|
286
|
+
options = {
|
287
|
+
function_name: @lambda_name
|
288
|
+
}
|
289
|
+
unless !response || response.next_marker.nil? || response.next_marker.empty?
|
290
|
+
options[:marker] = response.next_marker
|
291
|
+
end
|
292
|
+
response = @client.list_aliases(options)
|
281
293
|
aliases.concat(response.aliases)
|
282
294
|
return aliases if response.aliases.empty? || response.next_marker.nil? || response.next_marker.empty?
|
283
295
|
end
|
@@ -291,13 +303,5 @@ nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-
|
|
291
303
|
def alias_exist?(alias_name)
|
292
304
|
retrieve_all_aliases.detect { |a| a.name == alias_name }
|
293
305
|
end
|
294
|
-
|
295
|
-
def invoke_client_method_with_optional_marker(response, method_symbol)
|
296
|
-
if !response || response.next_marker.nil? || response.next_marker.empty?
|
297
|
-
@client.send(method_symbol, function_name: @lambda_name)
|
298
|
-
else
|
299
|
-
@client.send(method_symbol, function_name: @lambda_name, marker: response.next_marker)
|
300
|
-
end
|
301
|
-
end
|
302
306
|
end
|
303
307
|
end
|
data/lib/lambda_wrap/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lambda_wrap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Thurner
|
@@ -10,36 +10,36 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-
|
13
|
+
date: 2017-12-21 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: activesupport
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
19
|
- - "~>"
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
21
|
+
version: '4'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: '
|
28
|
+
version: '4'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
|
-
name:
|
30
|
+
name: aws-sdk
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
33
|
- - "~>"
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: '
|
35
|
+
version: '2'
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
40
|
- - "~>"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: '
|
42
|
+
version: '2'
|
43
43
|
description: |-
|
44
44
|
This gem wraps the AWS SDK to simplify deployment of AWS \
|
45
45
|
Lambda functions backed by API Gateway and DynamoDB.
|
@@ -69,7 +69,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
69
|
requirements:
|
70
70
|
- - ">="
|
71
71
|
- !ruby/object:Gem::Version
|
72
|
-
version: 1
|
72
|
+
version: '2.1'
|
73
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
74
|
requirements:
|
75
75
|
- - ">="
|
@@ -77,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
77
|
version: '0'
|
78
78
|
requirements: []
|
79
79
|
rubyforge_project:
|
80
|
-
rubygems_version: 2.
|
80
|
+
rubygems_version: 2.7.3
|
81
81
|
signing_key:
|
82
82
|
specification_version: 4
|
83
83
|
summary: Easy deployment of AWS Lambda functions and dependencies.
|