lambda_wrap 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b0185f2b09d7ebb650e894aaddd7d05b78d2a37
|
4
|
+
data.tar.gz: 96c6d4ccc733e983018f4c957015972be4f9e1dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c75377c2eeaf091657c49303165f04e454f3183894d71afe6b427e51c24986f4762fc17d50958ff0bea284e5cd7e565cd53b5e0d70ea79914d311db3aa1c282
|
7
|
+
data.tar.gz: 5681101d09354da961ff4f847c73a42769390a148d25099f3ded29fd7fb74796113a35197615199a287b1213b448ae248a3f278bd4f285d0879eb8c79c1357e5
|
@@ -3,8 +3,18 @@ require_relative 'aws_setup'
|
|
3
3
|
|
4
4
|
module LambdaWrap
|
5
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.
|
6
11
|
class ApiGatewayManager
|
7
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
|
8
18
|
def initialize()
|
9
19
|
AwsSetup.new.validate()
|
10
20
|
# AWS api gateway client
|
@@ -13,6 +23,15 @@ module LambdaWrap
|
|
13
23
|
@jarpath = File.join(Dir.tmpdir, 'aws-apigateway-importer-1.0.3-SNAPSHOT-jar-with-dependencies.jar')
|
14
24
|
end
|
15
25
|
|
26
|
+
##
|
27
|
+
# Downloads the aws-apigateway-importer jar from an S3 bucket.
|
28
|
+
# This is a workaround since aws-apigateway-importer does not provide a binary.
|
29
|
+
# Once a binary is available on the public internet, we'll start using this instead
|
30
|
+
# of requiring users of this gem to upload their custom binary to an S3 bucket.
|
31
|
+
#
|
32
|
+
# *Arguments*
|
33
|
+
# [s3_bucket] An S3 bucket from where the aws-apigateway-importer binary can be downloaded.
|
34
|
+
# [s3_key] The path (key) to the aws-apigateay-importer binary on the s3 bucket.
|
16
35
|
def download_apigateway_importer(s3_bucket, s3_key)
|
17
36
|
unless File.exist?(@jarpath)
|
18
37
|
puts 'Downloading aws-apigateway-importer jar'
|
@@ -21,6 +40,14 @@ module LambdaWrap
|
|
21
40
|
end
|
22
41
|
end
|
23
42
|
|
43
|
+
##
|
44
|
+
# Sets up the API gateway by searching whether the API Gateway already exists
|
45
|
+
# and updates it with the latest information from the swagger file.
|
46
|
+
#
|
47
|
+
# *Arguments*
|
48
|
+
# [api_name] The name of the API to which the swagger file should be applied to.
|
49
|
+
# [env] The environment where it should be published (which is matching an API gateway stage)
|
50
|
+
# [swagger_file] A handle to a swagger file that should be used by aws-apigateway-importer
|
24
51
|
def setup_apigateway(api_name, env, swagger_file)
|
25
52
|
|
26
53
|
# ensure API is created
|
@@ -38,6 +65,13 @@ module LambdaWrap
|
|
38
65
|
|
39
66
|
end
|
40
67
|
|
68
|
+
##
|
69
|
+
# Shuts down an environment from the API Gateway. This basically deletes the stage
|
70
|
+
# from the API Gateway, but does not delete the API Gateway itself.
|
71
|
+
#
|
72
|
+
# *Argument*
|
73
|
+
# [api_name] The name of the API where the environment should be shut down.
|
74
|
+
# [env] The environment (matching an API Gateway stage) to shutdown.
|
41
75
|
def shutdown_apigateway(api_name, env)
|
42
76
|
|
43
77
|
api_id = get_existing_rest_api(api_name)
|
@@ -45,6 +79,11 @@ module LambdaWrap
|
|
45
79
|
|
46
80
|
end
|
47
81
|
|
82
|
+
##
|
83
|
+
# Gets the ID of an existing API Gateway api, or nil if it doesn't exist
|
84
|
+
#
|
85
|
+
# *Arguments*
|
86
|
+
# [api_name] The name of the API to be checked for existance
|
48
87
|
def get_existing_rest_api(api_name)
|
49
88
|
|
50
89
|
apis = @client.get_rest_apis({limit: 500}).data
|
@@ -58,6 +97,11 @@ module LambdaWrap
|
|
58
97
|
|
59
98
|
end
|
60
99
|
|
100
|
+
##
|
101
|
+
# Creates the API with a given name and returns the id
|
102
|
+
#
|
103
|
+
# *Arguments*
|
104
|
+
# [api_name] The name of the API to be created
|
61
105
|
def setup_apigateway_create_rest_api(api_name)
|
62
106
|
|
63
107
|
puts 'Creating API with name ' + api_name
|
@@ -67,6 +111,12 @@ module LambdaWrap
|
|
67
111
|
|
68
112
|
end
|
69
113
|
|
114
|
+
##
|
115
|
+
# Invokes the aws-apigateway-importer jar with the required parameter
|
116
|
+
#
|
117
|
+
# *Arguments*
|
118
|
+
# [api_id] The AWS ApiGateway id where the swagger file should be applied to.
|
119
|
+
# [swagger_file] The handle to a swagger definition file that should be imported into API Gateway
|
70
120
|
def setup_apigateway_create_resources(api_id, swagger_file)
|
71
121
|
|
72
122
|
raise 'API ID not provided' if !api_id
|
@@ -76,6 +126,12 @@ module LambdaWrap
|
|
76
126
|
|
77
127
|
end
|
78
128
|
|
129
|
+
##
|
130
|
+
# Creates a stage of the currently set resources
|
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.
|
79
135
|
def create_stages(api_id, env)
|
80
136
|
|
81
137
|
deployment_description = 'Deployment of service to ' + env
|
@@ -84,6 +140,12 @@ module LambdaWrap
|
|
84
140
|
|
85
141
|
end
|
86
142
|
|
143
|
+
##
|
144
|
+
# Deletes a stage of the API Gateway
|
145
|
+
#
|
146
|
+
# *Arguments*
|
147
|
+
# [api_id] The AWS ApiGateway id from which the stage should be deleted from.
|
148
|
+
# [env] The environment (which matches the stage in API Gateway) to delete.
|
87
149
|
def delete_stage(api_id, env)
|
88
150
|
|
89
151
|
begin
|
@@ -95,6 +157,8 @@ module LambdaWrap
|
|
95
157
|
|
96
158
|
end
|
97
159
|
|
160
|
+
private :get_existing_rest_api, :setup_apigateway_create_rest_api, :setup_apigateway_create_resources, :create_stages, :delete_stage
|
161
|
+
|
98
162
|
end
|
99
163
|
|
100
164
|
end
|
@@ -1,9 +1,21 @@
|
|
1
1
|
require 'aws-sdk'
|
2
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.
|
3
5
|
module LambdaWrap
|
4
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.
|
5
10
|
class AwsSetup
|
6
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.
|
7
19
|
def validate()
|
8
20
|
|
9
21
|
# validate settings
|
@@ -3,14 +3,34 @@ require_relative 'aws_setup'
|
|
3
3
|
|
4
4
|
module LambdaWrap
|
5
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.
|
6
11
|
class DynamoDbManager
|
7
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.
|
8
17
|
def initialize()
|
9
18
|
AwsSetup.new.validate()
|
10
19
|
# AWS dynamodb client
|
11
20
|
@client = Aws::DynamoDB::Client.new()
|
12
21
|
end
|
13
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.
|
14
34
|
def publish_database(table_name, attribute_definitions, key_schema, read_capacity, write_capacity)
|
15
35
|
|
16
36
|
has_updates = false
|
@@ -57,6 +77,11 @@ module LambdaWrap
|
|
57
77
|
|
58
78
|
end
|
59
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.
|
60
85
|
def delete_database(table_name)
|
61
86
|
|
62
87
|
begin
|
@@ -69,6 +94,11 @@ module LambdaWrap
|
|
69
94
|
|
70
95
|
end
|
71
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.
|
72
102
|
def wait_until_table_available(table_name)
|
73
103
|
|
74
104
|
max_attempts = 24
|
@@ -89,6 +119,8 @@ module LambdaWrap
|
|
89
119
|
end
|
90
120
|
|
91
121
|
end
|
122
|
+
|
123
|
+
private :wait_until_table_available
|
92
124
|
|
93
125
|
end
|
94
126
|
|
@@ -3,14 +3,30 @@ require_relative 'aws_setup'
|
|
3
3
|
|
4
4
|
module LambdaWrap
|
5
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.
|
6
10
|
class LambdaManager
|
7
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
|
8
16
|
def initialize()
|
9
17
|
AwsSetup.new.validate()
|
10
18
|
# AWS lambda client
|
11
19
|
@client = Aws::Lambda::Client.new()
|
12
20
|
end
|
13
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.
|
14
30
|
def package(directory, zipfile, input_filenames, node_modules)
|
15
31
|
|
16
32
|
FileUtils::mkdir_p directory
|
@@ -28,6 +44,13 @@ module LambdaWrap
|
|
28
44
|
|
29
45
|
end
|
30
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.
|
31
54
|
def publish_lambda_to_s3(local_lambda_file, bucket, key)
|
32
55
|
|
33
56
|
# get s3 object
|
@@ -46,18 +69,28 @@ module LambdaWrap
|
|
46
69
|
|
47
70
|
end
|
48
71
|
|
49
|
-
|
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
|
+
def deploy_lambda(bucket, key, version_id, function_name, handler, lambda_role)
|
50
83
|
|
51
84
|
# create or update function
|
52
85
|
|
53
86
|
begin
|
54
87
|
func = @client.get_function({function_name: function_name})
|
55
|
-
func_config = @client.update_function_code({function_name: function_name, s3_bucket:
|
88
|
+
func_config = @client.update_function_code({function_name: function_name, s3_bucket: bucket, s3_key: key, s3_object_version: version_id, publish: true}).data
|
56
89
|
puts func_config
|
57
90
|
func_version = func_config.version
|
58
91
|
raise 'Error while publishing existing lambda function ' + function_name if !func_config.version
|
59
92
|
rescue Aws::Lambda::Errors::ResourceNotFoundException
|
60
|
-
func_config = @client.create_function({function_name: function_name, runtime: 'nodejs', role:
|
93
|
+
func_config = @client.create_function({function_name: function_name, runtime: 'nodejs', role: lambda_role, handler: handler, code: { s3_bucket: bucket, s3_key: key }, timeout: 5, memory_size: 128, publish: true, description: 'created by an automated script'}).data
|
61
94
|
puts func_config
|
62
95
|
func_version = func_config.version
|
63
96
|
raise 'Error while publishing new lambda function ' + function_name if !func_config.version
|
@@ -69,6 +102,13 @@ module LambdaWrap
|
|
69
102
|
|
70
103
|
end
|
71
104
|
|
105
|
+
##
|
106
|
+
# Creates an alias for a given lambda function version.
|
107
|
+
#
|
108
|
+
# *Arguments*
|
109
|
+
# [function_name] The lambda function name for which the alias should be created.
|
110
|
+
# [func_version] The lambda function versino to which the alias should point.
|
111
|
+
# [alias_name] The name of the alias, matching the LambdaWrap environment concept.
|
72
112
|
def create_alias(function_name, func_version, alias_name)
|
73
113
|
|
74
114
|
# create or update alias
|
@@ -85,12 +125,24 @@ module LambdaWrap
|
|
85
125
|
|
86
126
|
end
|
87
127
|
|
128
|
+
##
|
129
|
+
# Removes an alias for a function.
|
130
|
+
#
|
131
|
+
# *Arguments*
|
132
|
+
# [function_name] The lambda function name for which the alias should be removed.
|
133
|
+
# [alias_name] The alias to remove.
|
88
134
|
def remove_alias(function_name, alias_name)
|
89
135
|
|
90
136
|
@client.delete_alias({function_name: function_name, name: alias_name})
|
91
137
|
|
92
138
|
end
|
93
139
|
|
140
|
+
##
|
141
|
+
# Adds permissions for API gateway to execute this function.
|
142
|
+
#
|
143
|
+
# *Arguments*
|
144
|
+
# [function_name] The function name which needs to be executed from API Gateway.
|
145
|
+
# [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.
|
94
146
|
def add_api_gateway_permissions(function_name, env)
|
95
147
|
# permissions to execute lambda
|
96
148
|
suffix = (':' + env if env) || ''
|
@@ -110,6 +162,8 @@ module LambdaWrap
|
|
110
162
|
end
|
111
163
|
end
|
112
164
|
|
165
|
+
private :add_api_gateway_permissions
|
166
|
+
|
113
167
|
end
|
114
168
|
|
115
169
|
end
|
@@ -1,26 +1,33 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'zip'
|
3
|
-
# This is a simple example which uses rubyzip to
|
4
|
-
# recursively generate a zip file from the contents of
|
5
|
-
# a specified directory. The directory itself is not
|
6
|
-
# included in the archive, rather just its contents.
|
7
|
-
#
|
8
|
-
# Usage:
|
9
|
-
# require /path/to/the/ZipFileGenerator/Class
|
10
|
-
# directoryToZip = "/tmp/input"
|
11
|
-
# outputFile = "/tmp/out.zip"
|
12
|
-
# zf = ZipFileGenerator.new(directoryToZip, outputFile)
|
13
|
-
# zf.write()
|
14
3
|
|
15
4
|
module LambdaWrap
|
16
5
|
|
6
|
+
##
|
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()
|
17
21
|
class ZipFileGenerator
|
22
|
+
|
23
|
+
##
|
18
24
|
# Initialize with the directory to zip and the location of the output archive.
|
19
25
|
def initialize(input_dir, output_file)
|
20
26
|
@input_dir = input_dir
|
21
27
|
@output_file = output_file
|
22
28
|
end
|
23
29
|
|
30
|
+
##
|
24
31
|
# Zip the input directory.
|
25
32
|
def write
|
26
33
|
entries = Dir.entries(@input_dir) - %w(. ..)
|
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: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Thurner
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-01-
|
12
|
+
date: 2016-01-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk
|