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: 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