| # Copyright (c) 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved |
| # |
| # Permission is hereby granted, free of charge, to any person obtaining a |
| # copy of this software and associated documentation files (the |
| # "Software"), to deal in the Software without restriction, including |
| # without limitation the rights to use, copy, modify, merge, publish, dis- |
| # tribute, sublicense, and/or sell copies of the Software, and to permit |
| # persons to whom the Software is furnished to do so, subject to the fol- |
| # lowing conditions: |
| # |
| # The above copyright notice and this permission notice shall be included |
| # in all copies or substantial portions of the Software. |
| # |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- |
| # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT |
| # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| # IN THE SOFTWARE. |
| # |
| import os |
| |
| from boto.compat import json |
| from boto.exception import JSONResponseError |
| from boto.connection import AWSAuthConnection |
| from boto.regioninfo import RegionInfo |
| from boto.awslambda import exceptions |
| |
| |
| class AWSLambdaConnection(AWSAuthConnection): |
| """ |
| AWS Lambda |
| **Overview** |
| |
| This is the AWS Lambda API Reference. The AWS Lambda Developer |
| Guide provides additional information. For the service overview, |
| go to `What is AWS Lambda`_, and for information about how the |
| service works, go to `AWS LambdaL How it Works`_ in the AWS Lambda |
| Developer Guide. |
| """ |
| APIVersion = "2014-11-11" |
| DefaultRegionName = "us-east-1" |
| DefaultRegionEndpoint = "lambda.us-east-1.amazonaws.com" |
| ResponseError = JSONResponseError |
| |
| _faults = { |
| "InvalidRequestContentException": exceptions.InvalidRequestContentException, |
| "ResourceNotFoundException": exceptions.ResourceNotFoundException, |
| "InvalidParameterValueException": exceptions.InvalidParameterValueException, |
| "ServiceException": exceptions.ServiceException, |
| } |
| |
| |
| def __init__(self, **kwargs): |
| region = kwargs.get('region') |
| if not region: |
| region = RegionInfo(self, self.DefaultRegionName, |
| self.DefaultRegionEndpoint) |
| else: |
| del kwargs['region'] |
| kwargs['host'] = region.endpoint |
| super(AWSLambdaConnection, self).__init__(**kwargs) |
| self.region = region |
| |
| def _required_auth_capability(self): |
| return ['hmac-v4'] |
| |
| def add_event_source(self, event_source, function_name, role, |
| batch_size=None, parameters=None): |
| """ |
| Identifies an Amazon Kinesis stream as the event source for an |
| AWS Lambda function. AWS Lambda invokes the specified function |
| when records are posted to the stream. |
| |
| This is the pull model, where AWS Lambda invokes the function. |
| For more information, go to `AWS LambdaL How it Works`_ in the |
| AWS Lambda Developer Guide. |
| |
| This association between an Amazon Kinesis stream and an AWS |
| Lambda function is called the event source mapping. You |
| provide the configuration information (for example, which |
| stream to read from and which AWS Lambda function to invoke) |
| for the event source mapping in the request body. |
| |
| This operation requires permission for the `iam:PassRole` |
| action for the IAM role. It also requires permission for the |
| `lambda:AddEventSource` action. |
| |
| :type event_source: string |
| :param event_source: The Amazon Resource Name (ARN) of the Amazon |
| Kinesis stream that is the event source. Any record added to this |
| stream causes AWS Lambda to invoke your Lambda function. AWS Lambda |
| POSTs the Amazon Kinesis event, containing records, to your Lambda |
| function as JSON. |
| |
| :type function_name: string |
| :param function_name: The Lambda function to invoke when AWS Lambda |
| detects an event on the stream. |
| |
| :type role: string |
| :param role: The ARN of the IAM role (invocation role) that AWS Lambda |
| can assume to read from the stream and invoke the function. |
| |
| :type batch_size: integer |
| :param batch_size: The largest number of records that AWS Lambda will |
| give to your function in a single event. The default is 100 |
| records. |
| |
| :type parameters: map |
| :param parameters: A map (key-value pairs) defining the configuration |
| for AWS Lambda to use when reading the event source. Currently, AWS |
| Lambda supports only the `InitialPositionInStream` key. The valid |
| values are: "TRIM_HORIZON" and "LATEST". The default value is |
| "TRIM_HORIZON". For more information, go to `ShardIteratorType`_ in |
| the Amazon Kinesis Service API Reference. |
| |
| """ |
| |
| uri = '/2014-11-13/event-source-mappings/' |
| params = { |
| 'EventSource': event_source, |
| 'FunctionName': function_name, |
| 'Role': role, |
| } |
| headers = {} |
| query_params = {} |
| if batch_size is not None: |
| params['BatchSize'] = batch_size |
| if parameters is not None: |
| params['Parameters'] = parameters |
| return self.make_request('POST', uri, expected_status=200, |
| data=json.dumps(params), headers=headers, |
| params=query_params) |
| |
| def delete_function(self, function_name): |
| """ |
| Deletes the specified Lambda function code and configuration. |
| |
| This operation requires permission for the |
| `lambda:DeleteFunction` action. |
| |
| :type function_name: string |
| :param function_name: The Lambda function to delete. |
| |
| """ |
| |
| uri = '/2014-11-13/functions/{0}'.format(function_name) |
| return self.make_request('DELETE', uri, expected_status=204) |
| |
| def get_event_source(self, uuid): |
| """ |
| Returns configuration information for the specified event |
| source mapping (see AddEventSource). |
| |
| This operation requires permission for the |
| `lambda:GetEventSource` action. |
| |
| :type uuid: string |
| :param uuid: The AWS Lambda assigned ID of the event source mapping. |
| |
| """ |
| |
| uri = '/2014-11-13/event-source-mappings/{0}'.format(uuid) |
| return self.make_request('GET', uri, expected_status=200) |
| |
| def get_function(self, function_name): |
| """ |
| Returns the configuration information of the Lambda function |
| and a presigned URL link to the .zip file you uploaded with |
| UploadFunction so you can download the .zip file. Note that |
| the URL is valid for up to 10 minutes. The configuration |
| information is the same information you provided as parameters |
| when uploading the function. |
| |
| This operation requires permission for the |
| `lambda:GetFunction` action. |
| |
| :type function_name: string |
| :param function_name: The Lambda function name. |
| |
| """ |
| |
| uri = '/2014-11-13/functions/{0}'.format(function_name) |
| return self.make_request('GET', uri, expected_status=200) |
| |
| def get_function_configuration(self, function_name): |
| """ |
| Returns the configuration information of the Lambda function. |
| This the same information you provided as parameters when |
| uploading the function by using UploadFunction. |
| |
| This operation requires permission for the |
| `lambda:GetFunctionConfiguration` operation. |
| |
| :type function_name: string |
| :param function_name: The name of the Lambda function for which you |
| want to retrieve the configuration information. |
| |
| """ |
| |
| uri = '/2014-11-13/functions/{0}/configuration'.format(function_name) |
| return self.make_request('GET', uri, expected_status=200) |
| |
| def invoke_async(self, function_name, invoke_args): |
| """ |
| Submits an invocation request to AWS Lambda. Upon receiving |
| the request, Lambda executes the specified function |
| asynchronously. To see the logs generated by the Lambda |
| function execution, see the CloudWatch logs console. |
| |
| This operation requires permission for the |
| `lambda:InvokeAsync` action. |
| |
| :type function_name: string |
| :param function_name: The Lambda function name. |
| |
| :type invoke_args: blob |
| :param invoke_args: JSON that you want to provide to your Lambda |
| function as input. |
| |
| """ |
| uri = '/2014-11-13/functions/{0}/invoke-async/'.format(function_name) |
| headers = {} |
| query_params = {} |
| try: |
| content_length = str(len(invoke_args)) |
| except (TypeError, AttributeError): |
| # If a file like object is provided and seekable, try to retrieve |
| # the file size via fstat. |
| try: |
| invoke_args.tell() |
| except (AttributeError, OSError, IOError): |
| raise TypeError( |
| "File-like object passed to parameter " |
| "``invoke_args`` must be seekable." |
| ) |
| content_length = str(os.fstat(invoke_args.fileno()).st_size) |
| headers['Content-Length'] = content_length |
| return self.make_request('POST', uri, expected_status=202, |
| data=invoke_args, headers=headers, |
| params=query_params) |
| |
| def list_event_sources(self, event_source_arn=None, function_name=None, |
| marker=None, max_items=None): |
| """ |
| Returns a list of event source mappings. For each mapping, the |
| API returns configuration information (see AddEventSource). |
| You can optionally specify filters to retrieve specific event |
| source mappings. |
| |
| This operation requires permission for the |
| `lambda:ListEventSources` action. |
| |
| :type event_source_arn: string |
| :param event_source_arn: The Amazon Resource Name (ARN) of the Amazon |
| Kinesis stream. |
| |
| :type function_name: string |
| :param function_name: The name of the AWS Lambda function. |
| |
| :type marker: string |
| :param marker: Optional string. An opaque pagination token returned |
| from a previous `ListEventSources` operation. If present, specifies |
| to continue the list from where the returning call left off. |
| |
| :type max_items: integer |
| :param max_items: Optional integer. Specifies the maximum number of |
| event sources to return in response. This value must be greater |
| than 0. |
| |
| """ |
| |
| uri = '/2014-11-13/event-source-mappings/' |
| params = {} |
| headers = {} |
| query_params = {} |
| if event_source_arn is not None: |
| query_params['EventSource'] = event_source_arn |
| if function_name is not None: |
| query_params['FunctionName'] = function_name |
| if marker is not None: |
| query_params['Marker'] = marker |
| if max_items is not None: |
| query_params['MaxItems'] = max_items |
| return self.make_request('GET', uri, expected_status=200, |
| data=json.dumps(params), headers=headers, |
| params=query_params) |
| |
| def list_functions(self, marker=None, max_items=None): |
| """ |
| Returns a list of your Lambda functions. For each function, |
| the response includes the function configuration information. |
| You must use GetFunction to retrieve the code for your |
| function. |
| |
| This operation requires permission for the |
| `lambda:ListFunctions` action. |
| |
| :type marker: string |
| :param marker: Optional string. An opaque pagination token returned |
| from a previous `ListFunctions` operation. If present, indicates |
| where to continue the listing. |
| |
| :type max_items: integer |
| :param max_items: Optional integer. Specifies the maximum number of AWS |
| Lambda functions to return in response. This parameter value must |
| be greater than 0. |
| |
| """ |
| |
| uri = '/2014-11-13/functions/' |
| params = {} |
| headers = {} |
| query_params = {} |
| if marker is not None: |
| query_params['Marker'] = marker |
| if max_items is not None: |
| query_params['MaxItems'] = max_items |
| return self.make_request('GET', uri, expected_status=200, |
| data=json.dumps(params), headers=headers, |
| params=query_params) |
| |
| def remove_event_source(self, uuid): |
| """ |
| Removes an event source mapping. This means AWS Lambda will no |
| longer invoke the function for events in the associated |
| source. |
| |
| This operation requires permission for the |
| `lambda:RemoveEventSource` action. |
| |
| :type uuid: string |
| :param uuid: The event source mapping ID. |
| |
| """ |
| |
| uri = '/2014-11-13/event-source-mappings/{0}'.format(uuid) |
| return self.make_request('DELETE', uri, expected_status=204) |
| |
| def update_function_configuration(self, function_name, role=None, |
| handler=None, description=None, |
| timeout=None, memory_size=None): |
| """ |
| Updates the configuration parameters for the specified Lambda |
| function by using the values provided in the request. You |
| provide only the parameters you want to change. This operation |
| must only be used on an existing Lambda function and cannot be |
| used to update the function's code. |
| |
| This operation requires permission for the |
| `lambda:UpdateFunctionConfiguration` action. |
| |
| :type function_name: string |
| :param function_name: The name of the Lambda function. |
| |
| :type role: string |
| :param role: The Amazon Resource Name (ARN) of the IAM role that Lambda |
| will assume when it executes your function. |
| |
| :type handler: string |
| :param handler: The function that Lambda calls to begin executing your |
| function. For Node.js, it is the module-name.export value in your |
| function. |
| |
| :type description: string |
| :param description: A short user-defined function description. Lambda |
| does not use this value. Assign a meaningful description as you see |
| fit. |
| |
| :type timeout: integer |
| :param timeout: The function execution time at which Lambda should |
| terminate the function. Because the execution time has cost |
| implications, we recommend you set this value based on your |
| expected execution time. The default is 3 seconds. |
| |
| :type memory_size: integer |
| :param memory_size: The amount of memory, in MB, your Lambda function |
| is given. Lambda uses this memory size to infer the amount of CPU |
| allocated to your function. Your function use-case determines your |
| CPU and memory requirements. For example, a database operation |
| might need less memory compared to an image processing function. |
| The default value is 128 MB. The value must be a multiple of 64 MB. |
| |
| """ |
| |
| uri = '/2014-11-13/functions/{0}/configuration'.format(function_name) |
| params = {} |
| headers = {} |
| query_params = {} |
| if role is not None: |
| query_params['Role'] = role |
| if handler is not None: |
| query_params['Handler'] = handler |
| if description is not None: |
| query_params['Description'] = description |
| if timeout is not None: |
| query_params['Timeout'] = timeout |
| if memory_size is not None: |
| query_params['MemorySize'] = memory_size |
| return self.make_request('PUT', uri, expected_status=200, |
| data=json.dumps(params), headers=headers, |
| params=query_params) |
| |
| def upload_function(self, function_name, function_zip, runtime, role, |
| handler, mode, description=None, timeout=None, |
| memory_size=None): |
| """ |
| Creates a new Lambda function or updates an existing function. |
| The function metadata is created from the request parameters, |
| and the code for the function is provided by a .zip file in |
| the request body. If the function name already exists, the |
| existing Lambda function is updated with the new code and |
| metadata. |
| |
| This operation requires permission for the |
| `lambda:UploadFunction` action. |
| |
| :type function_name: string |
| :param function_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 APIs, such as InvokeAsync. |
| |
| :type function_zip: blob |
| :param function_zip: A .zip file containing your packaged source code. |
| For more information about creating a .zip file, go to `AWS LambdaL |
| How it Works`_ in the AWS Lambda Developer Guide. |
| |
| :type runtime: string |
| :param runtime: The runtime environment for the Lambda function you are |
| uploading. Currently, Lambda supports only "nodejs" as the runtime. |
| |
| :type role: string |
| :param role: 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. |
| |
| :type handler: string |
| :param handler: The function that Lambda calls to begin execution. For |
| Node.js, it is the module-name . export value in your function. |
| |
| :type mode: string |
| :param mode: How the Lambda function will be invoked. Lambda supports |
| only the "event" mode. |
| |
| :type description: string |
| :param description: A short, user-defined function description. Lambda |
| does not use this value. Assign a meaningful description as you see |
| fit. |
| |
| :type timeout: integer |
| :param timeout: The function execution time at which Lambda should |
| terminate the function. Because the execution time has cost |
| implications, we recommend you set this value based on your |
| expected execution time. The default is 3 seconds. |
| |
| :type memory_size: integer |
| :param memory_size: The amount of memory, in MB, your Lambda function |
| is given. Lambda uses this memory size to infer the amount of CPU |
| allocated to your function. Your function use-case determines your |
| CPU and memory requirements. For example, database operation might |
| need less memory compared to image processing function. The default |
| value is 128 MB. The value must be a multiple of 64 MB. |
| |
| """ |
| uri = '/2014-11-13/functions/{0}'.format(function_name) |
| headers = {} |
| query_params = {} |
| if runtime is not None: |
| query_params['Runtime'] = runtime |
| if role is not None: |
| query_params['Role'] = role |
| if handler is not None: |
| query_params['Handler'] = handler |
| if mode is not None: |
| query_params['Mode'] = mode |
| if description is not None: |
| query_params['Description'] = description |
| if timeout is not None: |
| query_params['Timeout'] = timeout |
| if memory_size is not None: |
| query_params['MemorySize'] = memory_size |
| |
| try: |
| content_length = str(len(function_zip)) |
| except (TypeError, AttributeError): |
| # If a file like object is provided and seekable, try to retrieve |
| # the file size via fstat. |
| try: |
| function_zip.tell() |
| except (AttributeError, OSError, IOError): |
| raise TypeError( |
| "File-like object passed to parameter " |
| "``function_zip`` must be seekable." |
| ) |
| content_length = str(os.fstat(function_zip.fileno()).st_size) |
| headers['Content-Length'] = content_length |
| return self.make_request('PUT', uri, expected_status=201, |
| data=function_zip, headers=headers, |
| params=query_params) |
| |
| def make_request(self, verb, resource, headers=None, data='', |
| expected_status=None, params=None): |
| if headers is None: |
| headers = {} |
| response = AWSAuthConnection.make_request( |
| self, verb, resource, headers=headers, data=data, params=params) |
| body = response.read().decode('utf-8') |
| if body: |
| body = json.loads(body) |
| if response.status == expected_status: |
| return body |
| else: |
| error_type = response.getheader('x-amzn-ErrorType').split(':')[0] |
| error_class = self._faults.get(error_type, self.ResponseError) |
| raise error_class(response.status, response.reason, body) |