lambda_wrap 0.3.0 → 0.4.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:
|
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
|