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: 5f48ab03f6ee01f4084324fd582489720820a060
4
- data.tar.gz: f7a1b100285e4fd602f654211dc0ac6a34cf1a8c
3
+ metadata.gz: 1b0185f2b09d7ebb650e894aaddd7d05b78d2a37
4
+ data.tar.gz: 96c6d4ccc733e983018f4c957015972be4f9e1dc
5
5
  SHA512:
6
- metadata.gz: ed51f65ba43fe439c31319287b33e4f04e5f59f1d4385c05408713354e1529a20f1cf99f83ae1bca4ce7866fb9a7cd9af2ed504064b4e51eb29b5ebd7a77dbf8
7
- data.tar.gz: 4fece3ef3a2758a300cb838ab295fdabbf502a3576b30fd307e19666b0061594fc3d50438b4becc1942e7057eb414f2b767fbeec96e0c510fe78ce2b1c5bdde0
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
- def deploy_lambda(version_id, function_name, handler)
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: S3_BUCKET, s3_key: S3_KEY, s3_object_version: version_id, publish: true}).data
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: LAMBDA_ROLE_ARN, handler: handler, code: { s3_bucket: S3_BUCKET, s3_key: S3_KEY }, timeout: 5, memory_size: 128, publish: true, description: 'created by an automated script'}).data
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.3.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-05 00:00:00.000000000 Z
12
+ date: 2016-01-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk