lambda_wrap 0.27.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/lambda_wrap/api_gateway_manager.rb +123 -173
- data/lib/lambda_wrap/api_manager.rb +270 -0
- data/lib/lambda_wrap/aws_service.rb +40 -0
- data/lib/lambda_wrap/dynamo_db_manager.rb +425 -146
- data/lib/lambda_wrap/environment.rb +53 -0
- data/lib/lambda_wrap/lambda_manager.rb +266 -171
- data/lib/lambda_wrap/version.rb +2 -1
- data/lib/lambda_wrap.rb +12 -2
- metadata +9 -8
- data/lib/lambda_wrap/s3_bucket_manager.rb +0 -32
- data/lib/lambda_wrap/zip_file_generator.rb +0 -67
@@ -0,0 +1,53 @@
|
|
1
|
+
module LambdaWrap
|
2
|
+
# Environment class to pass to the deploy and teardown
|
3
|
+
#
|
4
|
+
# @!attribute [r] name
|
5
|
+
# @return [String] The descriptive name of the environment.
|
6
|
+
#
|
7
|
+
# @!attribute [r] description
|
8
|
+
# @return [String] The description of the environment.
|
9
|
+
#
|
10
|
+
# @!attribute [r] variables
|
11
|
+
# @return [Hash] The Hash of environment variables to deploy with the environment.
|
12
|
+
#
|
13
|
+
# @since 1.0
|
14
|
+
class Environment
|
15
|
+
attr_reader :name
|
16
|
+
attr_reader :description
|
17
|
+
attr_reader :variables
|
18
|
+
|
19
|
+
# Constructor
|
20
|
+
#
|
21
|
+
# @param name [String] Name of the environment. Corresponds to the Lambda Alias and API Gateway Stage.
|
22
|
+
# Must be at least 3 characters, and no more than 20 characters.
|
23
|
+
# @param variables [Hash] Environment variables to pass to the API Gateway stage. Must be a flat hash.
|
24
|
+
# Each key must be Alphanumeric (underscores allowed) and no more than 64 characters. Values can have
|
25
|
+
# most special characters, and no more than 512 characters.
|
26
|
+
# @param description [String] Description of the environment for Stage & Alias descriptions. Must not
|
27
|
+
# exceed 256 characters.
|
28
|
+
def initialize(name, variables = {}, description = 'Managed by LambdaWrap')
|
29
|
+
raise ArgumentError, 'name must be provided (String)!' unless name && name.is_a?(String)
|
30
|
+
# Max Alias Name length is 20 characters.
|
31
|
+
raise ArgumentError, "Invalid name format: #{name}" unless /^[a-zA-Z0-9\-\_]{3,20}$/ =~ name
|
32
|
+
@name = name
|
33
|
+
|
34
|
+
raise ArgumentError, 'Variables must be a Hash!' unless variables.is_a?(Hash)
|
35
|
+
variables.each do |key, value|
|
36
|
+
next if /^[0-9a-zA-Z\_]{1,64}$/ =~ key && /^[A-Za-z0-9\-.\_~:\/?#&=,]{1,512}$/ =~ value && value.is_a?(String)
|
37
|
+
raise ArgumentError, "Invalid Format of variables hash: #{key} => #{value}"
|
38
|
+
end
|
39
|
+
|
40
|
+
variables[:environment] = name unless variables[:environment]
|
41
|
+
@variables = variables
|
42
|
+
|
43
|
+
raise ArgumentError, 'Description must be a String!' unless description.is_a?(String)
|
44
|
+
raise ArgumentError, 'Description too long (Max 256)' unless description.length < 256
|
45
|
+
@description = description
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
return @name if @name && @name.is_a?(String)
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,208 +1,303 @@
|
|
1
|
-
require '
|
1
|
+
require 'set'
|
2
|
+
require 'pathname'
|
2
3
|
|
3
4
|
module LambdaWrap
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
class
|
9
|
-
|
10
|
-
# The constructor does some basic setup
|
11
|
-
# * Validating basic AWS configuration
|
12
|
-
# * Creating the underlying client to interace with the AWS SDK
|
13
|
-
def initialize
|
14
|
-
# AWS lambda client
|
15
|
-
@client = Aws::Lambda::Client.new
|
16
|
-
end
|
17
|
-
|
18
|
-
##
|
19
|
-
# Packages a set of files and node modules into a deployable package.
|
5
|
+
# Lambda Manager class.
|
6
|
+
# Front loads the configuration to the constructor so that the developer can be more declarative with configuration
|
7
|
+
# and deployments.
|
8
|
+
# @since 1.0
|
9
|
+
class Lambda < AwsService
|
10
|
+
# Initializes a Lambda Manager. Frontloaded configuration.
|
20
11
|
#
|
21
|
-
#
|
22
|
-
# [
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
12
|
+
# @param [Hash] options The Configuration for the Lambda
|
13
|
+
# @option options [String] :lambda_name The name you want to assign to the function you are uploading. The function
|
14
|
+
# names appear in the console and are returned in the ListFunctions API. Function names are used to specify
|
15
|
+
# functions to other AWS Lambda API operations, such as Invoke. Note that the length constraint applies only to
|
16
|
+
# the ARN. If you specify only the function name, it is limited to 64 characters in length.
|
17
|
+
# @option options [String] :handler The function within your code that Lambda calls to begin execution.
|
18
|
+
# @option options [String] :role_arn The Amazon Resource Name (ARN) of the IAM role that Lambda assumes when it
|
19
|
+
# executes your function to access any other Amazon Web Services (AWS) resources.
|
20
|
+
# @option options [String] :path_to_zip_file The absolute path to the Deployment Package zip file
|
21
|
+
# @option options [String] :runtime The runtime environment for the Lambda function you are uploading.
|
22
|
+
# @option options [String] :description ('Deployed with LambdaWrap') A short, user-defined function description.
|
23
|
+
# Lambda does not use this value. Assign a meaningful description as you see fit.
|
24
|
+
# @option options [Integer] :timeout (30) The function execution time at which Lambda should terminate the function.
|
25
|
+
# @option options [Integer] :memory_size (128) The amount of memory, in MB, your Lambda function is given. Lambda
|
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: 1536.
|
28
|
+
# @option options [Array<String>] :subnet_ids ([]) If your Lambda function accesses resources in a VPC, you provide
|
29
|
+
# this parameter identifying the list of subnet IDs. These must belong to the same VPC. You must provide at least
|
30
|
+
# one security group and one subnet ID to configure VPC access.
|
31
|
+
# @option options [Array<String>] :security_group_ids ([]) If your Lambda function accesses resources in a VPC, you
|
32
|
+
# provide this parameter identifying the list of security group IDs. These must belong to the same VPC. You must
|
33
|
+
# provide at least one security group and one subnet ID.
|
34
|
+
# @option options [Boolean] :delete_unreferenced_versions (true) Option to delete any Lambda Function Versions upon
|
35
|
+
# deployment that do not have an alias pointing to them.
|
36
|
+
def initialize(options)
|
37
|
+
defaults = {
|
38
|
+
description: 'Deployed with LambdaWrap', subnet_ids: [], security_group_ids: [], timeout: 30, memory_size: 128,
|
39
|
+
delete_unreferenced_versions: true
|
40
|
+
}
|
41
|
+
options_with_defaults = options.reverse_merge(defaults)
|
29
42
|
|
30
|
-
|
31
|
-
|
43
|
+
unless (options_with_defaults[:lambda_name]) && (options_with_defaults[:lambda_name].is_a? String)
|
44
|
+
raise ArgumentError, 'lambda_name must be provided (String)!'
|
32
45
|
end
|
46
|
+
@lambda_name = options_with_defaults[:lambda_name]
|
33
47
|
|
34
|
-
|
35
|
-
|
48
|
+
unless (options_with_defaults[:handler]) && (options_with_defaults[:handler].is_a? String)
|
49
|
+
raise ArgumentError, 'handler must be provided (String)!'
|
36
50
|
end
|
51
|
+
@handler = options_with_defaults[:handler]
|
37
52
|
|
38
|
-
|
53
|
+
unless (options_with_defaults[:role_arn]) && (options_with_defaults[:role_arn].is_a? String)
|
54
|
+
raise ArgumentError, 'role_arn must be provided (String)!'
|
55
|
+
end
|
56
|
+
@role_arn = options_with_defaults[:role_arn]
|
57
|
+
|
58
|
+
unless (options_with_defaults[:path_to_zip_file]) && (options_with_defaults[:path_to_zip_file].is_a? String)
|
59
|
+
raise ArgumentError, 'path_to_zip_file must be provided (String)!'
|
60
|
+
end
|
61
|
+
@path_to_zip_file = options_with_defaults[:path_to_zip_file]
|
62
|
+
|
63
|
+
unless (options_with_defaults[:runtime]) && (options_with_defaults[:runtime].is_a? String)
|
64
|
+
raise ArgumentError, 'runtime must be provided (String)!'
|
65
|
+
end
|
66
|
+
|
67
|
+
case options_with_defaults[:runtime]
|
68
|
+
when 'nodejs' then raise ArgumentError, 'AWS Lambda Runtime NodeJS v0.10.42 is deprecated as of April 2017. \
|
69
|
+
Please see: https://forums.aws.amazon.com/ann.jspa?annID=4142'
|
70
|
+
when 'nodejs4.3', 'nodejs6.10', 'java8', 'python2.7', 'python3.6', 'dotnetcore1.0', 'nodejs4.3-edge'
|
71
|
+
@runtime = options_with_defaults[:runtime]
|
72
|
+
else
|
73
|
+
raise ArgumentError, "Invalid Runtime specified: #{options_with_defaults[:runtime]}. Only accepts: \
|
74
|
+
nodejs4.3, nodejs6.10, java8, python2.7, python3.6, dotnetcore1.0, or nodejs4.3-edge"
|
75
|
+
end
|
76
|
+
|
77
|
+
@description = options_with_defaults[:description]
|
78
|
+
|
79
|
+
@timeout = options_with_defaults[:timeout]
|
80
|
+
|
81
|
+
unless (options_with_defaults[:memory_size] % 64).zero? && (options_with_defaults[:memory_size] >= 128) &&
|
82
|
+
(options_with_defaults[:memory_size] <= 1536)
|
83
|
+
raise ArgumentError, 'Invalid Memory Size.'
|
84
|
+
end
|
85
|
+
@memory_size = options_with_defaults[:memory_size]
|
86
|
+
|
87
|
+
# VPC
|
88
|
+
if options_with_defaults[:subnet_ids].empty? ^ options_with_defaults[:security_group_ids].empty?
|
89
|
+
raise ArgumentError, 'Must supply values for BOTH Subnet Ids and Security Group ID if VPC is desired.'
|
90
|
+
end
|
91
|
+
unless options_with_defaults[:subnet_ids].empty?
|
92
|
+
@vpc_configuration = {
|
93
|
+
subnet_ids: options_with_defaults[:subnet_ids],
|
94
|
+
security_group_ids: options_with_defaults[:security_group_ids]
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
@delete_unreferenced_versions = options_with_defaults[:delete_unreferenced_versions]
|
39
99
|
end
|
40
100
|
|
41
|
-
|
42
|
-
#
|
101
|
+
# Deploys the Lambda to the specified Environment. Creates a Lambda Function if one didn't exist.
|
102
|
+
# Updates the Lambda's configuration, Updates the Lambda's Code, publishes a new version, and creates
|
103
|
+
# an alias that points to the newly published version. If the @delete_unreferenced_versions option
|
104
|
+
# is enabled, all Lambda Function versions that don't have an alias pointing to them will be deleted.
|
43
105
|
#
|
44
|
-
#
|
45
|
-
# [
|
46
|
-
# [
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
obj = s3.bucket(bucket).object(key)
|
106
|
+
# @param environment_options [LambdaWrap::Environment] The target Environment to deploy
|
107
|
+
# @param client [Aws::Lambda::Client] Client to use with SDK. Should be passed in by the API class.
|
108
|
+
# @param region [String] AWS Region string. Should be passed in by the API class.
|
109
|
+
def deploy(environment_options, client, region = 'AWS_REGION')
|
110
|
+
super
|
111
|
+
|
112
|
+
puts "Deploying Lambda: #{@lambda_name} to Environment: #{environment_options.name}"
|
52
113
|
|
53
|
-
|
54
|
-
|
55
|
-
File.open(local_lambda_file, 'rb') do |file|
|
56
|
-
version_id = obj.put(body: file).version_id
|
114
|
+
unless File.exist?(@path_to_zip_file)
|
115
|
+
raise ArgumentError, "Deployment Package Zip File does not exist: #{@path_to_zip_file}!"
|
57
116
|
end
|
58
|
-
raise 'Upload to S3 failed' unless version_id
|
59
117
|
|
60
|
-
|
61
|
-
|
118
|
+
lambda_details = retrieve_lambda_details
|
119
|
+
|
120
|
+
if lambda_details.nil?
|
121
|
+
function_version = create_lambda
|
122
|
+
else
|
123
|
+
update_lambda_config
|
124
|
+
function_version = update_lambda_code
|
125
|
+
end
|
126
|
+
|
127
|
+
create_alias(function_version, environment_options.name, environment_options.description)
|
128
|
+
|
129
|
+
cleanup_unused_versions if @delete_unreferenced_versions
|
130
|
+
|
131
|
+
puts "Lambda: #{@lambda_name} successfully deployed!"
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
135
|
+
# Tearsdown an Environment. Deletes an alias with the same name as the environment. Deletes
|
136
|
+
# Unreferenced Lambda Function Versions if the option was specified.
|
137
|
+
#
|
138
|
+
# @param environment_options [LambdaWrap::Environment] The target Environment to teardown.
|
139
|
+
# @param client [Aws::Lambda::Client] Client to use with SDK. Should be passed in by the API class.
|
140
|
+
# @param region [String] AWS Region string. Should be passed in by the API class.
|
141
|
+
def teardown(environment_options, client, region = 'AWS_REGION')
|
142
|
+
super
|
143
|
+
remove_alias(environment_options.name)
|
144
|
+
cleanup_unused_versions if @delete_unreferenced_versions
|
145
|
+
true
|
62
146
|
end
|
63
147
|
|
64
|
-
|
65
|
-
# Deploys a package that has been uploaded to S3.
|
148
|
+
# Deletes the Lambda Object with associated versions, code, configuration, and aliases.
|
66
149
|
#
|
67
|
-
#
|
68
|
-
# [
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
def
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
# create or update function
|
150
|
+
# @param client [Aws::Lambda::Client] Client to use with SDK. Should be passed in by the API class.
|
151
|
+
# @param region [String] AWS Region string. Should be passed in by the API class.
|
152
|
+
def delete(client, region = 'AWS_REGION')
|
153
|
+
super
|
154
|
+
puts "Deleting all versions and aliases for Lambda: #{@lambda_name}"
|
155
|
+
lambda_details = retrieve_lambda_details
|
156
|
+
if lambda_details.nil?
|
157
|
+
puts 'No Lambda to delete.'
|
158
|
+
else
|
159
|
+
@client.delete_function(function_name: @lambda_name)
|
160
|
+
puts "Lambda #{@lambda_name} and all Versions & Aliases have been deleted."
|
161
|
+
end
|
162
|
+
true
|
163
|
+
end
|
164
|
+
|
165
|
+
def to_s
|
166
|
+
return @lambda_name if @lambda_name && @lambda_name.is_a?(String)
|
167
|
+
super
|
168
|
+
end
|
87
169
|
|
170
|
+
private
|
171
|
+
|
172
|
+
def retrieve_lambda_details
|
173
|
+
lambda_details = nil
|
88
174
|
begin
|
89
|
-
@client.get_function(function_name:
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
description: lambda_description,
|
100
|
-
vpc_config: vpc_configuration
|
101
|
-
).data
|
102
|
-
puts func_config
|
103
|
-
|
104
|
-
func_config = @client.update_function_code(
|
105
|
-
function_name: function_name, s3_bucket: bucket, s3_key: key,
|
106
|
-
s3_object_version: version_id, publish: true
|
107
|
-
).data
|
108
|
-
|
109
|
-
puts func_config
|
110
|
-
func_version = func_config.version
|
111
|
-
raise 'Error while publishing existing lambda function ' + function_name unless func_version
|
112
|
-
rescue Aws::Lambda::Errors::ResourceNotFoundException
|
113
|
-
# check if vpc_subnet_ids and vpc_security_group_ids are empty or not and set the vpc_config accordingly.
|
114
|
-
if vpc_subnet_ids.empty? && vpc_security_group_ids.empty?
|
115
|
-
vpc_configuration = nil
|
116
|
-
else
|
117
|
-
vpc_configuration = { subnet_ids: vpc_subnet_ids, security_group_ids: vpc_security_group_ids }
|
118
|
-
end
|
175
|
+
lambda_details = @client.get_function(function_name: @lambda_name).configuration
|
176
|
+
rescue Aws::Lambda::Errors::ResourceNotFoundException, Aws::Lambda::Errors::NotFound
|
177
|
+
puts "Lambda #{@lambda_name} does not exist."
|
178
|
+
end
|
179
|
+
lambda_details
|
180
|
+
end
|
181
|
+
|
182
|
+
def create_lambda
|
183
|
+
puts "Creating New Lambda Function: #{@lambda_name}...."
|
184
|
+
puts "Runtime Engine: #{@runtime}, Timeout: #{@timeout}, Memory Size: #{@memory_size}."
|
119
185
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
186
|
+
lambda_version = @client.create_function(
|
187
|
+
function_name: @lambda_name, runtime: @runtime, role: @role_arn, handler: @handler,
|
188
|
+
code: { zip_file: @path_to_zip_file }, description: @description, timeout: @timeout, memory_size: @memory_size,
|
189
|
+
vpc_config: @vpc_configuration, publish: true
|
190
|
+
).version
|
191
|
+
puts "Successfully created Lambda: #{@lambda_name}!"
|
192
|
+
lambda_version
|
193
|
+
end
|
128
194
|
|
129
|
-
|
130
|
-
|
131
|
-
|
195
|
+
def update_lambda_config
|
196
|
+
puts "Updating Lambda Config for #{@lambda_name}..."
|
197
|
+
puts "Runtime Engine: #{@runtime}, Timeout: #{@timeout}, Memory Size: #{@memory_size}."
|
198
|
+
if @vpc_configuration
|
199
|
+
puts "With VPC Configuration: Subnets: #{@vpc_configuration[:subnet_ids]}, Security Groups: \
|
200
|
+
#{@vpc_configuration[:security_group_ids]}"
|
132
201
|
end
|
133
202
|
|
134
|
-
|
203
|
+
@client.update_function_configuration(
|
204
|
+
function_name: @lambda_name, role: @role_arn, handler: @handler, description: @description, timeout: @timeout,
|
205
|
+
memory_size: @memory_size, vpc_config: @vpc_configuration, runtime: @runtime
|
206
|
+
)
|
135
207
|
|
136
|
-
|
137
|
-
func_version
|
208
|
+
puts "Successfully updated Lambda configuration for #{@lambda_name}"
|
138
209
|
end
|
139
210
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
211
|
+
def update_lambda_code
|
212
|
+
puts "Updating Lambda Code for #{@lambda_name}...."
|
213
|
+
|
214
|
+
response = @client.update_function_code(
|
215
|
+
function_name: @lambda_name,
|
216
|
+
zip_file: File.open(@path_to_zip_file, 'rb').read,
|
217
|
+
publish: true
|
218
|
+
)
|
219
|
+
|
220
|
+
puts "Successully updated Lambda #{@lambda_name} code to version: #{response.version}"
|
221
|
+
response.version
|
222
|
+
end
|
223
|
+
|
224
|
+
def create_alias(func_version, alias_name, alias_description)
|
225
|
+
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
|
+
)
|
230
|
+
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
|
+
)
|
235
|
+
end
|
236
|
+
puts "Created Alias: #{alias_name} for Lambda: #{@lambda_name} v#{func_version}."
|
237
|
+
end
|
238
|
+
|
239
|
+
def remove_alias(alias_name)
|
240
|
+
puts "Deleting Alias: #{alias_name} for #{@lambda_name}"
|
241
|
+
@client.delete_alias(function_name: @lambda_name, name: alias_name)
|
242
|
+
end
|
243
|
+
|
244
|
+
def cleanup_unused_versions
|
245
|
+
puts "Cleaning up unused function versions for #{@lambda_name}."
|
246
|
+
function_versions_to_be_deleted = retrieve_all_function_versions -
|
247
|
+
retrieve_function_versions_used_in_aliases
|
248
|
+
|
249
|
+
return if function_versions_to_be_deleted.empty?
|
250
|
+
|
251
|
+
function_versions_to_be_deleted.each do |version|
|
252
|
+
puts "Deleting function version: #{version}."
|
253
|
+
@client.delete_function(function_name: @lambda_name, qualifier: version)
|
254
|
+
end
|
255
|
+
|
256
|
+
puts "Cleaned up #{function_versions_to_be_deleted.length} unused versions."
|
257
|
+
end
|
258
|
+
|
259
|
+
def retrieve_all_function_versions
|
260
|
+
function_versions = []
|
261
|
+
response = nil
|
262
|
+
loop do
|
263
|
+
response =
|
264
|
+
if !response || response.next_marker.nil? || response.next_marker.empty?
|
265
|
+
@client.list_versions_by_function(function_name: @lambda_name)
|
155
266
|
else
|
156
|
-
@client.
|
157
|
-
function_name: function_name, name: alias_name, function_version: func_version,
|
158
|
-
description: 'updated by an automated script'
|
159
|
-
).data
|
267
|
+
@client.list_versions_by_function(function_name: @lambda_name, marker: response.next_marker)
|
160
268
|
end
|
161
|
-
|
269
|
+
function_versions.concat(response.versions.map(&:version))
|
270
|
+
if response.next_marker.nil? || response.next_marker.empty?
|
271
|
+
return function_versions.reject { |v| v == '$LATEST' }
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
162
275
|
|
163
|
-
|
276
|
+
def retrieve_all_aliases
|
277
|
+
aliases = []
|
278
|
+
response = nil
|
279
|
+
loop do
|
280
|
+
response = invoke_client_method_with_optional_marker(response, :list_aliases)
|
281
|
+
aliases.concat(response.aliases)
|
282
|
+
return aliases if response.aliases.empty? || response.next_marker.nil? || response.next_marker.empty?
|
283
|
+
end
|
164
284
|
end
|
165
285
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
# *Arguments*
|
170
|
-
# [function_name] The lambda function name for which the alias should be removed.
|
171
|
-
# [alias_name] The alias to remove.
|
172
|
-
def remove_alias(function_name, alias_name)
|
173
|
-
@client.delete_alias(function_name: function_name, name: alias_name)
|
286
|
+
def retrieve_function_versions_used_in_aliases
|
287
|
+
function_versions_with_aliases = Set.new []
|
288
|
+
function_versions_with_aliases.merge(retrieve_all_aliases.map(&:function_version)).to_a
|
174
289
|
end
|
175
290
|
|
176
|
-
|
177
|
-
|
178
|
-
#
|
179
|
-
# *Arguments*
|
180
|
-
# [function_name] The function name which needs to be executed from API Gateway.
|
181
|
-
# [env] The environment (matching the function's alias) which needs to be executed from API Gateway.
|
182
|
-
# => If nil, the permissions are set of the $LATEST version.
|
183
|
-
def add_api_gateway_permissions(function_name, env)
|
184
|
-
# permissions to execute lambda
|
185
|
-
suffix = (':' + env if env) || ''
|
186
|
-
func = @client.get_function(function_name: function_name + suffix).data.configuration
|
187
|
-
statement_id = func.function_name + (('-' + env if env) || '')
|
188
|
-
begin
|
189
|
-
existing_policies = @client.get_policy(function_name: func.function_arn).data
|
190
|
-
existing_policy = JSON.parse(existing_policies.policy)
|
191
|
-
policy_exists = existing_policy['Statement'].select { |s| s['Sid'] == statement_id }.any?
|
192
|
-
rescue Aws::Lambda::Errors::ResourceNotFoundException
|
193
|
-
# policy does not exist, and that is ok
|
194
|
-
policy_exists = false
|
195
|
-
end
|
196
|
-
|
197
|
-
unless policy_exists
|
198
|
-
perm_add = @client.add_permission(
|
199
|
-
function_name: func.function_arn, statement_id: statement_id,
|
200
|
-
action: 'lambda:*', principal: 'apigateway.amazonaws.com'
|
201
|
-
)
|
202
|
-
puts perm_add.data
|
203
|
-
end
|
291
|
+
def alias_exist?(alias_name)
|
292
|
+
retrieve_all_aliases.detect { |a| a.name == alias_name }
|
204
293
|
end
|
205
294
|
|
206
|
-
|
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
|
207
302
|
end
|
208
303
|
end
|
data/lib/lambda_wrap/version.rb
CHANGED
data/lib/lambda_wrap.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'lambda_wrap/version'
|
2
|
+
|
3
|
+
require 'aws-sdk'
|
4
|
+
require 'yaml'
|
5
|
+
require 'active_support/core_ext/hash'
|
6
|
+
|
7
|
+
require 'lambda_wrap/aws_service'
|
8
|
+
require 'lambda_wrap/lambda_manager'
|
9
|
+
require 'lambda_wrap/dynamo_db_manager'
|
10
|
+
require 'lambda_wrap/api_gateway_manager'
|
11
|
+
require 'lambda_wrap/environment'
|
12
|
+
require 'lambda_wrap/api_manager'
|
3
13
|
|
4
14
|
STDOUT.sync = true
|
5
15
|
STDERR.sync = true
|
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: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Thurner
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-
|
13
|
+
date: 2017-05-17 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: aws-sdk
|
@@ -27,19 +27,19 @@ dependencies:
|
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: '2'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
|
-
name:
|
30
|
+
name: activesupport
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
33
|
- - "~>"
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: '
|
35
|
+
version: '4'
|
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: '4'
|
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.
|
@@ -51,11 +51,12 @@ extra_rdoc_files: []
|
|
51
51
|
files:
|
52
52
|
- lib/lambda_wrap.rb
|
53
53
|
- lib/lambda_wrap/api_gateway_manager.rb
|
54
|
+
- lib/lambda_wrap/api_manager.rb
|
55
|
+
- lib/lambda_wrap/aws_service.rb
|
54
56
|
- lib/lambda_wrap/dynamo_db_manager.rb
|
57
|
+
- lib/lambda_wrap/environment.rb
|
55
58
|
- lib/lambda_wrap/lambda_manager.rb
|
56
|
-
- lib/lambda_wrap/s3_bucket_manager.rb
|
57
59
|
- lib/lambda_wrap/version.rb
|
58
|
-
- lib/lambda_wrap/zip_file_generator.rb
|
59
60
|
homepage: https://github.com/Cimpress-MCP/LambdaWrap
|
60
61
|
licenses:
|
61
62
|
- Apache-2.0
|
@@ -68,7 +69,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
69
|
requirements:
|
69
70
|
- - ">="
|
70
71
|
- !ruby/object:Gem::Version
|
71
|
-
version:
|
72
|
+
version: 1.9.3
|
72
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
74
|
requirements:
|
74
75
|
- - ">="
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'aws-sdk'
|
2
|
-
|
3
|
-
module LambdaWrap
|
4
|
-
##
|
5
|
-
# The S3BucketManager would have functions to help add policies, CORS etc to S3 bucket.
|
6
|
-
class S3BucketManager
|
7
|
-
#
|
8
|
-
# The constructor creates an instance of s3 bucket
|
9
|
-
# * Validating basic AWS configuration
|
10
|
-
# * Creating the underlying client to interact with the AWS SDK.
|
11
|
-
# * Defining the temporary path of the api-gateway-importer jar file
|
12
|
-
def initialize
|
13
|
-
@s3bucket = Aws::S3::Client.new
|
14
|
-
end
|
15
|
-
|
16
|
-
##
|
17
|
-
# Adds policy to the bucket
|
18
|
-
#
|
19
|
-
# *Arguments*
|
20
|
-
# [s3_bucket_name] S3 bucket name.
|
21
|
-
# [policy] Policy to be added to the bucket
|
22
|
-
def setup_policy(s3_bucket_name, policy)
|
23
|
-
# Validate the parameters
|
24
|
-
raise 'S3 bucket is not provided' unless s3_bucket_name
|
25
|
-
raise 'Policy json is not provided' unless policy
|
26
|
-
|
27
|
-
@s3bucket.put_bucket_policy(bucket: s3_bucket_name,
|
28
|
-
policy: policy.to_json)
|
29
|
-
puts "Created/Updated policy: #{policy} in S3 bucket #{s3_bucket_name}"
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|