class LambdaWrap::Lambda
Lambda
Manager class. Front loads the configuration to the constructor so that the developer can be more declarative with configuration and deployments. @since 1.0
Constants
- SUPPORTED_RUNTIMES
Public Class Methods
Initializes a Lambda
Manager. Frontloaded configuration.
@param [Hash] options The Configuration for the Lambda
@option options [String] :lambda_name The name you want to assign to the function you are uploading. The function
names appear in the console and are returned in the ListFunctions API. Function names are used to specify functions to other AWS Lambda API operations, such as Invoke. Note that the length constraint applies only to the ARN. If you specify only the function name, it is limited to 64 characters in length.
@option options [String] :handler The function within your code that Lambda
calls to begin execution. @option options [String] :role_arn The Amazon Resource Name (ARN) of the IAM role that Lambda
assumes when it
executes your function to access any other Amazon Web Services (AWS) resources.
@option options [String] :path_to_zip_file The absolute path to the Deployment Package zip file @option options [String] :runtime The runtime environment for the Lambda
function you are uploading. @option options [String] :description ('Deployed with LambdaWrap') A short, user-defined function description.
Lambda does not use this value. Assign a meaningful description as you see fit.
@option options [Integer] :timeout (30) The function execution time at which Lambda
should terminate the function. @option options [Integer] :memory_size (128) The amount of memory, in MB, your Lambda
function is given. Lambda
uses this memory size to infer the amount of CPU and memory allocated to your function. The value must be a multiple of 64MB. Minimum: 128, Maximum: 3008.
@option options [Array<String>] :subnet_ids ([]) If your Lambda
function accesses resources in a VPC, you provide
this parameter identifying the list of subnet IDs. These must belong to the same VPC. You must provide at least one security group and one subnet ID to configure VPC access.
@option options [Array<String>] :security_group_ids ([]) If your Lambda
function accesses resources in a VPC, you
provide this parameter identifying the list of security group IDs. These must belong to the same VPC. You must provide at least one security group and one subnet ID.
@option options [Boolean] :delete_unreferenced_versions (true) Option to delete any Lambda
Function Versions upon
deployment that do not have an alias pointing to them.
@option options [String] :dead_letter_queue_arn ('') The ARN of the SQS Queue for failed async invocations.
# File lib/lambda_wrap/lambda_manager.rb, line 38 def initialize(options) defaults = { description: 'Deployed with LambdaWrap', subnet_ids: [], security_group_ids: [], timeout: 30, memory_size: 128, delete_unreferenced_versions: true, dead_letter_queue_arn: '' } options_with_defaults = options.reverse_merge(defaults) unless (options_with_defaults[:lambda_name]) && (options_with_defaults[:lambda_name].is_a? String) raise ArgumentError, 'lambda_name must be provided (String)!' end @lambda_name = options_with_defaults[:lambda_name] unless (options_with_defaults[:handler]) && (options_with_defaults[:handler].is_a? String) raise ArgumentError, 'handler must be provided (String)!' end @handler = options_with_defaults[:handler] unless (options_with_defaults[:role_arn]) && (options_with_defaults[:role_arn].is_a? String) raise ArgumentError, 'role_arn must be provided (String)!' end @role_arn = options_with_defaults[:role_arn] unless (options_with_defaults[:path_to_zip_file]) && (options_with_defaults[:path_to_zip_file].is_a? String) raise ArgumentError, 'path_to_zip_file must be provided (String)!' end @path_to_zip_file = options_with_defaults[:path_to_zip_file] unless (options_with_defaults[:runtime]) && (options_with_defaults[:runtime].is_a? String) raise ArgumentError, 'runtime must be provided (String)!' end unless SUPPORTED_RUNTIMES.include?(options_with_defaults[:runtime]) raise ArgumentError, "Invalid Runtime specified: #{options_with_defaults[:runtime]}." \ "Only accepts: #{SUPPORTED_RUNTIMES}" end @runtime = options_with_defaults[:runtime] unless (options_with_defaults[:memory_size] % 64).zero? && (options_with_defaults[:memory_size] >= 128) && (options_with_defaults[:memory_size] <= 3008) raise ArgumentError, 'Invalid Memory Size.' end @memory_size = options_with_defaults[:memory_size] # VPC if options_with_defaults[:subnet_ids].empty? ^ options_with_defaults[:security_group_ids].empty? raise ArgumentError, 'Must supply values for BOTH Subnet Ids and Security Group ID if VPC is desired.' end unless options_with_defaults[:subnet_ids].empty? @vpc_configuration = { subnet_ids: options_with_defaults[:subnet_ids], security_group_ids: options_with_defaults[:security_group_ids] } end @description = options_with_defaults[:description] @timeout = options_with_defaults[:timeout] @delete_unreferenced_versions = options_with_defaults[:delete_unreferenced_versions] @dead_letter_queue_arn = options_with_defaults[:dead_letter_queue_arn] end
Public Instance Methods
Deletes the Lambda
Object with associated versions, code, configuration, and aliases.
@param client [Aws::Lambda::Client] Client to use with SDK. Should be passed in by the API
class. @param region [String] AWS Region string. Should be passed in by the API
class.
LambdaWrap::AwsService#delete
# File lib/lambda_wrap/lambda_manager.rb, line 147 def delete(client, region = 'AWS_REGION') super puts "Deleting all versions and aliases for Lambda: #{@lambda_name}" lambda_details = retrieve_lambda_details if lambda_details.nil? puts 'No Lambda to delete.' else options = { function_name: @lambda_name } @client.delete_function(options) puts "Lambda #{@lambda_name} and all Versions & Aliases have been deleted." end true end
Deploys the Lambda
to the specified Environment
. Creates a Lambda
Function if one didn't exist. Updates the Lambda's configuration, Updates the Lambda's Code, publishes a new version, and creates an alias that points to the newly published version. If the @delete_unreferenced_versions option is enabled, all Lambda
Function versions that don't have an alias pointing to them will be deleted.
@param environment_options [LambdaWrap::Environment] The target Environment
to deploy @param client [Aws::Lambda::Client] Client to use with SDK. Should be passed in by the API
class. @param region [String] AWS Region string. Should be passed in by the API
class.
LambdaWrap::AwsService#deploy
# File lib/lambda_wrap/lambda_manager.rb, line 104 def deploy(environment_options, client, region = 'AWS_REGION') super puts "Deploying Lambda: #{@lambda_name} to Environment: #{environment_options.name}" unless File.exist?(@path_to_zip_file) raise ArgumentError, "Deployment Package Zip File does not exist: #{@path_to_zip_file}!" end lambda_details = retrieve_lambda_details if lambda_details.nil? function_version = create_lambda else update_lambda_config function_version = update_lambda_code end create_alias(function_version, environment_options.name, environment_options.description) cleanup_unused_versions if @delete_unreferenced_versions puts "Lambda: #{@lambda_name} successfully deployed!" true end
Tearsdown an Environment
. Deletes an alias with the same name as the environment. Deletes Unreferenced Lambda
Function Versions if the option was specified.
@param environment_options [LambdaWrap::Environment] The target Environment
to teardown. @param client [Aws::Lambda::Client] Client to use with SDK. Should be passed in by the API
class. @param region [String] AWS Region string. Should be passed in by the API
class.
LambdaWrap::AwsService#teardown
# File lib/lambda_wrap/lambda_manager.rb, line 136 def teardown(environment_options, client, region = 'AWS_REGION') super remove_alias(environment_options.name) cleanup_unused_versions if @delete_unreferenced_versions true end
# File lib/lambda_wrap/lambda_manager.rb, line 161 def to_s return @lambda_name if @lambda_name && @lambda_name.is_a?(String) super end
Private Instance Methods
# File lib/lambda_wrap/lambda_manager.rb, line 313 def alias_exist?(alias_name) retrieve_all_aliases.detect { |a| a.name == alias_name } end
# File lib/lambda_wrap/lambda_manager.rb, line 258 def cleanup_unused_versions puts "Cleaning up unused function versions for #{@lambda_name}." function_versions_to_be_deleted = retrieve_all_function_versions - retrieve_function_versions_used_in_aliases return if function_versions_to_be_deleted.empty? function_versions_to_be_deleted.each do |version| puts "Deleting function version: #{version}." options = { function_name: @lambda_name, qualifier: version } @client.delete_function(options) end puts "Cleaned up #{function_versions_to_be_deleted.length} unused versions." end
# File lib/lambda_wrap/lambda_manager.rb, line 239 def create_alias(func_version, alias_name, alias_description) options = { function_name: @lambda_name, name: alias_name, function_version: func_version, description: alias_description || 'Alias managed by LambdaWrap' } if alias_exist?(alias_name) @client.update_alias(options) else @client.create_alias(options) end puts "Created Alias: #{alias_name} for Lambda: #{@lambda_name} v#{func_version}." end
# File lib/lambda_wrap/lambda_manager.rb, line 191 def create_lambda puts "Creating New Lambda Function: #{@lambda_name}...." puts "Runtime Engine: #{@runtime}, Timeout: #{@timeout}, Memory Size: #{@memory_size}." options = { function_name: @lambda_name, runtime: @runtime, role: @role_arn, handler: @handler, code: { zip_file: File.binread(@path_to_zip_file) }, description: @description, timeout: @timeout, memory_size: @memory_size, vpc_config: @vpc_configuration, publish: true } options[:dead_letter_config] = { target_arn: @dead_letter_queue_arn } unless @dead_letter_queue_arn.blank? lambda_version = @client.create_function(options).version puts "Successfully created Lambda: #{@lambda_name}!" lambda_version end
# File lib/lambda_wrap/lambda_manager.rb, line 252 def remove_alias(alias_name) puts "Deleting Alias: #{alias_name} for #{@lambda_name}" options = { function_name: @lambda_name, name: alias_name } @client.delete_alias(options) end
# File lib/lambda_wrap/lambda_manager.rb, line 292 def retrieve_all_aliases aliases = [] response = nil loop do options = { function_name: @lambda_name } unless !response || response.next_marker.nil? || response.next_marker.empty? options[:marker] = response.next_marker end response = @client.list_aliases(options) aliases.concat(response.aliases) return aliases if response.aliases.empty? || response.next_marker.nil? || response.next_marker.empty? end end
# File lib/lambda_wrap/lambda_manager.rb, line 274 def retrieve_all_function_versions function_versions = [] response = nil loop do options = { function_name: @lambda_name } unless !response || response.next_marker.nil? || response.next_marker.empty? options[:marker] = response.next_marker end response = @client.list_versions_by_function(options) function_versions.concat(response.versions.map(&:version)) if response.next_marker.nil? || response.next_marker.empty? return function_versions.reject { |v| v == '$LATEST' } end end end
# File lib/lambda_wrap/lambda_manager.rb, line 308 def retrieve_function_versions_used_in_aliases function_versions_with_aliases = Set.new [] function_versions_with_aliases.merge(retrieve_all_aliases.map(&:function_version)).to_a end
# File lib/lambda_wrap/lambda_manager.rb, line 180 def retrieve_lambda_details lambda_details = nil begin options = { function_name: @lambda_name } lambda_details = @client.get_function(options).configuration rescue Aws::Lambda::Errors::ResourceNotFoundException, Aws::Lambda::Errors::NotFound puts "Lambda #{@lambda_name} does not exist." end lambda_details end
# File lib/lambda_wrap/lambda_manager.rb, line 225 def update_lambda_code puts "Updating Lambda Code for #{@lambda_name}...." options = { function_name: @lambda_name, zip_file: File.binread(@path_to_zip_file), publish: true } response = @client.update_function_code(options) puts "Successully updated Lambda #{@lambda_name} code to version: #{response.version}" response.version end
# File lib/lambda_wrap/lambda_manager.rb, line 206 def update_lambda_config puts "Updating Lambda Config for #{@lambda_name}..." puts "Runtime Engine: #{@runtime}, Timeout: #{@timeout}, Memory Size: #{@memory_size}." if @vpc_configuration puts "With VPC Configuration: Subnets: #{@vpc_configuration[:subnet_ids]}, Security Groups: \ #{@vpc_configuration[:security_group_ids]}" end options = { function_name: @lambda_name, role: @role_arn, handler: @handler, description: @description, timeout: @timeout, memory_size: @memory_size, vpc_config: @vpc_configuration, runtime: @runtime } options[:dead_letter_config] = { target_arn: @dead_letter_queue_arn } unless @dead_letter_queue_arn.blank? @client.update_function_configuration(options) puts "Successfully updated Lambda configuration for #{@lambda_name}" end