class Fog::AWS::Lambda::Mock

Attributes

account_id[R]
aws_access_key_id[R]
region[R]

Public Class Methods

data() click to toggle source
# File lib/fog/aws/lambda.rb, line 30
def self.data
  @data ||= Hash.new do |hash, region|
    hash[region] = Hash.new do |region_hash, key|
      region_hash[key] = {
        :functions             => {},
        :permissions           => {},
        :event_source_mappings => {}
      }
    end
  end
end
new(options={}) click to toggle source
# File lib/fog/aws/lambda.rb, line 46
def initialize(options={})
  @region            = options[:region] || 'us-east-1'
  @aws_access_key_id = options[:aws_access_key_id]
  @account_id        = Fog::AWS::Mock.owner_id
  @module            = "lambda"

  Fog::AWS.validate_region!(@region)
end

Public Instance Methods

add_permission(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/add_permission.rb, line 47
def add_permission(params={})
  function_id = params.delete('FunctionName')
  function = self.get_function_configuration(
    'FunctionName' => function_id
  ).body
  function_arn = function['FunctionArn']

  action         = params.delete('Action')
  principal      = params.delete('Principal')
  source_account = params.delete('SourceAccount')
  source_arn     = params.delete('SourceArn')
  sid            = params.delete('StatementId')

  if action.nil? || action.empty?
    message = 'Action cannot be blank'
    raise Fog::AWS::Lambda::Error, message
  end

  if principal.nil? || principal.empty?
    message = 'Principal cannot be blank'
    raise Fog::AWS::Lambda::Error, message
  end

  if sid.nil? || sid.empty?
    message = 'Sid cannot be blank'
    raise Fog::AWS::Lambda::Error, message
  end

  statement = {
    'Action'      => [action],
    'Principal'   => { 'Service' => principal },
    'Sid'         => sid,
    'Resource'    => function_arn,
    'Effect'      => 'Allow'
  }
  if source_arn
    statement['Condition'] = {}
    statement['Condition']['ArnLike'] = {
      'AWS:SourceArn' => source_arn
    }
  end

  self.data[:permissions][function_arn] ||= []
  self.data[:permissions][function_arn] << statement

  response = Excon::Response.new
  response.status = 201
  response.body = { 'Statement' => statement }
  response
end
create_event_source_mapping(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/create_event_source_mapping.rb, line 49
def create_event_source_mapping(params={})
  enabled          = params.delete('Enabled')   || false
  batch_size       = params.delete('BatchSize') || 100
  event_source_arn = params.delete('EventSourceArn')
  function_name    = params.delete('FunctionName')
  starting_pos     = params.delete('StartingPosition')

  function = self.get_function_configuration('FunctionName' => function_name).body

  unless event_source_arn
    message  = "ValidationException => "
    message << "'eventSourceArn' cannot be blank"
    raise Fog::AWS::Lambda::Error, message
  end

  unless starting_pos
    message  = "ValidationException => "
    message << "'startingPosition' cannot be blank"
    raise Fog::AWS::Lambda::Error, message
  end

  event_source_mapping_id = UUID.uuid
  event_source_mapping = {
    'BatchSize'             => batch_size,
    'EventSourceArn'        => event_source_arn,
    'FunctionArn'           => function['FunctionArn'],
    'LastModified'          => Time.now.to_f,
    'LastProcessingResult'  => 'No records processed',
    'State'                 => 'Creating',
    'StateTransitionReason' => 'User action',
    'UUID'                  => event_source_mapping_id
  }

  self.data[:event_source_mappings].merge!(
    event_source_mapping_id => event_source_mapping
  )

  response = Excon::Response.new
  response.body = event_source_mapping
  response.status = 202
  response
end
create_function(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/create_function.rb, line 66
def create_function(params={})
  response = Excon::Response.new

  runtime = params.delete('Runtime') || 'nodejs'
  if !%w(nodejs java8).include?(runtime)
    message = 'ValidationException: Runtime must be nodejs or java8.'
    raise Fog::AWS::Lambda::Error, message
  end

  unless code = params.delete('Code')
    message = 'ValidationException: Code cannot be blank.'
    raise Fog::AWS::Lambda::Error, message
  end

  unless function_name = params.delete('FunctionName')
    message = 'ValidationException: Function name cannot be blank.'
    raise Fog::AWS::Lambda::Error, message
  end

  unless handler = params.delete('Handler')
    message = 'ValidationException: Handler cannot be blank.'
    raise Fog::AWS::Lambda::Error, message
  end

  unless role = params.delete('Role')
    message = 'ValidationException: Role cannot be blank.'
    raise Fog::AWS::Lambda::Error, message
  end

  code_size = if code.has_key?('ZipFile')
    Base64.decode64(code['ZipFile']).length
  else
    Fog::Mock.random_numbers(5).to_i
  end

  description = params.delete('Description')

  function = {}
  begin
    opts     = { 'FunctionName' => function_name }
    function = self.get_function_configuration(opts).body
  rescue Fog::AWS::Lambda::Error => e
    # ignore: if the function doesn't exist we are OK.
  end

  if !function.empty?
    message  = "ResourceConflictException => "
    message << "Function already exist: #{function_name}"
    raise Fog::AWS::Lambda::Error, message
  end

  function_path = "function:#{function_name}"
  function_arn = Fog::AWS::Mock.arn(
    'lambda',
    self.account_id,
    function_path,
    self.region
  )

  function = {
    'CodeSize'     => code_size,
    'FunctionArn'  => function_arn,
    'FunctionName' => function_name,
    'Handler'      => handler,
    'LastModified' => Time.now.utc,
    'MemorySize'   => params.delete('MemorySize') || 128,
    'Timeout'      => params.delete('Timeout')    || 3,
    'Role'         => role,
    'Runtime'      => runtime
  }
  function['Description'] = description if description

  self.data[:functions][function_arn] = function
  response.body   = function
  response.status = 200
  response
end
data() click to toggle source
# File lib/fog/aws/lambda.rb, line 55
def data
  self.class.data[@region][@aws_access_key_id]
end
delete_event_source_mapping(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/delete_event_source_mapping.rb, line 24
def delete_event_source_mapping(params={})
  mapping = self.get_event_source_mapping(params).body

  unless mapping
    message  = "ResourceNotFoundException => "
    message << "The resource you requested does not exist."
    raise Fog::AWS::Lambda::Error, message
  end

  mapping_id = mapping['UUID']
  self.data[:event_source_mappings].delete(mapping_id)

  mapping['State'] = 'Deleting'

  response = Excon::Response.new
  response.status = 202
  response.body = mapping
  response
end
delete_function(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/delete_function.rb, line 24
def delete_function(params={})
  response = Excon::Response.new
  response.status = 204
  response.body = ''

  function = self.get_function_configuration(params).body
  function_id = function['FunctionArn']

  self.data[:functions].delete function_id
  self.data[:permissions].delete function_id
  self.data[:event_source_mappings].delete_if do |m,f|
    f['FunctionArn'].eql?(function_id)
  end

  response
end
get_event_source_mapping(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/get_event_source_mapping.rb, line 32
def get_event_source_mapping(params={})
  mapping_id = params.delete('UUID')

  unless mapping = self.data[:event_source_mappings][mapping_id]
    message  = 'ResourceNotFoundException => '
    message << 'The resource you requested does not exist.'
    raise Fog::AWS::Lambda::Error, message
  end

  if mapping['State'].eql?('Creating')
    mapping['LastProcessingResult'] = 'OK'
    mapping['State'] = 'Enabled'
  end

  response = Excon::Response.new
  response.status = 200
  response.body = mapping
  response
end
get_function(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/get_function.rb, line 27
def get_function(params={})
  response = Excon::Response.new
  response.status = 200
  response.body = ''

  unless function_id = params.delete('FunctionName')
    raise Fog::AWS::Lambda::Error, 'Function name cannot be blank.'
  end

  if function_id.match(/^arn:aws:lambda:.+:function:.+/)
    function = self.data[:functions][function_id]
  else
    search_function = Hash[
      self.data[:functions].select do |f,v|
        v['FunctionName'].eql?(function_id)
      end
    ]
    function = search_function.values.first
  end

  msg = 'The resource you requested does not exist.'
  raise Fog::AWS::Lambda::Error, msg if (function.nil? || function.empty?)

  location = "https://awslambda-#{self.region}-tasks.s3-#{self.region}"
  location << ".amazonaws.com/snapshot/#{self.account_id}/"
  location << "#{function['FunctionName']}-#{UUID.uuid}"
  location << '?x-amz-security-token='
  location << Fog::Mock.random_base64(718)
  location << "&AWSAccessKeyId=#{self.aws_access_key_id}"
  location << "&Expires=#{Time.now.to_i + 60*10}"
  location << '&Signature='
  location << Fog::Mock.random_base64(28)

  body = {
    'Code' => {
      'Location'       => location,
      'RepositoryType' => 'S3'
    },
    'Configuration' => function
  }
  response.body = body

  response
end
get_function_configuration(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/get_function_configuration.rb, line 35
def get_function_configuration(params={})
  response = self.get_function(params)
  function_configuration = response.body['Configuration']
  response.body = function_configuration
  response
end
get_policy(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/get_policy.rb, line 26
def get_policy(params={})
  response = Excon::Response.new

  function     = self.get_function_configuration(params).body
  function_arn = function['FunctionArn']
  statements   = self.data[:permissions][function_arn] || []

  if statements.empty?
    message = "ResourceNotFoundException => "
    message << "The resource you requested does not exist."
    raise Fog::AWS::Lambda::Error, message
  end

  policy = {
    'Version'   => '2012-10-17',
    'Statement' => statements,
    'Id'        => 'default'
  }

  response.status = 200
  response.body = { 'Policy' => policy }
  response
end
invoke(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/invoke.rb, line 43
def invoke(params={})
  response = Excon::Response.new
  response.status = 200
  response.body = ''

  unless function_id = params.delete('FunctionName')
    message = 'AccessDeniedException => '
    message << 'Unable to determine service/operation name to be authorized'
    raise Fog::AWS::Lambda::Error, message
  end

  client_context  = params.delete('ClientContext')
  invocation_type = params.delete('InvocationType')
  log_type        = params.delete('LogType')
  payload         = params.delete('Payload')

  if (client_context || invocation_type || log_type)
    message = "invoke parameters handling are not yet mocked [light_black](#{caller.first})[/]"
    Fog::Logger.warning message
    Fog::Mock.not_implemented
  end

  if payload
    message = "payload parameter is ignored since we are not really "
    message << "invoking a function [light_black](#{caller.first})[/]"
    Fog::Logger.warning message
  end

  function = self.get_function_configuration('FunctionName' => function_id).body

  if function.is_a?(Hash) && function.has_key?('FunctionArn')
    response.body = "\"Imagine #{function['FunctionArn']} was invoked\""
  else
    message = "ResourceNotFoundException => Function not found: #{function_id}"
    raise Fog::AWS::Lambda::Error, message
  end

  response
end
list_event_source_mappings(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/list_event_source_mappings.rb, line 38
def list_event_source_mappings(params={})
  response = Excon::Response.new
  response.status = 200

  function_name = params.delete('FunctionName')

  begin
    function = self.get_function_configuration('FunctionName' => function_name).body
    function_arn = function['FunctionArn']
  rescue Fog::AWS::Lambda::Error => e
    # interestingly enough, if you try to do a list_event_source_mappings
    # on a nonexisting function, Lambda API endpoint doesn't return
    # error, just an empty array.
  end

  event_source_mappings = []
  if function_arn
    event_source_mappings = self.data[:event_source_mappings].values.select do |m|
      m['FunctionArn'].eql?(function_arn)
    end
  end

  response.body = {
    'EventSourceMappings' => event_source_mappings,
    'NextMarker'          => nil
  }
  response
end
list_functions(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/list_functions.rb, line 27
def list_functions(params={})
  response = Excon::Response.new
  response.status = 200
  response.body = {
    'Functions'  => self.data[:functions].values,
    'NextMarker' => nil
  }
  response
end
remove_permission(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/remove_permission.rb, line 26
def remove_permission(params={})
  function_name = params.delete('FunctionName')
  opts = { 'FunctionName' => function_name }
  function     = self.get_function_configuration(opts).body
  function_arn = function['FunctionArn']

  statement_id = params.delete('StatementId')
  message      = 'Statement ID cannot be blank'
  raise Fog::AWS::Lambda::Error, message unless statement_id

  permissions_qty = self.data[:permissions][function_arn].size

  self.data[:permissions][function_arn].delete_if do |s|
    s['Sid'].eql?(statement_id)
  end

  if self.data[:permissions][function_arn].size.eql?(permissions_qty)
    message  = "ResourceNotFoundException => "
    message << "The resource you requested does not exist."
    raise Fog::AWS::Lambda::Error, message
  end

  response        = Excon::Response.new
  response.status = 204
  response.body   =  ''
  response
end
reset_data() click to toggle source
# File lib/fog/aws/lambda.rb, line 59
def reset_data
  self.class.data[@region].delete(@aws_access_key_id)
end
update_event_source_mapping(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/update_event_source_mapping.rb, line 45
def update_event_source_mapping(params={})
  mapping_id = params.delete('UUID')
  mapping = self.data[:event_source_mappings][mapping_id]

  unless mapping
    message  = 'ResourceNotFoundException => '
    message << 'The resource you requested does not exist.'
    raise Fog::AWS::Lambda::Error, message
  end

  function_name = params.delete('FunctionName')
  function = {}
  if function_name
    function_opts = { 'FunctionName' => function_name }
    function      = self.get_function_configuration(function_opts).body
    function_arn  = function['FunctionArn']
  end

  batch_size = params.delete('BatchSize')
  enabled    = params.delete('Enabled')

  update = {}

  if function_name && !function.empty? && function_arn
    update.merge!('FunctionArn' => function_arn)
  end
  update.merge!('BatchSize' => batch_size) if batch_size
  update.merge!('Enabled'   => enabled)    if !enabled.nil?

  mapping.merge!(update)
  mapping['State'] = 'Disabling' if enabled.eql?(false)
  mapping['State'] = 'Enabling'  if enabled.eql?(true)

  response = Excon::Response.new
  response.status = 202
  response.body = mapping
  response
end
update_function_code(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/update_function_code.rb, line 52
def update_function_code(params={})
  response = self.get_function_configuration(params)

  request_data = []
  %w(S3Bucket S3Key S3ObjectVersion ZipFile).each do |p|
    request_data << params.delete(p) if params.has_key?(p)
  end

  message = 'Please provide a source for function code.'
  raise Fog::AWS::Lambda::Error, message if request_data.empty?
  # we ignore any parameters since we are not uploading any code

  function_arn = response.body['FunctionArn']

  response = Excon::Response.new
  response.status = 200
  response.body = self.data[:functions][function_arn]

  response
end
update_function_configuration(params={}) click to toggle source
# File lib/fog/aws/requests/lambda/update_function_configuration.rb, line 55
def update_function_configuration(params={})
  response = self.get_function_configuration(params)

  function_arn = response.body['FunctionArn']

  description = params.delete('Description')
  handler     = params.delete('Handler')
  memory_size = params.delete('MemorySize')
  role        = params.delete('Role')
  timeout     = params.delete('Timeout')

  update = {}
  update.merge!('Description' => description) if description
  update.merge!('Handler'     => handler)     if handler
  update.merge!('MemorySize'  => memory_size) if memory_size
  update.merge!('Role'        => role)        if role
  update.merge!('Timeout'     => timeout)     if timeout

  self.data[:functions][function_arn].merge!(update)

  response = Excon::Response.new
  response.status = 200
  response.body = self.data[:functions][function_arn]

  response
end