lambda_wrap 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bb1eb756df3c76832fbe546394984c6342e38ee5
4
- data.tar.gz: a3016f7a3880c7137be66c68ef8baf0c0851cdc6
3
+ metadata.gz: d97a3646f6a910220435cc9631b671ef63089d0f
4
+ data.tar.gz: 3c46b725cbf0934aa83b937051bcba028a0321bd
5
5
  SHA512:
6
- metadata.gz: d65978e2e7be1c2ea4015b2fa55a1775c680ad2ca0c609386baf779a93f16f937e68e4c8e587c86cca6f15dddc1e7c119e112ce9dc48fcc66c2f91e4af7caff3
7
- data.tar.gz: 9eed6b47faf86c479bb861d6a329107d34623f606caa7c53eabc5f9d58ad4d1d8f2aa25a911af4285f8ca9521257ba57521dc0fca45afe9e2efe3115afe6ebd3
6
+ metadata.gz: 7c471f0e67052c94f555df32e17863058c05a67648daa53475db759c9a8f932f9d0ee631d2d3e98c19b48de6dc50de49ff9e3a8d673348a5124277656a5ffb2e
7
+ data.tar.gz: aa02fa599624407e03ab4c8a558f3f082e2dcea2cd53f83f571684e9c666c5bcc149b67950e29f0d49b5b24c808a25495a395dec69a511b6badabdcf8b7d8001
@@ -1,5 +1,5 @@
1
1
  # :nodoc:
2
- Dir["#{File.expand_path(File.dirname(__FILE__))}/**/*.rb"].each{|f| require f}
2
+ Dir["#{File.expand_path(File.dirname(__FILE__))}/**/*.rb"].each { |f| require f }
3
3
 
4
4
  STDOUT.sync = true
5
- STDERR.sync = true
5
+ STDERR.sync = true
@@ -1,177 +1,151 @@
1
1
  require 'aws-sdk'
2
- require_relative 'aws_setup'
3
2
 
4
3
  module LambdaWrap
5
-
6
- ##
7
- # The ApiGatewayManager simplifies downloading the aws-apigateway-importer binary,
8
- # importing a {swagger configuration}[http://swagger.io], and managing API Gateway stages.
9
- #
10
- # Note: The concept of an environment of the LambdaWrap gem matches a stage in AWS ApiGateway terms.
11
- class ApiGatewayManager
12
-
13
- ##
14
- # The constructor does some basic setup
15
- # * Validating basic AWS configuration
16
- # * Creating the underlying client to interact with the AWS SDK.
17
- # * Defining the temporary path of the api-gateway-importer jar file
18
- def initialize()
19
- AwsSetup.new.validate()
20
- # AWS api gateway client
21
- @client = Aws::APIGateway::Client.new()
22
- # path to apigateway-importer jar
23
- @jarpath = File.join(Dir.tmpdir, 'aws-apigateway-importer-1.0.3-SNAPSHOT-jar-with-dependencies.jar')
24
- @versionpath = File.join(Dir.tmpdir, 'aws-apigateway-importer-1.0.3-SNAPSHOT-jar-with-dependencies.s3version')
25
- end
26
-
27
- ##
28
- # Downloads the aws-apigateway-importer jar from an S3 bucket.
29
- # This is a workaround since aws-apigateway-importer does not provide a binary.
30
- # Once a binary is available on the public internet, we'll start using this instead
31
- # of requiring users of this gem to upload their custom binary to an S3 bucket.
32
- #
33
- # *Arguments*
34
- # [s3_bucket] An S3 bucket from where the aws-apigateway-importer binary can be downloaded.
35
- # [s3_key] The path (key) to the aws-apigateay-importer binary on the s3 bucket.
36
- def download_apigateway_importer(s3_bucket, s3_key)
37
-
38
- s3 = Aws::S3::Client.new
39
-
40
- # current version
41
- current_s3_version = File.open(@versionpath, 'rb').read if File.exists?(@versionpath)
42
-
43
- # online s3 version
44
- desired_s3_version = s3.head_object(bucket:s3_bucket, key:s3_key).version_id
45
-
46
- # compare local with remote version
47
- if current_s3_version != desired_s3_version || !File.exists?(@jarpath)
48
- puts "Downloading aws-apigateway-importer jar with S3 version #{desired_s3_version}"
49
- obj = s3.get_object(response_target:@jarpath, bucket:s3_bucket, key:s3_key)
50
- File.write(@versionpath, desired_s3_version)
51
- end
52
-
53
- end
54
-
55
- ##
56
- # Sets up the API gateway by searching whether the API Gateway already exists
57
- # and updates it with the latest information from the swagger file.
58
- #
59
- # *Arguments*
60
- # [api_name] The name of the API to which the swagger file should be applied to.
61
- # [env] The environment where it should be published (which is matching an API gateway stage)
62
- # [swagger_file] A handle to a swagger file that should be used by aws-apigateway-importer
63
- # [api_description] The description of the API to be displayed.
64
- def setup_apigateway(api_name, env, swagger_file, api_description = "Deployed with LambdaWrap")
65
-
66
- # ensure API is created
67
- api_id = get_existing_rest_api(api_name)
68
- api_id = setup_apigateway_create_rest_api(api_name, api_description) if !api_id
69
-
70
- # create resources
71
- setup_apigateway_create_resources(api_id, swagger_file)
72
-
73
- # create stages
74
- create_stages(api_id, env)
75
-
76
- # return URI of created stage
77
- return "https://#{api_id}.execute-api.#{ENV['AWS_REGION']}.amazonaws.com/#{env}/"
78
-
79
- end
80
-
81
- ##
82
- # Shuts down an environment from the API Gateway. This basically deletes the stage
83
- # from the API Gateway, but does not delete the API Gateway itself.
84
- #
85
- # *Argument*
86
- # [api_name] The name of the API where the environment should be shut down.
87
- # [env] The environment (matching an API Gateway stage) to shutdown.
88
- def shutdown_apigateway(api_name, env)
89
-
90
- api_id = get_existing_rest_api(api_name)
91
- delete_stage(api_id, env)
92
-
93
- end
94
-
95
- ##
96
- # Gets the ID of an existing API Gateway api, or nil if it doesn't exist
97
- #
98
- # *Arguments*
99
- # [api_name] The name of the API to be checked for existance
100
- def get_existing_rest_api(api_name)
101
-
102
- apis = @client.get_rest_apis({limit: 500}).data
103
- api = apis.items.select{ |api| api.name == api_name}.first()
104
-
105
- if (api)
106
- return api.id
107
- else
108
- return nil
109
- end
110
-
111
- end
112
-
113
- ##
114
- # Creates the API with a given name and returns the id
115
- #
116
- # *Arguments*
117
- # [api_name] The name of the API to be created
118
- def setup_apigateway_create_rest_api(api_name, api_description)
119
-
120
- puts 'Creating API with name ' + api_name
121
- api = @client.create_rest_api({name: api_name, description: api_description})
122
-
123
- return api.id
124
-
125
- end
126
-
127
- ##
128
- # Invokes the aws-apigateway-importer jar with the required parameter
129
- #
130
- # *Arguments*
131
- # [api_id] The AWS ApiGateway id where the swagger file should be applied to.
132
- # [swagger_file] The handle to a swagger definition file that should be imported into API Gateway
133
- def setup_apigateway_create_resources(api_id, swagger_file)
134
-
135
- raise 'API ID not provided' if !api_id
136
-
137
- cmd = "java -jar #{@jarpath} --update #{api_id} --region #{ENV['AWS_REGION']} #{swagger_file}"
138
- raise 'API gateway not created' if !system(cmd)
139
-
140
- end
141
-
142
- ##
143
- # Creates a stage of the currently set resources
144
- #
145
- # *Arguments*
146
- # [api_id] The AWS ApiGateway id where the stage should be created at.
147
- # [env] The environment (which matches the stage in API Gateway) to create.
148
- def create_stages(api_id, env)
149
-
150
- deployment_description = 'Deployment of service to ' + env
151
- deployment = @client.create_deployment({rest_api_id: api_id, stage_name: env, cache_cluster_enabled: false, description: deployment_description, variables: { "environment" => env}}).data
152
- puts deployment
153
-
154
- end
155
-
156
- ##
157
- # Deletes a stage of the API Gateway
158
- #
159
- # *Arguments*
160
- # [api_id] The AWS ApiGateway id from which the stage should be deleted from.
161
- # [env] The environment (which matches the stage in API Gateway) to delete.
162
- def delete_stage(api_id, env)
163
-
164
- begin
165
- @client.delete_stage({rest_api_id: api_id, stage_name: env})
166
- puts 'Deleted API gateway stage ' + env
167
- rescue Aws::APIGateway::Errors::NotFoundException
168
- puts 'API Gateway stage ' + env + ' does not exist. Nothing to delete.'
169
- end
170
-
171
- end
172
-
173
- private :get_existing_rest_api, :setup_apigateway_create_rest_api, :setup_apigateway_create_resources, :create_stages, :delete_stage
174
-
175
- end
176
-
177
- end
4
+ # The ApiGatewayManager simplifies downloading the aws-apigateway-importer binary,
5
+ # importing a {swagger configuration}[http://swagger.io], and managing API Gateway stages.
6
+
7
+ # Note: The concept of an environment of the LambdaWrap gem matches a stage in AWS ApiGateway terms.
8
+ class ApiGatewayManager
9
+ #
10
+ # The constructor does some basic setup
11
+ # * Validating basic AWS configuration
12
+ # * Creating the underlying client to interact with the AWS SDK.
13
+ # * Defining the temporary path of the api-gateway-importer jar file
14
+ def initialize
15
+ # AWS api gateway client
16
+ @client = Aws::APIGateway::Client.new
17
+ # path to apigateway-importer jar
18
+ @jarpath = File.join(Dir.tmpdir, 'aws-apigateway-importer-1.0.3-SNAPSHOT-jar-with-dependencies.jar')
19
+ @versionpath = File.join(Dir.tmpdir, 'aws-apigateway-importer-1.0.3-SNAPSHOT-jar-with-dependencies.s3version')
20
+ end
21
+
22
+ ##
23
+ # Downloads the aws-apigateway-importer jar from an S3 bucket.
24
+ # This is a workaround since aws-apigateway-importer does not provide a binary.
25
+ # Once a binary is available on the public internet, we'll start using this instead
26
+ # of requiring users of this gem to upload their custom binary to an S3 bucket.
27
+ #
28
+ # *Arguments*
29
+ # [s3_bucket] An S3 bucket from where the aws-apigateway-importer binary can be downloaded.
30
+ # [s3_key] The path (key) to the aws-apigateay-importer binary on the s3 bucket.
31
+ def download_apigateway_importer(s3_bucket, s3_key)
32
+ s3 = Aws::S3::Client.new
33
+
34
+ # current version
35
+ current_s3_version = File.open(@versionpath, 'rb').read if File.exist?(@versionpath)
36
+
37
+ # online s3 version
38
+ desired_s3_version = s3.head_object(bucket: s3_bucket, key: s3_key).version_id
39
+
40
+ # compare local with remote version
41
+ if current_s3_version != desired_s3_version || !File.exist?(@jarpath)
42
+ puts "Downloading aws-apigateway-importer jar with S3 version #{desired_s3_version}"
43
+ s3.get_object(response_target: @jarpath, bucket: s3_bucket, key: s3_key)
44
+ File.write(@versionpath, desired_s3_version)
45
+ end
46
+ end
47
+
48
+ ##
49
+ # Sets up the API gateway by searching whether the API Gateway already exists
50
+ # and updates it with the latest information from the swagger file.
51
+ #
52
+ # *Arguments*
53
+ # [api_name] The name of the API to which the swagger file should be applied to.
54
+ # [env] The environment where it should be published (which is matching an API gateway stage)
55
+ # [swagger_file] A handle to a swagger file that should be used by aws-apigateway-importer
56
+ # [api_description] The description of the API to be displayed.
57
+ def setup_apigateway(api_name, env, swagger_file, api_description = 'Deployed with LambdaWrap')
58
+ # ensure API is created
59
+ api_id = get_existing_rest_api(api_name)
60
+ api_id = setup_apigateway_create_rest_api(api_name, api_description) unless api_id
61
+
62
+ # create resources
63
+ setup_apigateway_create_resources(api_id, swagger_file)
64
+
65
+ # create stages
66
+ create_stages(api_id, env)
67
+
68
+ # return URI of created stage
69
+ "https://#{api_id}.execute-api.#{ENV['AWS_REGION']}.amazonaws.com/#{env}/"
70
+ end
71
+
72
+ ##
73
+ # Shuts down an environment from the API Gateway. This basically deletes the stage
74
+ # from the API Gateway, but does not delete the API Gateway itself.
75
+ #
76
+ # *Argument*
77
+ # [api_name] The name of the API where the environment should be shut down.
78
+ # [env] The environment (matching an API Gateway stage) to shutdown.
79
+ def shutdown_apigateway(api_name, env)
80
+ api_id = get_existing_rest_api(api_name)
81
+ delete_stage(api_id, env)
82
+ end
83
+
84
+ ##
85
+ # Gets the ID of an existing API Gateway api, or nil if it doesn't exist
86
+ #
87
+ # *Arguments*
88
+ # [api_name] The name of the API to be checked for existance
89
+ def get_existing_rest_api(api_name)
90
+ apis = @client.get_rest_apis(limit: 500).data
91
+ api = apis.items.select { |a| a.name == api_name }.first
92
+
93
+ return api.id if api
94
+ # nil is returned otherwise
95
+ end
96
+
97
+ ##
98
+ # Creates the API with a given name and returns the id
99
+ #
100
+ # *Arguments*
101
+ # [api_name] The name of the API to be created
102
+ def setup_apigateway_create_rest_api(api_name, api_description)
103
+ puts 'Creating API with name ' + api_name
104
+ api = @client.create_rest_api(name: api_name, description: api_description)
105
+ api.id
106
+ end
107
+
108
+ ##
109
+ # Invokes the aws-apigateway-importer jar with the required parameter
110
+ #
111
+ # *Arguments*
112
+ # [api_id] The AWS ApiGateway id where the swagger file should be applied to.
113
+ # [swagger_file] The handle to a swagger definition file that should be imported into API Gateway
114
+ def setup_apigateway_create_resources(api_id, swagger_file)
115
+ raise 'API ID not provided' unless api_id
116
+
117
+ cmd = "java -jar #{@jarpath} --update #{api_id} #{swagger_file}"
118
+ raise 'API gateway not created' unless system(cmd)
119
+ end
120
+
121
+ ##
122
+ # Creates a stage of the currently set resources
123
+ #
124
+ # *Arguments*
125
+ # [api_id] The AWS ApiGateway id where the stage should be created at.
126
+ # [env] The environment (which matches the stage in API Gateway) to create.
127
+ def create_stages(api_id, env)
128
+ deployment_description = 'Deployment of service to ' + env
129
+ deployment = @client.create_deployment(
130
+ rest_api_id: api_id, stage_name: env, cache_cluster_enabled: false, description: deployment_description,
131
+ variables: { 'environment' => env }
132
+ ).data
133
+ puts deployment
134
+ end
135
+
136
+ ##
137
+ # Deletes a stage of the API Gateway
138
+ #
139
+ # *Arguments*
140
+ # [api_id] The AWS ApiGateway id from which the stage should be deleted from.
141
+ # [env] The environment (which matches the stage in API Gateway) to delete.
142
+ def delete_stage(_, env)
143
+ puts 'Deleted API gateway stage ' + env
144
+ rescue Aws::APIGateway::Errors::NotFoundException
145
+ puts 'API Gateway stage ' + env + ' does not exist. Nothing to delete.'
146
+ end
147
+
148
+ private :get_existing_rest_api, :setup_apigateway_create_rest_api, :setup_apigateway_create_resources,
149
+ :create_stages, :delete_stage
150
+ end
151
+ end
@@ -1,127 +1,121 @@
1
1
  require 'aws-sdk'
2
- require_relative 'aws_setup'
3
2
 
4
3
  module LambdaWrap
5
-
6
- ##
7
- # The DynamoDBManager simplifies setting up and destroying a DynamoDB database.
8
- #
9
- # Note: In case an environment specific DynamoDB tablename such as +<baseTableName>-production+ should be used, then
10
- # it has to be injected directly to the methods since not all environments necessarily need separated databases.
11
- class DynamoDbManager
4
+ # The DynamoDBManager simplifies setting up and destroying a DynamoDB database.
5
+ #
6
+ # Note: In case an environment specific DynamoDB tablename such as +<baseTableName>-production+ should be used, then
7
+ # it has to be injected directly to the methods since not all environments necessarily need separated databases.
8
+ class DynamoDbManager
9
+ ##
10
+ # The constructor does some basic setup
11
+ # * Validating basic AWS configuration
12
+ # * Creating the underlying client to interact with the AWS SDK.
13
+ def initialize
14
+ # AWS dynamodb client
15
+ @client = Aws::DynamoDB::Client.new
16
+ end
12
17
 
13
- ##
14
- # The constructor does some basic setup
15
- # * Validating basic AWS configuration
16
- # * Creating the underlying client to interact with the AWS SDK.
17
- def initialize()
18
- AwsSetup.new.validate()
19
- # AWS dynamodb client
20
- @client = Aws::DynamoDB::Client.new()
21
- end
22
-
23
- ##
24
- # Publishes the database and awaits until it is fully available. If the table already exists, it only adjusts the read/write
25
- # capacities upwards (it doesn't downgrade them to avoid a production environment being impacted with a default setting of an
26
- # automated script).
27
- #
28
- # *Arguments*
29
- # [table_name] The table name of the dynamoDB to be created.
30
- # [attribute_definitions] The dynamoDB attribute definitions to be used when the table is created. See the AWS documentation for details.
31
- # [key_schema] The dynamoDB key definitions to be used when the table is created. See the AWS documentation for details.
32
- # [read_capacity] The read capacity to configure for the dynamoDB table.
33
- # [write_capacity] The write capacity to configure for the dynamoDB table.
34
- def publish_database(table_name, attribute_definitions, key_schema, read_capacity, write_capacity)
35
-
36
- has_updates = false
37
-
38
- # figure out whether the table exists
39
- begin
40
- table_details = @client.describe_table(table_name: table_name).table
41
- rescue Aws::DynamoDB::Errors::ResourceNotFoundException
42
- end
43
-
44
- if (table_details)
45
- wait_until_table_available(table_name) if (table_details.table_status != 'ACTIVE')
46
-
47
- if (read_capacity > table_details.provisioned_throughput.read_capacity_units ||
48
- write_capacity > table_details.provisioned_throughput.write_capacity_units)
49
- puts "Updating new read/write capacity for table #{table_name}.
50
- Read #{table_details.provisioned_throughput.read_capacity_units} ==> #{read_capacity}.
51
- Write #{table_details.provisioned_throughput.write_capacity_units} ==> #{write_capacity}."
52
- table = @client.update_table({
53
- table_name: table_name,
54
- provisioned_throughput: { read_capacity_units: read_capacity, write_capacity_units: write_capacity }
55
- })
56
- has_updates = true
57
- else
58
- puts "Table #{table_name} already exists and the desired read capacity of #{read_capacity} and write capacity of #{write_capacity} has at least been configured. Downgrading capacity units is not supported. No changes were applied."
59
- end
60
- else
61
- puts "Creating table #{table_name}."
62
- ad = attribute_definitions || [{ attribute_name: "Id", attribute_type: "S" }]
63
- ks = key_schema || [{ attribute_name: "Id", key_type: "HASH" }]
64
- table = @client.create_table({
65
- attribute_definitions: ad,
66
- table_name: table_name,
67
- key_schema: ks,
68
- provisioned_throughput: {read_capacity_units: read_capacity, write_capacity_units: write_capacity}
69
- })
70
- has_updates = true
71
- end
72
-
73
- if (has_updates)
74
- wait_until_table_available(table_name)
75
- puts "DynamoDB table #{table_name} is now fully available."
76
- end
77
-
78
- end
79
-
80
- ##
81
- # Deletes a DynamoDB table. It does not wait until the table has been deleted.
82
- #
83
- # *Arguments*
84
- # [table_name] The dynamoDB table name to delete.
85
- def delete_database(table_name)
86
-
87
- begin
88
- table_details = @client.describe_table(table_name: table_name).table
89
- wait_until_table_available(table_name) if (table_details.table_status != 'ACTIVE')
90
- @client.delete_table({table_name: table_name})
91
- rescue Aws::DynamoDB::Errors::ResourceNotFoundException
92
- puts 'Table did not exist. Nothing to delete.'
93
- end
94
-
95
- end
96
-
97
- ##
98
- # Awaits a given status of a table.
99
- #
100
- # *Arguments*
101
- # [table_name] The dynamoDB table name to watch until it reaches an active status.
102
- def wait_until_table_available(table_name)
103
-
104
- max_attempts = 24
105
- delay_between_attempts = 5
106
-
107
- # wait until the table has updated to being fully available
108
- # waiting for ~2min at most; an error will be thrown afterwards
109
- begin
110
- @client.wait_until(:table_exists, table_name: table_name) do |w|
111
- w.max_attempts = max_attempts
112
- w.delay = delay_between_attempts
113
- w.before_wait do |attempts, response|
114
- puts "Waiting until table becomes available. Attempt #{attempts}/#{max_attempts} with polling interval #{delay_between_attempts}."
115
- end
116
- end
117
- rescue Aws::Waiters::Errors::TooManyAttemptsError => e
118
- puts "Table #{table_name} did not become available after #{e.attempts} attempts. Try again later or inspect the AWS console."
119
- end
120
-
121
- end
122
-
123
- private :wait_until_table_available
18
+ def set_table_capacity(table_name, read_capacity, write_capacity)
19
+ puts "Updating new read/write capacity for table #{table_name}.
20
+ Read #{table_details.provisioned_throughput.read_capacity_units} ==> #{read_capacity}.
21
+ Write #{table_details.provisioned_throughput.write_capacity_units} ==> #{write_capacity}."
22
+ @client.update_table(
23
+ table_name: table_name,
24
+ provisioned_throughput: { read_capacity_units: read_capacity, write_capacity_units: write_capacity }
25
+ )
26
+ end
124
27
 
125
- end
28
+ ##
29
+ # Publishes the database and awaits until it is fully available. If the table already exists,
30
+ # it only adjusts the read and write
31
+ # capacities upwards (it doesn't downgrade them to avoid a production environment being impacted with
32
+ # a default setting of an automated script).
33
+ #
34
+ # *Arguments*
35
+ # [table_name] The table name of the dynamoDB to be created.
36
+ # [attribute_definitions] The dynamoDB attribute definitions to be used when the table is created.
37
+ # [key_schema] The dynamoDB key definitions to be used when the table is created.
38
+ # [read_capacity] The read capacity to configure for the dynamoDB table.
39
+ # [write_capacity] The write capacity to configure for the dynamoDB table.
40
+ def publish_database(table_name, attribute_definitions, key_schema, read_capacity, write_capacity)
41
+ has_updates = false
126
42
 
127
- end
43
+ # figure out whether the table exists
44
+ begin
45
+ table_details = @client.describe_table(table_name: table_name).table
46
+ rescue Aws::DynamoDB::Errors::ResourceNotFoundException
47
+ # skip this exception because we are using it for control flow.
48
+ table_details = nil
49
+ end
50
+
51
+ if table_details
52
+ wait_until_table_available(table_name) if table_details.table_status != 'ACTIVE'
53
+
54
+ if read_capacity > table_details.provisioned_throughput.read_capacity_units ||
55
+ write_capacity > table_details.provisioned_throughput.write_capacity_units
56
+
57
+ set_table_capacity read_capacity, write_capacity
58
+ has_updates = true
59
+ else
60
+ puts "Table #{table_name} already exists and the desired read capacity of #{read_capacity} and " \
61
+ "write capacity of #{write_capacity} has at least been configured. Downgrading capacity units is not " \
62
+ 'supported. No changes were applied.'
63
+ end
64
+ else
65
+ puts "Creating table #{table_name}."
66
+ ad = attribute_definitions || [{ attribute_name: 'Id', attribute_type: 'S' }]
67
+ ks = key_schema || [{ attribute_name: 'Id', key_type: 'HASH' }]
68
+ @client.create_table(table_name: table_name, key_schema: ks, attribute_definitions: ad,
69
+ provisioned_throughput:
70
+ { read_capacity_units: read_capacity, write_capacity_units: write_capacity })
71
+ has_updates = true
72
+ end
73
+
74
+ if has_updates
75
+ wait_until_table_available(table_name)
76
+ puts "DynamoDB table #{table_name} is now fully available."
77
+ end
78
+ end
79
+
80
+ ##
81
+ # Deletes a DynamoDB table. It does not wait until the table has been deleted.
82
+ #
83
+ # *Arguments*
84
+ # [table_name] The dynamoDB table name to delete.
85
+ def delete_database(table_name)
86
+ table_details = @client.describe_table(table_name: table_name).table
87
+ wait_until_table_available(table_name) if table_details.table_status != 'ACTIVE'
88
+ @client.delete_table(table_name: table_name)
89
+ rescue Aws::DynamoDB::Errors::ResourceNotFoundException
90
+ puts 'Table did not exist. Nothing to delete.'
91
+ end
92
+
93
+ ##
94
+ # Awaits a given status of a table.
95
+ #
96
+ # *Arguments*
97
+ # [table_name] The dynamoDB table name to watch until it reaches an active status.
98
+ def wait_until_table_available(table_name)
99
+ max_attempts = 24
100
+ delay_between_attempts = 5
101
+
102
+ # wait until the table has updated to being fully available
103
+ # waiting for ~2min at most; an error will be thrown afterwards
104
+ begin
105
+ @client.wait_until(:table_exists, table_name: table_name) do |w|
106
+ w.max_attempts = max_attempts
107
+ w.delay = delay_between_attempts
108
+ w.before_wait do |attempts, _|
109
+ puts "Waiting until table becomes available. Attempt #{attempts}/#{max_attempts} " \
110
+ "with polling interval #{delay_between_attempts}."
111
+ end
112
+ end
113
+ rescue Aws::Waiters::Errors::TooManyAttemptsError => e
114
+ puts "Table #{table_name} did not become available after #{e.attempts} attempts. " \
115
+ 'Try again later or inspect the AWS console.'
116
+ end
117
+ end
118
+
119
+ private :wait_until_table_available
120
+ end
121
+ end
@@ -1,172 +1,177 @@
1
1
  require 'aws-sdk'
2
- require_relative 'aws_setup'
3
2
 
4
3
  module LambdaWrap
5
-
6
- ##
7
- # The LambdaManager simplifies creating a package, publishing it to S3, deploying a new version, and setting permissions.
8
- #
9
- # Note: The concept of an environment of the LambdaWrap gem matches an alias of AWS Lambda.
10
- class LambdaManager
11
-
12
- ##
13
- # The constructor does some basic setup
14
- # * Validating basic AWS configuration
15
- # * Creating the underlying client to interace with the AWS SDK
16
- def initialize()
17
- AwsSetup.new.validate()
18
- # AWS lambda client
19
- @client = Aws::Lambda::Client.new()
20
- end
21
-
22
- ##
23
- # Packages a set of files and node modules into a deployable package.
24
- #
25
- # *Arguments*
26
- # [directory] A temporary directory to copy all related files before they are packages into a single zip file.
27
- # [zipfile] A path where the deployable package, a zip file, should be stored.
28
- # [input_filenames] A list of file names that contain the source code.
29
- # [node_modules] A list of node modules that need to be included in the package.
30
- def package(directory, zipfile, input_filenames, node_modules)
31
-
32
- FileUtils::mkdir_p directory
33
- FileUtils::mkdir_p File.join(directory, 'node_modules')
34
-
35
- input_filenames.each do |filename|
36
- FileUtils::copy_file(File.join(filename), File.join(directory, File.basename(filename)))
37
- end
38
-
39
- node_modules.each do |dir|
40
- FileUtils::cp_r(File.join('node_modules', dir), File.join(directory, 'node_modules'))
41
- end
42
-
43
- ZipFileGenerator.new(directory, zipfile).write
44
-
45
- end
46
-
47
- ##
48
- # Publishes a package to S3 so it can be deployed as a lambda function.
49
- #
50
- # *Arguments*
51
- # [local_lambda_file] The location of the package that needs to be deployed.
52
- # [bucket] The s3 bucket where the file needs to be uploaded to.
53
- # [key] The S3 path (key) where the package should be stored.
54
- def publish_lambda_to_s3(local_lambda_file, bucket, key)
55
-
56
- # get s3 object
57
- s3 = Aws::S3::Resource.new()
58
- obj = s3.bucket(bucket).object(key)
59
-
60
- # upload
61
- version_id = nil
62
- File.open(local_lambda_file, 'rb') do |file|
63
- version_id = obj.put({body: file}).version_id
64
- end
65
- raise 'Upload to S3 failed' if !version_id
66
-
67
- puts 'Uploaded object to S3 with version ' + version_id
68
- return version_id
69
-
70
- end
71
-
72
- ##
73
- # Deploys a package that has been uploaded to S3.
74
- #
75
- # *Arguments*
76
- # [bucket] The S3 bucket where the package can be retrieved from.
77
- # [key] The S3 path (key) where the package can be retrieved from.
78
- # [version_id] The version of the file on S3 to retrieve.
79
- # [function_name] The name of the lambda function.
80
- # [handler] The handler that should be executed for this lambda function.
81
- # [lambda_role] The arn of the IAM role that should be used when executing the lambda function.
82
- # [lambda_description] The description of the lambda function.
83
- # [vpc_subnet_ids] A list of subnet ids for the lambda's VPC configuration. All of the subnets must be on the same VPC.
84
- # [vpc_security_group_ids] A list of security group ids for the lambda's VPC configuration. All of the security_group_ids must be on the same VPC.
85
- def deploy_lambda(bucket, key, version_id, function_name, handler, lambda_role, lambda_description = "Deployed with LambdaWrap", vpc_subnet_ids = [], vpc_security_group_ids = [])
86
-
87
- # create or update function
88
-
89
- begin
90
- func = @client.get_function({function_name: function_name})
91
- func_config = @client.update_function_code({function_name: function_name, s3_bucket: bucket, s3_key: key, s3_object_version: version_id, publish: true}).data
92
- puts func_config
93
- func_version = func_config.version
94
- raise 'Error while publishing existing lambda function ' + function_name if !func_config.version
95
- rescue Aws::Lambda::Errors::ResourceNotFoundException
96
- func_config = @client.create_function({function_name: function_name, runtime: 'nodejs4.3', role: lambda_role, handler: handler, code: { s3_bucket: bucket, s3_key: key }, timeout: 5, memory_size: 128, publish: true, description: lambda_description, vpc_config: {subnet_ids: vpc_subnet_ids, security_group_ids: vpc_security_group_ids} }).data
97
- puts func_config
98
- func_version = func_config.version
99
- raise 'Error while publishing new lambda function ' + function_name if !func_config.version
100
- end
101
-
102
- add_api_gateway_permissions(function_name, nil)
103
-
104
- return func_version
105
-
106
- end
107
-
108
- ##
109
- # Creates an alias for a given lambda function version.
110
- #
111
- # *Arguments*
112
- # [function_name] The lambda function name for which the alias should be created.
113
- # [func_version] The lambda function versino to which the alias should point.
114
- # [alias_name] The name of the alias, matching the LambdaWrap environment concept.
115
- def create_alias(function_name, func_version, alias_name)
116
-
117
- # create or update alias
118
- func_alias = @client.list_aliases({function_name: function_name}).aliases.select{ |a| a.name == alias_name }.first()
119
- if (!func_alias)
120
- a = @client.create_alias({function_name: function_name, name: alias_name, function_version: func_version, description: 'created by an automated script'}).data
121
- puts a
122
- else
123
- a = @client.update_alias({function_name: function_name, name: alias_name, function_version: func_version, description: 'updated by an automated script'}).data
124
- puts a
125
- end
126
-
127
- add_api_gateway_permissions(function_name, alias_name)
128
-
129
- end
130
-
131
- ##
132
- # Removes an alias for a function.
133
- #
134
- # *Arguments*
135
- # [function_name] The lambda function name for which the alias should be removed.
136
- # [alias_name] The alias to remove.
137
- def remove_alias(function_name, alias_name)
138
-
139
- @client.delete_alias({function_name: function_name, name: alias_name})
140
-
141
- end
142
-
143
- ##
144
- # Adds permissions for API gateway to execute this function.
145
- #
146
- # *Arguments*
147
- # [function_name] The function name which needs to be executed from API Gateway.
148
- # [env] The environment (matching the function's alias) which needs to be executed from API Gateway. If nil, the permissions are set of the $LATEST version.
149
- def add_api_gateway_permissions(function_name, env)
150
- # permissions to execute lambda
151
- suffix = (':' + env if env) || ''
152
- func = @client.get_function({function_name: function_name + suffix}).data.configuration
153
- statement_id = func.function_name + (('-' + env if env) || '')
154
- policy_exists = false
155
- begin
156
- existing_policies = @client.get_policy({function_name: func.function_arn}).data
157
- existing_policy = JSON.parse(existing_policies.policy)
158
- policy_exists = existing_policy['Statement'].select{ |s| s['Sid'] == statement_id}.any?
159
- rescue Aws::Lambda::Errors::ResourceNotFoundException
160
- end
161
-
162
- if !policy_exists
163
- perm_add = @client.add_permission({function_name: func.function_arn, statement_id: statement_id, action: 'lambda:*', principal: 'apigateway.amazonaws.com'})
164
- puts perm_add.data
165
- end
166
- end
167
-
168
- private :add_api_gateway_permissions
169
-
170
- end
171
-
172
- end
4
+ ##
5
+ # The LambdaManager simplifies creating a package, publishing to S3, deploying a new version, & setting permissions.
6
+ #
7
+ # Note: The concept of an environment of the LambdaWrap gem matches an alias of AWS Lambda.
8
+ class LambdaManager
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.
20
+ #
21
+ # *Arguments*
22
+ # [directory] A temporary directory to copy all related files before they are packages into a single zip file.
23
+ # [zipfile] A path where the deployable package, a zip file, should be stored.
24
+ # [input_filenames] A list of file names that contain the source code.
25
+ # [node_modules] A list of node modules that need to be included in the package.
26
+ def package(directory, zipfile, input_filenames, node_modules)
27
+ FileUtils.mkdir_p directory
28
+ FileUtils.mkdir_p File.join(directory, 'node_modules')
29
+
30
+ input_filenames.each do |filename|
31
+ FileUtils.copy_file(File.join(filename), File.join(directory, File.basename(filename)))
32
+ end
33
+
34
+ node_modules.each do |dir|
35
+ FileUtils.cp_r(File.join('node_modules', dir), File.join(directory, 'node_modules'))
36
+ end
37
+
38
+ ZipFileGenerator.new(directory, zipfile).write
39
+ end
40
+
41
+ ##
42
+ # Publishes a package to S3 so it can be deployed as a lambda function.
43
+ #
44
+ # *Arguments*
45
+ # [local_lambda_file] The location of the package that needs to be deployed.
46
+ # [bucket] The s3 bucket where the file needs to be uploaded to.
47
+ # [key] The S3 path (key) where the package should be stored.
48
+ def publish_lambda_to_s3(local_lambda_file, bucket, key)
49
+ # get s3 object
50
+ s3 = Aws::S3::Resource.new
51
+ obj = s3.bucket(bucket).object(key)
52
+
53
+ # upload
54
+ version_id = nil
55
+ File.open(local_lambda_file, 'rb') do |file|
56
+ version_id = obj.put(body: file).version_id
57
+ end
58
+ raise 'Upload to S3 failed' unless version_id
59
+
60
+ puts 'Uploaded object to S3 with version ' + version_id
61
+ version_id
62
+ end
63
+
64
+ ##
65
+ # Deploys a package that has been uploaded to S3.
66
+ #
67
+ # *Arguments*
68
+ # [bucket] The S3 bucket where the package can be retrieved from.
69
+ # [key] The S3 path (key) where the package can be retrieved from.
70
+ # [version_id] The version of the file on S3 to retrieve.
71
+ # [function_name] The name of the lambda function.
72
+ # [handler] The handler that should be executed for this lambda function.
73
+ # [lambda_role] The arn of the IAM role that should be used when executing the lambda function.
74
+ # [lambda_description] The description of the lambda function.
75
+ # [vpc_subnet_ids] A list of subnet ids for the lambda's VPC configuration. All subnets must be on the same VPC.
76
+ # [vpc_security_group_ids] A list of security group ids for the lambda's VPC configuration. All of the
77
+ # security_group_ids must be on the same VPC.
78
+ def deploy_lambda(
79
+ bucket, key, version_id, function_name, handler, lambda_role,
80
+ lambda_description = 'Deployed with LambdaWrap', vpc_subnet_ids = [], vpc_security_group_ids = []
81
+ )
82
+ # create or update function
83
+
84
+ begin
85
+ @client.get_function(function_name: function_name)
86
+ func_config = @client.update_function_code(function_name: function_name, s3_bucket: bucket, s3_key: key,
87
+ s3_object_version: version_id, publish: true).data
88
+ puts func_config
89
+ func_version = func_config.version
90
+ raise 'Error while publishing existing lambda function ' + function_name unless func_version
91
+ rescue Aws::Lambda::Errors::ResourceNotFoundException
92
+ # if we cannot find it, we have to create it instead of updating it
93
+ func_config = @client.create_function(
94
+ function_name: function_name, runtime: 'nodejs4.3', role: lambda_role,
95
+ handler: handler, code: { s3_bucket: bucket, s3_key: key }, timeout: 5, memory_size: 128, publish: true,
96
+ description: lambda_description,
97
+ vpc_config: { subnet_ids: vpc_subnet_ids, security_group_ids: vpc_security_group_ids }
98
+ ).data
99
+ puts func_config
100
+ func_version = func_config.version
101
+ raise "Error while publishing new lambda function #{function_name}" unless func_version
102
+ end
103
+
104
+ add_api_gateway_permissions(function_name, nil)
105
+
106
+ func_version
107
+ end
108
+
109
+ ##
110
+ # Creates an alias for a given lambda function version.
111
+ #
112
+ # *Arguments*
113
+ # [function_name] The lambda function name for which the alias should be created.
114
+ # [func_version] The lambda function versino to which the alias should point.
115
+ # [alias_name] The name of the alias, matching the LambdaWrap environment concept.
116
+ def create_alias(function_name, func_version, alias_name)
117
+ # create or update alias
118
+ func_alias = @client.list_aliases(function_name: function_name).aliases.select { |a| a.name == alias_name }.first
119
+ if !func_alias
120
+ a = @client.create_alias(
121
+ function_name: function_name, name: alias_name, function_version: func_version,
122
+ description: 'created by an automated script'
123
+ ).data
124
+ else
125
+ a = @client.update_alias(
126
+ function_name: function_name, name: alias_name, function_version: func_version,
127
+ description: 'updated by an automated script'
128
+ ).data
129
+ end
130
+ puts a
131
+
132
+ add_api_gateway_permissions(function_name, alias_name)
133
+ end
134
+
135
+ ##
136
+ # Removes an alias for a function.
137
+ #
138
+ # *Arguments*
139
+ # [function_name] The lambda function name for which the alias should be removed.
140
+ # [alias_name] The alias to remove.
141
+ def remove_alias(function_name, alias_name)
142
+ @client.delete_alias(function_name: function_name, name: alias_name)
143
+ end
144
+
145
+ ##
146
+ # Adds permissions for API gateway to execute this function.
147
+ #
148
+ # *Arguments*
149
+ # [function_name] The function name which needs to be executed from API Gateway.
150
+ # [env] The environment (matching the function's alias) which needs to be executed from API Gateway.
151
+ # => If nil, the permissions are set of the $LATEST version.
152
+ def add_api_gateway_permissions(function_name, env)
153
+ # permissions to execute lambda
154
+ suffix = (':' + env if env) || ''
155
+ func = @client.get_function(function_name: function_name + suffix).data.configuration
156
+ statement_id = func.function_name + (('-' + env if env) || '')
157
+ begin
158
+ existing_policies = @client.get_policy(function_name: func.function_arn).data
159
+ existing_policy = JSON.parse(existing_policies.policy)
160
+ policy_exists = existing_policy['Statement'].select { |s| s['Sid'] == statement_id }.any?
161
+ rescue Aws::Lambda::Errors::ResourceNotFoundException
162
+ # policy does not exist, and that is ok
163
+ policy_exists = false
164
+ end
165
+
166
+ unless policy_exists
167
+ perm_add = @client.add_permission(
168
+ function_name: func.function_arn, statement_id: statement_id,
169
+ action: 'lambda:*', principal: 'apigateway.amazonaws.com'
170
+ )
171
+ puts perm_add.data
172
+ end
173
+ end
174
+
175
+ private :add_api_gateway_permissions
176
+ end
177
+ end
@@ -2,69 +2,66 @@ require 'rubygems'
2
2
  require 'zip'
3
3
 
4
4
  module LambdaWrap
5
-
5
+ ##
6
+ # Allows to easily zip a directory recursively. It's intended for gem internal use only.
7
+ #
8
+ # From the original example:
9
+ # This is a simple example which uses rubyzip to
10
+ # recursively generate a zip file from the contents of
11
+ # a specified directory. The directory itself is not
12
+ # included in the archive, rather just its contents.
13
+ #
14
+ # Usage:
15
+ # require /path/to/the/ZipFileGenerator/Class
16
+ # directoryToZip = "/tmp/input"
17
+ # outputFile = "/tmp/out.zip"
18
+ # zf = ZipFileGenerator.new(directoryToZip, outputFile)
19
+ # zf.write()
20
+ class ZipFileGenerator
6
21
  ##
7
- # Allows to easily zip a directory recursively. It's intended for gem internal use only.
8
- #
9
- # From the original example:
10
- # This is a simple example which uses rubyzip to
11
- # recursively generate a zip file from the contents of
12
- # a specified directory. The directory itself is not
13
- # included in the archive, rather just its contents.
14
- #
15
- # Usage:
16
- # require /path/to/the/ZipFileGenerator/Class
17
- # directoryToZip = "/tmp/input"
18
- # outputFile = "/tmp/out.zip"
19
- # zf = ZipFileGenerator.new(directoryToZip, outputFile)
20
- # zf.write()
21
- class ZipFileGenerator
22
-
23
- ##
24
- # Initialize with the directory to zip and the location of the output archive.
25
- def initialize(input_dir, output_file)
26
- @input_dir = input_dir
27
- @output_file = output_file
28
- end
29
-
30
- ##
31
- # Zip the input directory.
32
- def write
33
- entries = Dir.entries(@input_dir) - %w(. ..)
22
+ # Initialize with the directory to zip and the location of the output archive.
23
+ def initialize(input_dir, output_file)
24
+ @input_dir = input_dir
25
+ @output_file = output_file
26
+ end
34
27
 
35
- ::Zip::File.open(@output_file, ::Zip::File::CREATE) do |io|
36
- write_entries entries, '', io
37
- end
38
- end
28
+ ##
29
+ # Zip the input directory.
30
+ def write
31
+ entries = Dir.entries(@input_dir) - %w(. ..)
39
32
 
40
- private
33
+ Zip::File.open(@output_file, Zip::File::CREATE) do |io|
34
+ write_entries entries, '', io
35
+ end
36
+ end
41
37
 
42
- # A helper method to make the recursion work.
43
- def write_entries(entries, path, io)
44
- entries.each do |e|
45
- zip_file_path = path == '' ? e : File.join(path, e)
46
- disk_file_path = File.join(@input_dir, zip_file_path)
47
- puts "Deflating #{disk_file_path}"
38
+ private
48
39
 
49
- if File.directory? disk_file_path
50
- recursively_deflate_directory(disk_file_path, io, zip_file_path)
51
- else
52
- put_into_archive(disk_file_path, io, zip_file_path)
53
- end
54
- end
55
- end
40
+ # A helper method to make the recursion work.
41
+ def write_entries(entries, path, io)
42
+ entries.each do |e|
43
+ zip_file_path = path == '' ? e : File.join(path, e)
44
+ disk_file_path = File.join(@input_dir, zip_file_path)
45
+ puts "Deflating #{disk_file_path}"
56
46
 
57
- def recursively_deflate_directory(disk_file_path, io, zip_file_path)
58
- io.mkdir zip_file_path
59
- subdir = Dir.entries(disk_file_path) - %w(. ..)
60
- write_entries subdir, zip_file_path, io
47
+ if File.directory? disk_file_path
48
+ recursively_deflate_directory(disk_file_path, io, zip_file_path)
49
+ else
50
+ put_into_archive(disk_file_path, io, zip_file_path)
61
51
  end
52
+ end
53
+ end
62
54
 
63
- def put_into_archive(disk_file_path, io, zip_file_path)
64
- io.get_output_stream(zip_file_path) do |f|
65
- f.puts(File.open(disk_file_path, 'rb').read)
66
- end
67
- end
55
+ def recursively_deflate_directory(disk_file_path, io, zip_file_path)
56
+ io.mkdir zip_file_path
57
+ subdir = Dir.entries(disk_file_path) - %w(. ..)
58
+ write_entries subdir, zip_file_path, io
68
59
  end
69
60
 
70
- end
61
+ def put_into_archive(disk_file_path, io, zip_file_path)
62
+ io.get_output_stream(zip_file_path) do |f|
63
+ f.puts(File.open(disk_file_path, 'rb').read)
64
+ end
65
+ end
66
+ end
67
+ end
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.10.0
4
+ version: 0.11.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: 2016-06-13 00:00:00.000000000 Z
13
+ date: 2016-06-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws-sdk
@@ -27,20 +27,20 @@ dependencies:
27
27
  - !ruby/object:Gem::Version
28
28
  version: '2'
29
29
  - !ruby/object:Gem::Dependency
30
- name: zip
30
+ name: rubyzip
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
33
  - - "~>"
34
34
  - !ruby/object:Gem::Version
35
- version: '2'
35
+ version: '1.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: '2'
43
- description: This gem wraps the AWS SDK to simplify deployment of AWS Lambda functions
42
+ version: '1.2'
43
+ description: This gem wraps the AWS SDK to simplify deployment of AWSLambda functions
44
44
  backed by API Gateway and DynamoDB.
45
45
  email:
46
46
  executables: []
@@ -49,7 +49,6 @@ extra_rdoc_files: []
49
49
  files:
50
50
  - lib/lambda_wrap.rb
51
51
  - lib/lambda_wrap/api_gateway_manager.rb
52
- - lib/lambda_wrap/aws_setup.rb
53
52
  - lib/lambda_wrap/dynamo_db_manager.rb
54
53
  - lib/lambda_wrap/lambda_manager.rb
55
54
  - lib/lambda_wrap/zip_file_generator.rb
@@ -73,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
72
  version: '0'
74
73
  requirements: []
75
74
  rubyforge_project:
76
- rubygems_version: 2.4.7
75
+ rubygems_version: 2.2.5
77
76
  signing_key:
78
77
  specification_version: 4
79
78
  summary: Easy deployment of AWS Lambda functions and dependencies.
@@ -1,32 +0,0 @@
1
- require 'aws-sdk'
2
-
3
- ##
4
- # LambdaWrap is a ruby gem that simplifies deployment of AWS Lambda functions that are invoked through AWS API Gateway and optionally include a DynamoDB backend.
5
- module LambdaWrap
6
-
7
- ##
8
- # Helper class to ensure valid configuration of AWS.
9
- # This class is intended for internal use only, but clients can call it before calling any other functionality to ensure early failure.
10
- class AwsSetup
11
-
12
- ##
13
- # Validates that the setup is correct and that the bundled AWS certificate is used for subsequent calls to the AWS SDK
14
- #
15
- # *Required environment variables*
16
- # [AWS_ACCESS_KEY_ID] The AWS access key to be used when calling AWS SDK functions
17
- # [AWS_SECRET_ACCESS_KEY] The AWS secret to be used when calling AWS SDK functions
18
- # [AWS_REGION] A valid AWS region to use during configuration.
19
- def validate()
20
-
21
- # validate settings
22
- raise 'AWS_ACCESS_KEY_ID not set' if !ENV['AWS_ACCESS_KEY_ID']
23
- raise 'AWS_SECRET_ACCESS_KEY not set' if !ENV['AWS_SECRET_ACCESS_KEY']
24
- raise 'AWS_REGION not set' if !ENV['AWS_REGION']
25
-
26
- Aws::use_bundled_cert!
27
-
28
- end
29
-
30
- end
31
-
32
- end