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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd87dbdb65df35c7a42c352ee4b619ee1f2c263a
|
4
|
+
data.tar.gz: 7bddaa1b451694fbf78f85a85a1ea35aa69a51cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ddde3fd339e8d3cd88dc8a4ba8508e246d895ffacd56477857530f9335d9226859759ff66337602ca83fdb1bd6cb5f0b774f4e41ccb4cd607f64a0cebaef1cc
|
7
|
+
data.tar.gz: 68c827f0dedea73cd533e6bb4d63d529544d337889c7db8e60147905405d9a738c6cf251ed31a32428fc6152f27b7ba4b0ca3bb10f1fdf856cb002f4369ea186
|
@@ -1,203 +1,153 @@
|
|
1
|
-
require 'aws-sdk'
|
2
|
-
|
3
1
|
module LambdaWrap
|
4
|
-
# The
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
#
|
10
|
-
|
2
|
+
# The ApiGateway class simplifies creation, deployment, and management of API Gateway objects.
|
3
|
+
# The specification for the API MUST be detailed in a provided Open API Formatted file (fka Swagger).
|
4
|
+
#
|
5
|
+
# @!attribute [r] specification
|
6
|
+
# @return [Hash] The Swagger spec parsed into a Hash
|
7
|
+
#
|
8
|
+
# @since 1.0
|
9
|
+
class ApiGateway < AwsService
|
10
|
+
attr_reader :specification
|
11
|
+
|
12
|
+
# Initializes the APIGateway Manager Object. A significant majority of the configuration of your
|
13
|
+
# API should be configured through your Swagger File (e.g. Integrations, API Name, Version).
|
11
14
|
#
|
12
|
-
# The
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
def initialize
|
17
|
-
|
18
|
-
@
|
19
|
-
|
20
|
-
@
|
21
|
-
@
|
15
|
+
# @param [Hash] options The Options initialize the API Gateway Manager with.
|
16
|
+
# @option options [String] :path_to_swagger_file File path the Swagger File to load and parse.
|
17
|
+
# @option options [String] :import_mode (overwrite) How the API Gateway Object will handle updates.
|
18
|
+
# Accepts <tt>overwrite</tt> and <tt>merge</tt>.
|
19
|
+
def initialize(options)
|
20
|
+
options_with_defaults = options.reverse_merge(import_mode: 'overwrite')
|
21
|
+
@path_to_swagger_file = options_with_defaults[:path_to_swagger_file]
|
22
|
+
@specification = extract_specification(@path_to_swagger_file)
|
23
|
+
@api_name = @specification['info']['title']
|
24
|
+
@api_version = @specification['info']['version']
|
25
|
+
@import_mode = options_with_defaults[:import_mode]
|
22
26
|
end
|
23
27
|
|
24
|
-
|
25
|
-
# Downloads the aws-apigateway-importer jar from an S3 bucket.
|
26
|
-
# This is a workaround since aws-apigateway-importer does not provide a binary.
|
27
|
-
# Once a binary is available on the public internet, we'll start using this instead
|
28
|
-
# of requiring users of this gem to upload their custom binary to an S3 bucket.
|
28
|
+
# Deploys the API Gateway Object to a specified environment
|
29
29
|
#
|
30
|
-
#
|
31
|
-
# [
|
32
|
-
# [
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
30
|
+
# @param environment_options [LambdaWrap::Environment] The environment to deploy
|
31
|
+
# @param client [Aws::APIGateway::Client] Client to use with SDK. Should be passed in by the API class.
|
32
|
+
# @param region [String] AWS Region string. Should be passed in by the API class.
|
33
|
+
def deploy(environment_options, client, region = 'AWS_REGION')
|
34
|
+
super
|
35
|
+
puts "Deploying API: #{@api_name} to Environment: #{environment_options.name}"
|
36
|
+
@stage_variables = environment_options.variables || {}
|
37
|
+
@stage_variables.store('environment', environment_options.name)
|
38
|
+
|
39
|
+
api_id = get_id_for_api(@api_name)
|
40
|
+
service_response =
|
41
|
+
if api_id
|
42
|
+
@client.put_rest_api(
|
43
|
+
fail_on_warnings: false, mode: @import_mode, rest_api_id:
|
44
|
+
api_id, body: File.open(@path_to_swagger_file, 'rb').read
|
45
|
+
)
|
46
|
+
else
|
47
|
+
@client.import_rest_api(
|
48
|
+
fail_on_warnings: false,
|
49
|
+
body: File.open(@path_to_swagger_file, 'rb').read
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
if service_response.nil? || service_response.id.nil?
|
54
|
+
raise "Failed to create API gateway with name #{@api_name}"
|
47
55
|
end
|
48
|
-
end
|
49
56
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
# [api_name] The name of the API to which the swagger file should be applied to.
|
56
|
-
# [env] The environment where it should be published (which is matching an API gateway stage)
|
57
|
-
# [swagger_file] A handle to a swagger file that should be used by aws-apigateway-importer
|
58
|
-
# [api_description] The description of the API to be displayed.
|
59
|
-
# [stage_variables] A Hash of stage variables to be deployed with the stage. Adds an 'environment' by default.
|
60
|
-
# [region] A string representing the region to deploy the API. Defaults to what is set as an environment variable.
|
61
|
-
def setup_apigateway(api_name, env, swagger_file, api_description = 'Deployed with LambdaWrap',
|
62
|
-
stage_variables = {}, region = ENV['AWS_REGION'])
|
63
|
-
# ensure API is created
|
64
|
-
api_id = get_existing_rest_api(api_name)
|
65
|
-
api_id = setup_apigateway_create_rest_api(api_name, api_description) unless api_id
|
66
|
-
|
67
|
-
# create resources
|
68
|
-
setup_apigateway_create_resources(api_id, swagger_file, region)
|
69
|
-
|
70
|
-
# create stages
|
71
|
-
stage_variables.store('environment', env)
|
72
|
-
create_stages(api_id, env, stage_variables)
|
73
|
-
|
74
|
-
# return URI of created stage
|
75
|
-
"https://#{api_id}.execute-api.#{region}.amazonaws.com/#{env}/"
|
76
|
-
end
|
57
|
+
if api_id
|
58
|
+
"Created API Gateway Object: #{@api_name} having id #{service_response.id}"
|
59
|
+
else
|
60
|
+
"Updated API Gateway Object: #{@api_name} having id #{service_response.id}"
|
61
|
+
end
|
77
62
|
|
78
|
-
|
79
|
-
# Shuts down an environment from the API Gateway. This basically deletes the stage
|
80
|
-
# from the API Gateway, but does not delete the API Gateway itself.
|
81
|
-
#
|
82
|
-
# *Argument*
|
83
|
-
# [api_name] The name of the API where the environment should be shut down.
|
84
|
-
# [env] The environment (matching an API Gateway stage) to shutdown.
|
85
|
-
def shutdown_apigateway(api_name, env)
|
86
|
-
api_id = get_existing_rest_api(api_name)
|
87
|
-
delete_stage(api_id, env)
|
88
|
-
end
|
63
|
+
create_stage(service_response.id, environment_options)
|
89
64
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
def get_existing_rest_api(api_name)
|
96
|
-
apis = @client.get_rest_apis(limit: 500).data
|
97
|
-
api = apis.items.select { |a| a.name == api_name }.first
|
98
|
-
|
99
|
-
return api.id if api
|
100
|
-
# nil is returned otherwise
|
65
|
+
service_uri = "https://#{service_response.id}.execute-api.#{@region}.amazonaws.com/#{environment_options.name}/"
|
66
|
+
|
67
|
+
puts "API: #{@api_name} deployed at #{service_uri}"
|
68
|
+
|
69
|
+
service_uri
|
101
70
|
end
|
102
71
|
|
103
|
-
|
104
|
-
# Creates the API with a given name using the SDK and returns the id
|
72
|
+
# Tearsdown environment for API Gateway. Deletes stage.
|
105
73
|
#
|
106
|
-
#
|
107
|
-
# [
|
108
|
-
# [
|
109
|
-
def
|
110
|
-
|
111
|
-
|
112
|
-
|
74
|
+
# @param environment_options [LambdaWrap::Environment] The environment to teardown.
|
75
|
+
# @param client [Aws::APIGateway::Client] Client to use with SDK. Should be passed in by the API class.
|
76
|
+
# @param region [String] AWS Region string. Should be passed in by the API class.
|
77
|
+
def teardown(environment_options, client, region = 'AWS_REGION')
|
78
|
+
super
|
79
|
+
api_id = get_id_for_api(@api_name)
|
80
|
+
if api_id
|
81
|
+
delete_stage(api_id, environment_options.name)
|
82
|
+
else
|
83
|
+
puts "API Gateway Object #{@api_name} not found. No environment to tear down."
|
84
|
+
end
|
85
|
+
true
|
113
86
|
end
|
114
87
|
|
115
|
-
|
116
|
-
#
|
117
|
-
#
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
88
|
+
# Deletes all stages and API Gateway object.
|
89
|
+
# @param client [Aws::APIGateway::Client] Client to use with SDK. Should be passed in by the API class.
|
90
|
+
# @param region [String] AWS Region string. Should be passed in by the API class.
|
91
|
+
def delete(client, region = 'AWS_REGION')
|
92
|
+
super
|
93
|
+
api_id = get_id_for_api(@api_name)
|
94
|
+
if api_id
|
95
|
+
@client.delete_rest_api(rest_api_id: api_id)
|
96
|
+
puts "Deleted API: #{@api_name} ID:#{api_id}"
|
97
|
+
else
|
98
|
+
puts "API Gateway Object #{@api_name} not found. Nothing to delete."
|
99
|
+
end
|
100
|
+
true
|
127
101
|
end
|
128
102
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
# *Arguments*
|
133
|
-
# [api_id] The AWS ApiGateway id where the stage should be created at.
|
134
|
-
# [env] The environment (which matches the stage in API Gateway) to create.
|
135
|
-
# [stage_variables] A Hash of stage variables to deploy with the stage
|
136
|
-
def create_stages(api_id, env, stage_variables)
|
137
|
-
deployment_description = 'Deployment of service to ' + env
|
138
|
-
deployment = @client.create_deployment(
|
139
|
-
rest_api_id: api_id, stage_name: env, cache_cluster_enabled: false, description: deployment_description,
|
140
|
-
variables: stage_variables
|
141
|
-
).data
|
142
|
-
puts deployment
|
103
|
+
def to_s
|
104
|
+
return @api_name if @api_name && @api_name.is_a?(String)
|
105
|
+
super
|
143
106
|
end
|
144
107
|
|
145
|
-
|
146
|
-
|
147
|
-
#
|
148
|
-
# *Arguments*
|
149
|
-
# [api_id] The AWS ApiGateway id from which the stage should be deleted from.
|
150
|
-
# [env]The environment (which matches the stage in API Gateway) to delete.
|
108
|
+
private
|
109
|
+
|
151
110
|
def delete_stage(api_id, env)
|
152
111
|
@client.delete_stage(rest_api_id: api_id, stage_name: env)
|
153
112
|
puts 'Deleted API gateway stage ' + env
|
154
113
|
rescue Aws::APIGateway::Errors::NotFoundException
|
155
|
-
puts
|
114
|
+
puts "API Gateway stage #{env} does not exist. Nothing to delete."
|
156
115
|
end
|
157
116
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
api_id = get_existing_rest_api(api_name)
|
169
|
-
swagger_file_content = File.read(local_swagger_file)
|
170
|
-
|
171
|
-
gateway_response = nil
|
172
|
-
if api_id.nil?
|
173
|
-
# Create a new APIGateway
|
174
|
-
gateway_response = @client.import_rest_api(fail_on_warnings: false, body: swagger_file_content)
|
175
|
-
else
|
176
|
-
# Update the exsiting APIgateway. By Merge the exsisting gateway will be merged with the new
|
177
|
-
# one supplied in the Swagger file.
|
178
|
-
gateway_response = @client.put_rest_api(rest_api_id: api_id, mode: 'merge', fail_on_warnings: false,
|
179
|
-
body: swagger_file_content)
|
180
|
-
end
|
181
|
-
|
182
|
-
raise "Failed to create API gateway with name #{api_name}" if gateway_response.nil? && gateway_response.id.nil?
|
117
|
+
def create_stage(api_id, environment_options)
|
118
|
+
deployment_description = "Deploying API #{@api_name} v#{@api_version}\
|
119
|
+
to Environment:#{environment_options.name}"
|
120
|
+
stage_description = "#{environment_options.name} - #{environment_options.description}"
|
121
|
+
@client.create_deployment(
|
122
|
+
rest_api_id: api_id, stage_name: environment_options.name,
|
123
|
+
stage_description: stage_description, description: deployment_description,
|
124
|
+
cache_cluster_enabled: false, variables: environment_options.variables
|
125
|
+
)
|
126
|
+
end
|
183
127
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
puts "Updated api gateway #{api_name} having id #{gateway_response.id}"
|
128
|
+
def extract_specification(file_path)
|
129
|
+
unless File.exist?(file_path)
|
130
|
+
raise ArgumentError, "Open API Spec (Swagger) File does not exist: #{file_path}!"
|
188
131
|
end
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
service_uri = "https://#{gateway_response.id}.execute-api.#{ENV['AWS_REGION']}.amazonaws.com/#{env}/"
|
195
|
-
puts "Service deployed at #{service_uri}"
|
196
|
-
|
197
|
-
service_uri
|
132
|
+
spec = Psych.load_file(file_path)
|
133
|
+
raise ArgumentError, 'LambdaWrap only supports swagger v2.0' unless spec['swagger'] == '2.0'
|
134
|
+
raise ArgumentError, 'Invalid Title field in the OAPISpec' unless spec['info']['title'] =~ /[A-Za-z0-9]{1,1024}/
|
135
|
+
spec
|
198
136
|
end
|
199
137
|
|
200
|
-
|
201
|
-
|
138
|
+
def get_id_for_api(api_name)
|
139
|
+
response = nil
|
140
|
+
loop do
|
141
|
+
response =
|
142
|
+
if !response || response.position.nil?
|
143
|
+
@client.get_rest_apis(limit: 500)
|
144
|
+
else
|
145
|
+
@client.get_rest_apis(limit: 500, position: response.position)
|
146
|
+
end
|
147
|
+
api = response.items.detect { |item| item.name == api_name }
|
148
|
+
return api.id if api
|
149
|
+
return if response.items.empty? || response.position.nil? || response.position.empty?
|
150
|
+
end
|
151
|
+
end
|
202
152
|
end
|
203
153
|
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
module LambdaWrap
|
2
|
+
# Top level class that manages the Serverless Microservice API deployment.
|
3
|
+
#
|
4
|
+
# @!attribute [r] lambdas
|
5
|
+
# @return [Array<LambdaWrap::Lambda>] The List of Lambdas to be deployed with the API.
|
6
|
+
#
|
7
|
+
# @!attribute [r] dynamo_tables
|
8
|
+
# @return [Array<LambdaWrap::DynamoTables>] The List of DynamoTables to be deployed with the API.
|
9
|
+
#
|
10
|
+
# @!attribute [r] api_gateways
|
11
|
+
# @return [Array<LambdaWrap::ApiGateway>] The List of API Gateways to be deployed with the API.
|
12
|
+
#
|
13
|
+
# @!attribute [r] region
|
14
|
+
# @return [String] The AWS Region to deploy the API.
|
15
|
+
#
|
16
|
+
# @since 1.0
|
17
|
+
class API
|
18
|
+
attr_reader :lambdas
|
19
|
+
attr_reader :dynamo_tables
|
20
|
+
attr_reader :api_gateways
|
21
|
+
attr_reader :region
|
22
|
+
|
23
|
+
# Constructor for the high level API Manager class.
|
24
|
+
#
|
25
|
+
# @param [Hash] options The Options to configure the API.
|
26
|
+
# @option options [String] :access_key_id The AWS Access Key Id to communicate with AWS. Will also check the
|
27
|
+
# environment variables for this value.
|
28
|
+
# @option options [String] :secret_access_key The AWS Secret Access Key to communicate with AWS. Also checks
|
29
|
+
# environment variables for this value.
|
30
|
+
# @option options [String] :region The AWS Region to deploy API to. Also checks environment variables for this
|
31
|
+
# value.
|
32
|
+
#
|
33
|
+
# @todo Allow clients to pass in a YAML file for all construction.
|
34
|
+
def initialize(options = {})
|
35
|
+
unless options[:lambda_client] && options[:dynamo_client] && options[:api_gateway_client]
|
36
|
+
access_key_id = options[:access_key_id] || ENV['AWS_ACCESS_KEY_ID'] || ENV['ACCESS_KEY'] ||
|
37
|
+
raise(ArgumentError, 'Cannot find AWS Access Key ID.')
|
38
|
+
|
39
|
+
secret_access_key = options[:secret_access_key] || ENV['AWS_SECRET_ACCESS_KEY'] || ENV['SECRET_KEY'] ||
|
40
|
+
raise(ArgumentError, 'Cannot find AWS Secret Key.')
|
41
|
+
|
42
|
+
credentials = Aws::Credentials.new(access_key_id, secret_access_key)
|
43
|
+
end
|
44
|
+
|
45
|
+
region = options[:region] || ENV['AWS_REGION'] || ENV['AMAZON_REGION'] || ENV['AWS_DEFAULT_REGION'] ||
|
46
|
+
raise(ArgumentError, 'Cannot find AWS Region.')
|
47
|
+
|
48
|
+
@lambdas = []
|
49
|
+
@dynamo_tables = []
|
50
|
+
@api_gateways = []
|
51
|
+
|
52
|
+
@region = region
|
53
|
+
@lambda_client = options[:lambda_client] ||
|
54
|
+
Aws::Lambda::Client.new(credentials: credentials, region: region)
|
55
|
+
@dynamo_client = options[:dynamo_client] ||
|
56
|
+
Aws::DynamoDB::Client.new(credentials: credentials, region: region)
|
57
|
+
@api_gateway_client = options[:api_gateway_client] ||
|
58
|
+
Aws::APIGateway::Client.new(credentials: credentials, region: region)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Add Lambda Object(s) to the API.
|
62
|
+
#
|
63
|
+
# @param [LambdaWrap::Lambda Array<LambdaWrap::Lambda>] new_lambda Splat of LambdaWrap Lambda
|
64
|
+
# objects to add to the API. Overloaded as:
|
65
|
+
# add_lambda(lambda1) OR add_lambda([lambda1, lambda2]) OR add_lambda(lambda1, lambda2)
|
66
|
+
def add_lambda(*new_lambda)
|
67
|
+
flattened_lambdas = new_lambda.flatten
|
68
|
+
flattened_lambdas.each { |lambda| parameter_guard(lambda, LambdaWrap::Lambda, 'LambdaWrap::Lambda') }
|
69
|
+
lambdas.concat(flattened_lambdas)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Add Dynamo Table Object(s) to the API.
|
73
|
+
#
|
74
|
+
# @param [LambdaWrap::DynamoTable, Array<LambdaWrap::DynamoTable>] new_table Splat of LambdaWrap DynamoTable
|
75
|
+
# objects to add to the API. Overloaded as:
|
76
|
+
# add_dynamo_table(table1) OR add_dynamo_table([table1, table2]) OR add_dynamo_table(table1, table2)
|
77
|
+
def add_dynamo_table(*new_table)
|
78
|
+
flattened_tables = new_table.flatten
|
79
|
+
flattened_tables.each { |table| parameter_guard(table, LambdaWrap::DynamoTable, 'LambdaWrap::DynamoTable') }
|
80
|
+
dynamo_tables.concat(flattened_tables)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Add API Gateway Object(s) to the API.
|
84
|
+
#
|
85
|
+
# @param [LambdaWrap::ApiGateway, Array<LambdaWrap::ApiGateway>] new_api_gateway Splat of LambdaWrap API Gateway
|
86
|
+
# objects to add to the API. Overloaded as:
|
87
|
+
# add_api_gateway(apig1) OR add_api_gateway([apig1, apig2]) OR add_api_gateway(apig1, apig2)
|
88
|
+
def add_api_gateway(*new_api_gateway)
|
89
|
+
flattened_api_gateways = new_api_gateway.flatten
|
90
|
+
flattened_api_gateways.each { |apig| parameter_guard(apig, LambdaWrap::ApiGateway, 'LambdaWrap::ApiGateway') }
|
91
|
+
api_gateways.concat(flattened_api_gateways)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Deploys all services to the specified environment.
|
95
|
+
#
|
96
|
+
# @param [LambdaWrap::Environment] environment_options the Environment to deploy
|
97
|
+
def deploy(environment_options)
|
98
|
+
environment_parameter_guard(environment_options)
|
99
|
+
if no_op?
|
100
|
+
puts 'Nothing to deploy.'
|
101
|
+
return
|
102
|
+
end
|
103
|
+
|
104
|
+
deployment_start_message = 'Deploying '
|
105
|
+
deployment_start_message += "#{dynamo_tables.length} Dynamo Tables, " unless dynamo_tables.empty?
|
106
|
+
deployment_start_message += "#{lambdas.length} Lambdas, " unless lambdas.empty?
|
107
|
+
deployment_start_message += "#{api_gateways.length} API Gateways " unless api_gateways.empty?
|
108
|
+
deployment_start_message += "to Environment: #{environment_options.name}"
|
109
|
+
puts deployment_start_message
|
110
|
+
|
111
|
+
total_time_start = Time.now
|
112
|
+
|
113
|
+
services_time_start = total_time_start
|
114
|
+
dynamo_tables.each { |table| table.deploy(environment_options, @dynamo_client, @region) }
|
115
|
+
services_time_end = Time.now
|
116
|
+
|
117
|
+
unless dynamo_tables.empty?
|
118
|
+
puts "Deploying #{dynamo_tables.length} Table(s) took: \
|
119
|
+
#{Time.at(services_time_end - services_time_start).utc.strftime('%H:%M:%S')}"
|
120
|
+
end
|
121
|
+
|
122
|
+
services_time_start = Time.now
|
123
|
+
lambdas.each { |lambda| lambda.deploy(environment_options, @lambda_client, @region) }
|
124
|
+
services_time_end = Time.now
|
125
|
+
|
126
|
+
unless lambdas.empty?
|
127
|
+
puts "Deploying #{lambdas.length} Lambda(s) took: \
|
128
|
+
#{Time.at(services_time_end - services_time_start).utc.strftime('%H:%M:%S')}"
|
129
|
+
end
|
130
|
+
|
131
|
+
services_time_start = Time.now
|
132
|
+
api_gateways.each { |apig| apig.deploy(environment_options, @api_gateway_client, @region) }
|
133
|
+
services_time_end = Time.now
|
134
|
+
|
135
|
+
unless api_gateways.empty?
|
136
|
+
puts "Deploying #{api_gateways.length} API Gateway(s) took: \
|
137
|
+
#{Time.at(services_time_end - services_time_start).utc.strftime('%H:%M:%S')}"
|
138
|
+
end
|
139
|
+
|
140
|
+
total_time_end = Time.now
|
141
|
+
|
142
|
+
puts "Total API Deployment took: \
|
143
|
+
#{Time.at(total_time_end - total_time_start).utc.strftime('%H:%M:%S')}"
|
144
|
+
puts "Successfully deployed API to #{environment_options.name}"
|
145
|
+
|
146
|
+
true
|
147
|
+
end
|
148
|
+
|
149
|
+
# Tearsdown Environment for all services.
|
150
|
+
#
|
151
|
+
# @param [LambdaWrap::Environment] environment_options the Environment to teardown
|
152
|
+
def teardown(environment_options)
|
153
|
+
environment_parameter_guard(environment_options)
|
154
|
+
if no_op?
|
155
|
+
puts 'Nothing to teardown.'
|
156
|
+
return
|
157
|
+
end
|
158
|
+
|
159
|
+
deployment_start_message = 'Tearing-down '
|
160
|
+
deployment_start_message += "#{dynamo_tables.length} Dynamo Tables, " unless dynamo_tables.empty?
|
161
|
+
deployment_start_message += "#{lambdas.length} Lambdas, " unless lambdas.empty?
|
162
|
+
deployment_start_message += "#{api_gateways.length} API Gateways " unless api_gateways.empty?
|
163
|
+
deployment_start_message += " Environment: #{environment_options.name}"
|
164
|
+
puts deployment_start_message
|
165
|
+
|
166
|
+
total_time_start = Time.now
|
167
|
+
|
168
|
+
services_time_start = total_time_start
|
169
|
+
dynamo_tables.each { |table| table.teardown(environment_options, @dynamo_client, @region) }
|
170
|
+
services_time_end = Time.now
|
171
|
+
|
172
|
+
unless dynamo_tables.empty?
|
173
|
+
puts "Tearing-down #{dynamo_tables.length} Table(s) took: \
|
174
|
+
#{Time.at(services_time_end - services_time_start).utc.strftime('%H:%M:%S')}"
|
175
|
+
end
|
176
|
+
|
177
|
+
services_time_start = Time.now
|
178
|
+
lambdas.each { |lambda| lambda.teardown(environment_options, @lambda_client, @region) }
|
179
|
+
services_time_end = Time.now
|
180
|
+
|
181
|
+
unless lambdas.empty?
|
182
|
+
puts "Tearing-down #{lambdas.length} Lambda(s) took: \
|
183
|
+
#{Time.at(services_time_end - services_time_start).utc.strftime('%H:%M:%S')}"
|
184
|
+
end
|
185
|
+
|
186
|
+
services_time_start = Time.now
|
187
|
+
api_gateways.each { |apig| apig.teardown(environment_options, @api_gateway_client, @region) }
|
188
|
+
services_time_end = Time.now
|
189
|
+
|
190
|
+
unless api_gateways.empty?
|
191
|
+
puts "Tearing-down #{api_gateways.length} API Gateway(s) took: \
|
192
|
+
#{Time.at(services_time_end - services_time_start).utc.strftime('%H:%M:%S')}"
|
193
|
+
end
|
194
|
+
|
195
|
+
total_time_end = Time.now
|
196
|
+
|
197
|
+
puts "Total API Tear-down took: \
|
198
|
+
#{Time.at(total_time_end - total_time_start).utc.strftime('%H:%M:%S')}"
|
199
|
+
puts "Successful Teardown API to #{environment_options.name}"
|
200
|
+
|
201
|
+
true
|
202
|
+
end
|
203
|
+
|
204
|
+
# Deletes all services from the cloud.
|
205
|
+
def delete
|
206
|
+
if dynamo_tables.empty? && lambdas.empty? && api_gateways.empty?
|
207
|
+
puts 'Nothing to Deleting.'
|
208
|
+
return
|
209
|
+
end
|
210
|
+
|
211
|
+
deployment_start_message = 'Deleting '
|
212
|
+
deployment_start_message += "#{dynamo_tables.length} Dynamo Tables, " unless dynamo_tables.empty?
|
213
|
+
deployment_start_message += "#{lambdas.length} Lambdas, " unless lambdas.empty?
|
214
|
+
deployment_start_message += "#{api_gateways.length} API Gateways " unless api_gateways.empty?
|
215
|
+
puts deployment_start_message
|
216
|
+
|
217
|
+
total_time_start = Time.now
|
218
|
+
|
219
|
+
services_time_start = total_time_start
|
220
|
+
dynamo_tables.each { |table| table.delete(@dynamo_client, @region) }
|
221
|
+
services_time_end = Time.now
|
222
|
+
|
223
|
+
unless dynamo_tables.empty?
|
224
|
+
puts "Deleting #{dynamo_tables.length} Table(s) took: \
|
225
|
+
#{Time.at(services_time_end - services_time_start).utc.strftime('%H:%M:%S')}"
|
226
|
+
end
|
227
|
+
|
228
|
+
services_time_start = Time.now
|
229
|
+
lambdas.each { |lambda| lambda.delete(@lambda_client, @region) }
|
230
|
+
services_time_end = Time.now
|
231
|
+
|
232
|
+
unless lambdas.empty?
|
233
|
+
puts "Deleting #{lambdas.length} Lambda(s) took: \
|
234
|
+
#{Time.at(services_time_end - services_time_start).utc.strftime('%H:%M:%S')}"
|
235
|
+
end
|
236
|
+
|
237
|
+
services_time_start = Time.now
|
238
|
+
api_gateways.each { |apig| apig.delete(@api_gateway_client, @region) }
|
239
|
+
services_time_end = Time.now
|
240
|
+
|
241
|
+
unless api_gateways.empty?
|
242
|
+
puts "Deleting #{api_gateways.length} API Gateway(s) took: \
|
243
|
+
#{Time.at(services_time_end - services_time_start).utc.strftime('%H:%M:%S')}"
|
244
|
+
end
|
245
|
+
|
246
|
+
total_time_end = Time.now
|
247
|
+
|
248
|
+
puts "Total API Deletion took: \
|
249
|
+
#{Time.at(total_time_end - total_time_start).utc.strftime('%H:%M:%S')}"
|
250
|
+
puts 'Successful Deletion of API'
|
251
|
+
|
252
|
+
true
|
253
|
+
end
|
254
|
+
|
255
|
+
private
|
256
|
+
|
257
|
+
def environment_parameter_guard(parameter)
|
258
|
+
parameter_guard(parameter, LambdaWrap::Environment, 'LambdaWrap::Environment')
|
259
|
+
end
|
260
|
+
|
261
|
+
def parameter_guard(parameter, type, type_name)
|
262
|
+
return if parameter.is_a?(type)
|
263
|
+
raise ArgumentError, "Must pass a #{type_name} to the API Manager. Got: #{parameter}"
|
264
|
+
end
|
265
|
+
|
266
|
+
def no_op?
|
267
|
+
dynamo_tables.empty? && lambdas.empty? && api_gateways.empty?
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module LambdaWrap
|
2
|
+
# Super Abstract Class for all AWS services and their calls.
|
3
|
+
# @abstract
|
4
|
+
# @since 1.0
|
5
|
+
class AwsService
|
6
|
+
def deploy(environment, client, region = 'AWS_REGION')
|
7
|
+
unless environment.is_a?(LambdaWrap::Environment)
|
8
|
+
raise ArgumentError, 'Must pass a LambdaWrap::Environment class.'
|
9
|
+
end
|
10
|
+
@client = client
|
11
|
+
@region = region
|
12
|
+
client_guard
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown(environment, client, region = 'AWS_REGION')
|
16
|
+
unless environment.is_a?(LambdaWrap::Environment)
|
17
|
+
raise ArgumentError, 'Must pass a LambdaWrap::Environment class.'
|
18
|
+
end
|
19
|
+
@client = client
|
20
|
+
@region = region
|
21
|
+
client_guard
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete(client, region = 'AWS_REGION')
|
25
|
+
@client = client
|
26
|
+
@region = region
|
27
|
+
client_guard
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def client_guard
|
33
|
+
unless @client.class == Aws::Lambda::Client || @client.class == Aws::DynamoDB::Client ||
|
34
|
+
@client.class == Aws::APIGateway::Client
|
35
|
+
raise ArgumentError, 'AWS client not initialized.'
|
36
|
+
end
|
37
|
+
raise ArgumentError, 'Invalid region' if @region.empty? || !Aws.partition('aws').region(@region)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|