Best Python code snippet using localstack_python
lambda_api.py
Source:lambda_api.py  
...225    return get_function_version(arn, str(last_version + 1))226def do_list_versions(arn):227    return sorted([get_function_version(arn, version) for version in228                   arn_to_lambda.get(arn).versions.keys()], key=lambda k: str(k.get('Version')))229def do_update_alias(arn, alias, version, description=None):230    new_alias = {231        'AliasArn': arn + ':' + alias,232        'FunctionVersion': version,233        'Name': alias,234        'Description': description or ''235    }236    arn_to_lambda.get(arn).aliases[alias] = new_alias237    return new_alias238@cloudwatched('lambda')239def run_lambda(event, context, func_arn, version=None, suppress_output=False, asynchronous=False):240    if suppress_output:241        stdout_ = sys.stdout242        stderr_ = sys.stderr243        stream = StringIO()244        sys.stdout = stream245        sys.stderr = stream246    try:247        func_details = arn_to_lambda.get(func_arn)248        if not context:249            context = LambdaContext(func_details, version)250        result, log_output = LAMBDA_EXECUTOR.execute(func_arn, func_details,251            event, context=context, version=version, asynchronous=asynchronous)252    except Exception as e:253        return error_response('Error executing Lambda function: %s %s' % (e, traceback.format_exc()))254    finally:255        if suppress_output:256            sys.stdout = stdout_257            sys.stderr = stderr_258    return result259def exec_lambda_code(script, handler_function='handler', lambda_cwd=None, lambda_env=None):260    if lambda_cwd or lambda_env:261        exec_mutex.acquire()262        if lambda_cwd:263            previous_cwd = os.getcwd()264            os.chdir(lambda_cwd)265            sys.path = [lambda_cwd] + sys.path266        if lambda_env:267            previous_env = dict(os.environ)268            os.environ.update(lambda_env)269    # generate lambda file name270    lambda_id = 'l_%s' % short_uid()271    lambda_file = LAMBDA_SCRIPT_PATTERN.replace('*', lambda_id)272    save_file(lambda_file, script)273    # delete temporary .py and .pyc files on exit274    TMP_FILES.append(lambda_file)275    TMP_FILES.append('%sc' % lambda_file)276    try:277        handler_module = imp.load_source(lambda_id, lambda_file)278        module_vars = handler_module.__dict__279    except Exception as e:280        LOG.error('Unable to exec: %s %s' % (script, traceback.format_exc()))281        raise e282    finally:283        if lambda_cwd or lambda_env:284            if lambda_cwd:285                os.chdir(previous_cwd)286                sys.path.pop(0)287            if lambda_env:288                os.environ = previous_env289            exec_mutex.release()290    return module_vars[handler_function]291def get_handler_file_from_name(handler_name, runtime=LAMBDA_DEFAULT_RUNTIME):292    # TODO: support Java Lambdas in the future293    delimiter = '.'294    if runtime.startswith(LAMBDA_RUNTIME_NODEJS):295        file_ext = '.js'296    elif runtime.startswith(LAMBDA_RUNTIME_GOLANG):297        file_ext = ''298    elif runtime.startswith(LAMBDA_RUNTIME_DOTNETCORE2):299        file_ext = '.dll'300        delimiter = ':'301    else:302        file_ext = '.py'303    return '%s%s' % (handler_name.split(delimiter)[0], file_ext)304def get_handler_function_from_name(handler_name, runtime=LAMBDA_DEFAULT_RUNTIME):305    # TODO: support Java Lambdas in the future306    if runtime.startswith(LAMBDA_RUNTIME_DOTNETCORE2):307        return handler_name.split(':')[-1]308    else:309        return handler_name.split('.')[-1]310def error_response(msg, code=500, error_type='InternalFailure'):311    LOG.warning(msg)312    return aws_responses.flask_error_response(msg, code=code, error_type=error_type)313def get_zip_bytes(function_code):314    """Returns the ZIP file contents from a FunctionCode dict.315    :type function_code: dict316    :param function_code: https://docs.aws.amazon.com/lambda/latest/dg/API_FunctionCode.html317    :returns: bytes of the Zip file.318    """319    if 'S3Bucket' in function_code:320        s3_client = aws_stack.connect_to_service('s3')321        bytes_io = BytesIO()322        try:323            s3_client.download_fileobj(function_code['S3Bucket'], function_code['S3Key'], bytes_io)324            zip_file_content = bytes_io.getvalue()325        except Exception as e:326            return error_response('Unable to fetch Lambda archive from S3: %s' % e, 404)327    elif 'ZipFile' in function_code:328        zip_file_content = function_code['ZipFile']329        zip_file_content = base64.b64decode(zip_file_content)330    else:331        return error_response('No valid Lambda archive specified.', 400)332    return zip_file_content333def get_java_handler(zip_file_content, handler, main_file):334    """Creates a Java handler from an uploaded ZIP or JAR.335    :type zip_file_content: bytes336    :param zip_file_content: ZIP file bytes.337    :type handler: str338    :param handler: The lambda handler path.339    :type main_file: str340    :param main_file: Filepath to the uploaded ZIP or JAR file.341    :returns: function or flask.Response342    """343    if not is_jar_archive(zip_file_content):344        with zipfile.ZipFile(BytesIO(zip_file_content)) as zip_ref:345            jar_entries = [e for e in zip_ref.infolist() if e.filename.endswith('.jar')]346            if len(jar_entries) != 1:347                raise Exception('Expected exactly one *.jar entry in zip file, found %s' % len(jar_entries))348            zip_file_content = zip_ref.read(jar_entries[0].filename)349            LOG.info('Found jar file %s with %s bytes in Lambda zip archive' %350                     (jar_entries[0].filename, len(zip_file_content)))351            main_file = new_tmp_file()352            save_file(main_file, zip_file_content)353    if is_jar_archive(zip_file_content):354        def execute(event, context):355            result, log_output = lambda_executors.EXECUTOR_LOCAL.execute_java_lambda(356                event, context, handler=handler, main_file=main_file)357            return result358        return execute359    return error_response(360        'Unable to extract Java Lambda handler - file is not a valid zip/jar files', 400, error_type='ValidationError')361def set_function_code(code, lambda_name):362    def generic_handler(event, context):363        raise Exception(('Unable to find executor for Lambda function "%s". ' +364            'Note that Node.js and .NET Core Lambdas currently require LAMBDA_EXECUTOR=docker') % lambda_name)365    lambda_cwd = None366    arn = func_arn(lambda_name)367    runtime = arn_to_lambda[arn].runtime368    handler_name = arn_to_lambda.get(arn).handler369    lambda_environment = arn_to_lambda.get(arn).envvars370    if not handler_name:371        handler_name = LAMBDA_DEFAULT_HANDLER372    # Stop/remove any containers that this arn uses.373    LAMBDA_EXECUTOR.cleanup(arn)374    # Save the zip file to a temporary file that the lambda executors can reference.375    zip_file_content = get_zip_bytes(code)376    if isinstance(zip_file_content, Response):377        return zip_file_content378    tmp_dir = '%s/zipfile.%s' % (config.TMP_FOLDER, short_uid())379    mkdir(tmp_dir)380    tmp_file = '%s/%s' % (tmp_dir, LAMBDA_ZIP_FILE_NAME)381    save_file(tmp_file, zip_file_content)382    TMP_FILES.append(tmp_dir)383    lambda_cwd = tmp_dir384    # Set the appropriate lambda handler.385    lambda_handler = generic_handler386    if runtime == LAMBDA_RUNTIME_JAVA8:387        # The Lambda executors for Docker subclass LambdaExecutorContainers,388        # which runs Lambda in Docker by passing all *.jar files in the function389        # working directory as part of the classpath. Because of this, we need to390        # save the zip_file_content as a .jar here.391        if is_jar_archive(zip_file_content):392            jar_tmp_file = '{working_dir}/{file_name}'.format(393                working_dir=tmp_dir, file_name=LAMBDA_JAR_FILE_NAME)394            save_file(jar_tmp_file, zip_file_content)395        lambda_handler = get_java_handler(zip_file_content, handler_name, tmp_file)396        if isinstance(lambda_handler, Response):397            return lambda_handler398    else:399        handler_file = get_handler_file_from_name(handler_name, runtime=runtime)400        handler_function = get_handler_function_from_name(handler_name, runtime=runtime)401        # Lambda code must be uploaded in the Zip format.402        if not is_zip_file(zip_file_content):403            raise Exception(404                'Uploaded Lambda code for runtime ({}) is not in Zip format'.format(runtime))405        unzip(tmp_file, tmp_dir)406        main_file = '%s/%s' % (tmp_dir, handler_file)407        if os.path.isfile(main_file):408            # make sure the file is actually readable, then read contents409            ensure_readable(main_file)410            with open(main_file, 'rb') as file_obj:411                zip_file_content = file_obj.read()412        else:413            file_list = run('ls -la %s' % tmp_dir)414            LOG.debug('Lambda archive content:\n%s' % file_list)415            return error_response(416                'Unable to find handler script in Lambda archive.', 400,417                error_type='ValidationError')418        if runtime.startswith('python') and not use_docker():419            try:420                lambda_handler = exec_lambda_code(421                    zip_file_content,422                    handler_function=handler_function,423                    lambda_cwd=lambda_cwd,424                    lambda_env=lambda_environment)425            except Exception as e:426                raise Exception('Unable to get handler function from lambda code.', e)427    add_function_mapping(lambda_name, lambda_handler, lambda_cwd)428    return {'FunctionName': lambda_name}429def do_list_functions():430    funcs = []431    for f_arn, func in iteritems(arn_to_lambda):432        func_name = f_arn.split(':function:')[-1]433        arn = func_arn(func_name)434        func_details = arn_to_lambda.get(arn)435        funcs.append(format_func_details(func_details))436    return funcs437def format_func_details(func_details, version=None, always_add_version=False):438    version = version or '$LATEST'439    result = {440        'Version': version,441        'FunctionArn': func_details.arn(),442        'FunctionName': func_details.name(),443        'CodeSize': func_details.get_version(version).get('CodeSize'),444        'Handler': func_details.handler,445        'Runtime': func_details.runtime,446        'Timeout': func_details.timeout,447        'Environment': func_details.envvars,448        # 'Description': ''449        # 'MemorySize': 192,450    }451    if (always_add_version or version != '$LATEST') and len(result['FunctionArn'].split(':')) <= 7:452        result['FunctionArn'] += ':%s' % (version)453    return result454# ------------455# API METHODS456# ------------457@app.route('%s/functions' % PATH_ROOT, methods=['POST'])458def create_function():459    """ Create new function460        ---461        operationId: 'createFunction'462        parameters:463            - name: 'request'464              in: body465    """466    arn = 'n/a'467    try:468        data = json.loads(to_str(request.data))469        lambda_name = data['FunctionName']470        event_publisher.fire_event(event_publisher.EVENT_LAMBDA_CREATE_FUNC,471            payload={'n': event_publisher.get_hash(lambda_name)})472        arn = func_arn(lambda_name)473        if arn in arn_to_lambda:474            return error_response('Function already exist: %s' %475                lambda_name, 409, error_type='ResourceConflictException')476        arn_to_lambda[arn] = func_details = LambdaFunction(arn)477        func_details.versions = {'$LATEST': {'CodeSize': 50}}478        func_details.handler = data['Handler']479        func_details.runtime = data['Runtime']480        func_details.envvars = data.get('Environment', {}).get('Variables', {})481        func_details.timeout = data.get('Timeout')482        result = set_function_code(data['Code'], lambda_name)483        if isinstance(result, Response):484            del arn_to_lambda[arn]485            return result486        result.update({487            'DeadLetterConfig': data.get('DeadLetterConfig'),488            'Description': data.get('Description'),489            'Environment': {'Error': {}, 'Variables': func_details.envvars},490            'FunctionArn': arn,491            'FunctionName': lambda_name,492            'Handler': func_details.handler,493            'MemorySize': data.get('MemorySize'),494            'Role': data.get('Role'),495            'Runtime': func_details.runtime,496            'Timeout': data.get('Timeout'),497            'TracingConfig': {},498            'VpcConfig': {'SecurityGroupIds': [None], 'SubnetIds': [None], 'VpcId': None}499        })500        if data.get('Publish', False):501            result['Version'] = publish_new_function_version(arn)['Version']502        return jsonify(result or {})503    except Exception as e:504        del arn_to_lambda[arn]505        return error_response('Unknown error: %s %s' % (e, traceback.format_exc()))506@app.route('%s/functions/<function>' % PATH_ROOT, methods=['GET'])507def get_function(function):508    """ Get details for a single function509        ---510        operationId: 'getFunction'511        parameters:512            - name: 'request'513              in: body514            - name: 'function'515              in: path516    """517    funcs = do_list_functions()518    for func in funcs:519        if func['FunctionName'] == function:520            result = {521                'Configuration': func,522                'Code': {523                    'Location': '%s/code' % request.url524                }525            }526            lambda_details = arn_to_lambda.get(func['FunctionArn'])527            if lambda_details.concurrency is not None:528                result['Concurrency'] = lambda_details.concurrency529            return jsonify(result)530    return error_response(531        'Function not found: %s' % func_arn(function), 404, error_type='ResourceNotFoundException')532@app.route('%s/functions/' % PATH_ROOT, methods=['GET'])533def list_functions():534    """ List functions535        ---536        operationId: 'listFunctions'537        parameters:538            - name: 'request'539              in: body540    """541    funcs = do_list_functions()542    result = {}543    result['Functions'] = funcs544    return jsonify(result)545@app.route('%s/functions/<function>' % PATH_ROOT, methods=['DELETE'])546def delete_function(function):547    """ Delete an existing function548        ---549        operationId: 'deleteFunction'550        parameters:551            - name: 'request'552              in: body553    """554    arn = func_arn(function)555    # Stop/remove any containers that this arn uses.556    LAMBDA_EXECUTOR.cleanup(arn)557    try:558        arn_to_lambda.pop(arn)559    except KeyError:560        return error_response('Function does not exist: %s' % function, 404, error_type='ResourceNotFoundException')561    event_publisher.fire_event(event_publisher.EVENT_LAMBDA_DELETE_FUNC,562        payload={'n': event_publisher.get_hash(function)})563    i = 0564    while i < len(event_source_mappings):565        mapping = event_source_mappings[i]566        if mapping['FunctionArn'] == arn:567            del event_source_mappings[i]568            i -= 1569        i += 1570    result = {}571    return jsonify(result)572@app.route('%s/functions/<function>/code' % PATH_ROOT, methods=['PUT'])573def update_function_code(function):574    """ Update the code of an existing function575        ---576        operationId: 'updateFunctionCode'577        parameters:578            - name: 'request'579              in: body580    """581    data = json.loads(to_str(request.data))582    result = set_function_code(data, function)583    return jsonify(result or {})584@app.route('%s/functions/<function>/code' % PATH_ROOT, methods=['GET'])585def get_function_code(function):586    """ Get the code of an existing function587        ---588        operationId: 'getFunctionCode'589        parameters:590    """591    arn = func_arn(function)592    lambda_cwd = arn_to_lambda[arn].cwd593    tmp_file = '%s/%s' % (lambda_cwd, LAMBDA_ZIP_FILE_NAME)594    return Response(load_file(tmp_file, mode='rb'),595            mimetype='application/zip',596            headers={'Content-Disposition': 'attachment; filename=lambda_archive.zip'})597@app.route('%s/functions/<function>/configuration' % PATH_ROOT, methods=['GET'])598def get_function_configuration(function):599    """ Get the configuration of an existing function600        ---601        operationId: 'getFunctionConfiguration'602        parameters:603    """604    arn = func_arn(function)605    lambda_details = arn_to_lambda.get(arn)606    if not lambda_details:607        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')608    result = format_func_details(lambda_details)609    return jsonify(result)610@app.route('%s/functions/<function>/configuration' % PATH_ROOT, methods=['PUT'])611def update_function_configuration(function):612    """ Update the configuration of an existing function613        ---614        operationId: 'updateFunctionConfiguration'615        parameters:616            - name: 'request'617              in: body618    """619    data = json.loads(to_str(request.data))620    arn = func_arn(function)621    # Stop/remove any containers that this arn uses.622    LAMBDA_EXECUTOR.cleanup(arn)623    lambda_details = arn_to_lambda[arn]624    if data.get('Handler'):625        lambda_details.handler = data['Handler']626    if data.get('Runtime'):627        lambda_details.runtime = data['Runtime']628    if data.get('Environment'):629        lambda_details.envvars = data.get('Environment', {}).get('Variables', {})630    if data.get('Timeout'):631        lambda_details.timeout = data['Timeout']632    result = {}633    return jsonify(result)634@app.route('%s/functions/<function>/invocations' % PATH_ROOT, methods=['POST'])635def invoke_function(function):636    """ Invoke an existing function637        ---638        operationId: 'invokeFunction'639        parameters:640            - name: 'request'641              in: body642    """643    # function here can either be an arn or a function name644    arn = func_arn(function)645    # arn can also contain a qualifier, extract it from there if so646    m = re.match('(arn:aws:lambda:.*:.*:function:[a-zA-Z0-9-_]+)(:.*)?', arn)647    if m and m.group(2):648        qualifier = m.group(2)[1:]649        arn = m.group(1)650    else:651        qualifier = request.args.get('Qualifier')652    if arn not in arn_to_lambda:653        return error_response('Function does not exist: %s' % arn, 404, error_type='ResourceNotFoundException')654    if qualifier and not arn_to_lambda.get(arn).qualifier_exists(qualifier):655        return error_response('Function does not exist: {0}:{1}'.format(arn, qualifier), 404,656                              error_type='ResourceNotFoundException')657    data = None658    if request.data:659        try:660            data = json.loads(to_str(request.data))661        except Exception:662            return error_response('The payload is not JSON', 415, error_type='UnsupportedMediaTypeException')663    # Default invocation type is RequestResponse664    invocation_type = request.environ.get('HTTP_X_AMZ_INVOCATION_TYPE', 'RequestResponse')665    if invocation_type == 'RequestResponse':666        result = run_lambda(asynchronous=False, func_arn=arn, event=data, context={}, version=qualifier)667        if isinstance(result, dict):668            return jsonify(result)669        if result:670            return result671        return make_response('', 200)672    elif invocation_type == 'Event':673        run_lambda(asynchronous=True, func_arn=arn, event=data, context={}, version=qualifier)674        return make_response('', 202)675    elif invocation_type == 'DryRun':676        # Assume the dry run always passes.677        return make_response('', 204)678    else:679        return error_response('Invocation type not one of: RequestResponse, Event or DryRun',680                              code=400,681                              error_type='InvalidParameterValueException')682@app.route('%s/event-source-mappings/' % PATH_ROOT, methods=['GET'])683def list_event_source_mappings():684    """ List event source mappings685        ---686        operationId: 'listEventSourceMappings'687    """688    event_source_arn = request.args.get('EventSourceArn')689    function_name = request.args.get('FunctionName')690    mappings = event_source_mappings691    if event_source_arn:692        mappings = [m for m in mappings if event_source_arn == m.get('EventSourceArn')]693    if function_name:694        function_arn = func_arn(function_name)695        mappings = [m for m in mappings if function_arn == m.get('FunctionArn')]696    response = {697        'EventSourceMappings': mappings698    }699    return jsonify(response)700@app.route('%s/event-source-mappings/<mapping_uuid>' % PATH_ROOT, methods=['GET'])701def get_event_source_mapping(mapping_uuid):702    """ Get an existing event source mapping703        ---704        operationId: 'getEventSourceMapping'705        parameters:706            - name: 'request'707              in: body708    """709    mappings = event_source_mappings710    mappings = [m for m in mappings if mapping_uuid == m.get('UUID')]711    if len(mappings) == 0:712        return error_response('The resource you requested does not exist.', 404, error_type='ResourceNotFoundException')713    return jsonify(mappings[0])714@app.route('%s/event-source-mappings/' % PATH_ROOT, methods=['POST'])715def create_event_source_mapping():716    """ Create new event source mapping717        ---718        operationId: 'createEventSourceMapping'719        parameters:720            - name: 'request'721              in: body722    """723    data = json.loads(to_str(request.data))724    mapping = add_event_source(data['FunctionName'], data['EventSourceArn'])725    return jsonify(mapping)726@app.route('%s/event-source-mappings/<mapping_uuid>' % PATH_ROOT, methods=['PUT'])727def update_event_source_mapping(mapping_uuid):728    """ Update an existing event source mapping729        ---730        operationId: 'updateEventSourceMapping'731        parameters:732            - name: 'request'733              in: body734    """735    data = json.loads(request.data)736    if not mapping_uuid:737        return jsonify({})738    function_name = data.get('FunctionName') or ''739    enabled = data.get('Enabled') or True740    batch_size = data.get('BatchSize') or 100741    mapping = update_event_source(mapping_uuid, function_name, enabled, batch_size)742    return jsonify(mapping)743@app.route('%s/event-source-mappings/<mapping_uuid>' % PATH_ROOT, methods=['DELETE'])744def delete_event_source_mapping(mapping_uuid):745    """ Delete an event source mapping746        ---747        operationId: 'deleteEventSourceMapping'748    """749    if not mapping_uuid:750        return jsonify({})751    mapping = delete_event_source(mapping_uuid)752    return jsonify(mapping)753@app.route('%s/functions/<function>/versions' % PATH_ROOT, methods=['POST'])754def publish_version(function):755    arn = func_arn(function)756    if arn not in arn_to_lambda:757        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')758    return jsonify(publish_new_function_version(arn))759@app.route('%s/functions/<function>/versions' % PATH_ROOT, methods=['GET'])760def list_versions(function):761    arn = func_arn(function)762    if arn not in arn_to_lambda:763        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')764    return jsonify({'Versions': do_list_versions(arn)})765@app.route('%s/functions/<function>/aliases' % PATH_ROOT, methods=['POST'])766def create_alias(function):767    arn = func_arn(function)768    if arn not in arn_to_lambda:769        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')770    data = json.loads(request.data)771    alias = data.get('Name')772    if alias in arn_to_lambda.get(arn).aliases:773        return error_response('Alias already exists: %s' % arn + ':' + alias, 404,774                              error_type='ResourceConflictException')775    version = data.get('FunctionVersion')776    description = data.get('Description')777    return jsonify(do_update_alias(arn, alias, version, description))778@app.route('%s/functions/<function>/aliases/<name>' % PATH_ROOT, methods=['PUT'])779def update_alias(function, name):780    arn = func_arn(function)781    if arn not in arn_to_lambda:782        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')783    if name not in arn_to_lambda.get(arn).aliases:784        return error_response('Alias not found: %s' % arn + ':' + name, 404,785                              error_type='ResourceNotFoundException')786    current_alias = arn_to_lambda.get(arn).aliases.get(name)787    data = json.loads(request.data)788    version = data.get('FunctionVersion') or current_alias.get('FunctionVersion')789    description = data.get('Description') or current_alias.get('Description')790    return jsonify(do_update_alias(arn, name, version, description))791@app.route('%s/functions/<function>/aliases/<name>' % PATH_ROOT, methods=['GET'])792def get_alias(function, name):793    arn = func_arn(function)794    if arn not in arn_to_lambda:795        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')796    if name not in arn_to_lambda.get(arn).aliases:797        return error_response('Alias not found: %s' % arn + ':' + name, 404,798                              error_type='ResourceNotFoundException')799    return jsonify(arn_to_lambda.get(arn).aliases.get(name))800@app.route('%s/functions/<function>/aliases' % PATH_ROOT, methods=['GET'])801def list_aliases(function):802    arn = func_arn(function)803    if arn not in arn_to_lambda:804        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')...34072_lambda_api.py
Source:34072_lambda_api.py  
...195    return get_function_version(arn, str(last_version + 1))196def do_list_versions(arn):197    return sorted([get_function_version(arn, version) for version in198                   arn_to_lambda.get(arn).versions.keys()], key=lambda k: str(k.get('Version')))199def do_update_alias(arn, alias, version, description=None):200    new_alias = {201        'AliasArn': arn + ':' + alias,202        'FunctionVersion': version,203        'Name': alias,204        'Description': description or ''205    }206    arn_to_lambda.get(arn).aliases[alias] = new_alias207    return new_alias208def get_host_path_for_path_in_docker(path):209    return re.sub(r'^%s/(.*)$' % config.TMP_FOLDER,210                r'%s/\1' % config.HOST_TMP_FOLDER, path)211@cloudwatched('lambda')212def run_lambda(func, event, context, func_arn, suppress_output=False):213    if suppress_output:214        stdout_ = sys.stdout215        stderr_ = sys.stderr216        stream = StringIO()217        sys.stdout = stream218        sys.stderr = stream219    lambda_cwd = arn_to_lambda.get(func_arn).cwd220    result = None221    try:222        runtime = arn_to_lambda.get(func_arn).runtime223        handler = arn_to_lambda.get(func_arn).handler224        environment = arn_to_lambda.get(func_arn).envvars225        if use_docker():226            handler_args = '"%s"' % handler227            entrypoint = ''228            # prepare event body229            if not event:230                LOG.warning('Empty event body specified for invocation of Lambda "%s"' % func_arn)231                event = {}232            event_body = json.dumps(event)233            # if running a Java Lambda, set up classpath arguments234            if runtime == LAMBDA_RUNTIME_JAVA8:235                # copy executor jar into temp directory236                cp_r(LAMBDA_EXECUTOR_JAR, lambda_cwd)237                # TODO cleanup once we have custom Java Docker image238                taskdir = '/var/task'239                event_file = 'event_file.json'240                save_file(os.path.join(lambda_cwd, event_file), event_body)241                handler_args = ("bash -c 'cd %s; java -cp .:`ls *.jar | tr \"\\n\" \":\"` \"%s\" \"%s\" \"%s\"'" %242                    (taskdir, LAMBDA_EXECUTOR_CLASS, handler, event_file))243                entrypoint = ' --entrypoint ""'244            env_vars = ' '.join(['-e {}={}'.format(k, cmd_quote(v)) for (k, v) in environment.items()])245            if config.LAMBDA_REMOTE_DOCKER:246                cmd = (247                    'CONTAINER_ID="$(docker create'248                    '%s -e AWS_LAMBDA_EVENT_BODY="$AWS_LAMBDA_EVENT_BODY"'249                    ' -e HOSTNAME="$HOSTNAME"'250                    ' -e LOCALSTACK_HOSTNAME="$LOCALSTACK_HOSTNAME"'251                    ' %s'252                    ' "lambci/lambda:%s" %s'253                    ')";'254                    'docker cp "%s/." "$CONTAINER_ID:/var/task";'255                    'docker start -a "$CONTAINER_ID";'256                ) % (entrypoint, runtime, env_vars, handler_args, lambda_cwd)257            else:258                lambda_cwd_on_host = get_host_path_for_path_in_docker(lambda_cwd)259                cmd = (260                    'docker run'261                    '%s -v "%s":/var/task'262                    ' -e AWS_LAMBDA_EVENT_BODY="$AWS_LAMBDA_EVENT_BODY"'263                    ' -e HOSTNAME="$HOSTNAME"'264                    ' -e LOCALSTACK_HOSTNAME="$LOCALSTACK_HOSTNAME"'265                    ' %s'266                    ' --rm'267                    ' "lambci/lambda:%s" %s'268                ) % (entrypoint, lambda_cwd_on_host, env_vars, runtime, handler_args)269            print(cmd)270            event_body_escaped = event_body.replace("'", "\\'")271            docker_host = config.DOCKER_HOST_FROM_CONTAINER272            env_vars = {273                'AWS_LAMBDA_EVENT_BODY': event_body_escaped,274                'HOSTNAME': docker_host,275                'LOCALSTACK_HOSTNAME': docker_host276            }277            # lambci writes the Lambda result to stdout and logs to stderr, fetch it from there!278            result, log_output = run_lambda_executor(cmd, env_vars)279            LOG.debug('Lambda log output:\n%s' % log_output)280        else:281            # execute the Lambda function in a forked sub-process, sync result via queue282            queue = Queue()283            def do_execute():284                # now we're executing in the child process, safe to change CWD and ENV285                if lambda_cwd:286                    os.chdir(lambda_cwd)287                if environment:288                    os.environ.update(environment)289                result = func(event, context)290                queue.put(result)291            process = Process(target=do_execute)292            process.run()293            result = queue.get()294    except Exception as e:295        return error_response('Error executing Lambda function: %s %s' % (e, traceback.format_exc()))296    finally:297        if suppress_output:298            sys.stdout = stdout_299            sys.stderr = stderr_300    return result301def exec_lambda_code(script, handler_function='handler', lambda_cwd=None, lambda_env=None):302    if lambda_cwd or lambda_env:303        exec_mutex.acquire()304        if lambda_cwd:305            previous_cwd = os.getcwd()306            os.chdir(lambda_cwd)307            sys.path = [lambda_cwd] + sys.path308        if lambda_env:309            previous_env = dict(os.environ)310            os.environ.update(lambda_env)311    # generate lambda file name312    lambda_id = 'l_%s' % short_uid()313    lambda_file = LAMBDA_SCRIPT_PATTERN.replace('*', lambda_id)314    save_file(lambda_file, script)315    # delete temporary .py and .pyc files on exit316    TMP_FILES.append(lambda_file)317    TMP_FILES.append('%sc' % lambda_file)318    try:319        handler_module = imp.load_source(lambda_id, lambda_file)320        module_vars = handler_module.__dict__321    except Exception as e:322        LOG.error('Unable to exec: %s %s' % (script, traceback.format_exc()))323        raise e324    finally:325        if lambda_cwd or lambda_env:326            if lambda_cwd:327                os.chdir(previous_cwd)328                sys.path.pop(0)329            if lambda_env:330                os.environ = previous_env331            exec_mutex.release()332    return module_vars[handler_function]333def get_handler_file_from_name(handler_name, runtime=LAMBDA_RUNTIME_PYTHON27):334    # TODO: support Java Lambdas in the future335    file_ext = '.js' if runtime.startswith(LAMBDA_RUNTIME_NODEJS) else '.py'336    return '%s%s' % (handler_name.split('.')[0], file_ext)337def get_handler_function_from_name(handler_name, runtime=LAMBDA_RUNTIME_PYTHON27):338    # TODO: support Java Lambdas in the future339    return handler_name.split('.')[-1]340def error_response(msg, code=500, error_type='InternalFailure'):341    LOG.warning(msg)342    return aws_responses.flask_error_response(msg, code=code, error_type=error_type)343def run_lambda_executor(cmd, env_vars={}):344    process = run(cmd, async=True, stderr=subprocess.PIPE, outfile=subprocess.PIPE, env_vars=env_vars)345    return_code = process.wait()346    result = to_str(process.stdout.read())347    log_output = to_str(process.stderr.read())348    if return_code != 0:349        raise Exception('Lambda process returned error status code: %s. Output:\n%s' %350            (return_code, log_output))351    return result, log_output352def set_function_code(code, lambda_name):353    def generic_handler(event, context):354        raise Exception(('Unable to find executor for Lambda function "%s". ' +355            'Note that Node.js Lambdas currently require LAMBDA_EXECUTOR=docker') % lambda_name)356    lambda_handler = generic_handler357    lambda_cwd = None358    arn = func_arn(lambda_name)359    runtime = arn_to_lambda[arn].runtime360    handler_name = arn_to_lambda.get(arn).handler361    lambda_environment = arn_to_lambda.get(arn).envvars362    if not handler_name:363        handler_name = LAMBDA_DEFAULT_HANDLER364    handler_file = get_handler_file_from_name(handler_name, runtime=runtime)365    handler_function = get_handler_function_from_name(handler_name, runtime=runtime)366    if 'S3Bucket' in code:367        s3_client = aws_stack.connect_to_service('s3')368        bytes_io = BytesIO()369        try:370            s3_client.download_fileobj(code['S3Bucket'], code['S3Key'], bytes_io)371            zip_file_content = bytes_io.getvalue()372        except Exception as e:373            return error_response('Unable to fetch Lambda archive from S3: %s' % e, 404)374    elif 'ZipFile' in code:375        zip_file_content = code['ZipFile']376        zip_file_content = base64.b64decode(zip_file_content)377    else:378        return error_response('No valid Lambda archive specified.', 400)379    # save tmp file380    tmp_dir = '%s/zipfile.%s' % (config.TMP_FOLDER, short_uid())381    run('mkdir -p %s' % tmp_dir)382    tmp_file = '%s/%s' % (tmp_dir, LAMBDA_ZIP_FILE_NAME)383    save_file(tmp_file, zip_file_content)384    TMP_FILES.append(tmp_dir)385    lambda_cwd = tmp_dir386    # check if this is a ZIP file387    is_zip = is_zip_file(zip_file_content)388    if is_zip:389        unzip(tmp_file, tmp_dir)390        main_file = '%s/%s' % (tmp_dir, handler_file)391        if not os.path.isfile(main_file):392            # check if this is a zip file that contains a single JAR file393            jar_files = glob.glob('%s/*.jar' % tmp_dir)394            if len(jar_files) == 1:395                main_file = jar_files[0]396        if os.path.isfile(main_file):397            with open(main_file, 'rb') as file_obj:398                zip_file_content = file_obj.read()399        else:400            file_list = run('ls -la %s' % tmp_dir)401            LOG.debug('Lambda archive content:\n%s' % file_list)402            return error_response('Unable to find handler script in Lambda archive.', 400, error_type='ValidationError')403    # it could be a JAR file (regardless of whether wrapped in a ZIP file or not)404    is_jar = is_jar_archive(zip_file_content)405    if is_jar:406        def execute(event, context):407            event_file = EVENT_FILE_PATTERN.replace('*', short_uid())408            save_file(event_file, json.dumps(event))409            TMP_FILES.append(event_file)410            class_name = arn_to_lambda[arn].handler.split('::')[0]411            classpath = '%s:%s' % (LAMBDA_EXECUTOR_JAR, main_file)412            cmd = 'java -cp %s %s %s %s' % (classpath, LAMBDA_EXECUTOR_CLASS, class_name, event_file)413            result, log_output = run_lambda_executor(cmd)414            LOG.info('Lambda output: %s' % log_output.replace('\n', '\n> '))415            return result416        lambda_handler = execute417    elif runtime.startswith('python') and not use_docker():418        try:419            lambda_handler = exec_lambda_code(zip_file_content,420                handler_function=handler_function, lambda_cwd=lambda_cwd,421                lambda_env=lambda_environment)422        except Exception as e:423            raise Exception('Unable to get handler function from lambda code.', e)424    if not is_zip and not is_jar:425        raise Exception('Uploaded Lambda code is neither a ZIP nor JAR file.')426    add_function_mapping(lambda_name, lambda_handler, lambda_cwd)427    return {'FunctionName': lambda_name}428def do_list_functions():429    funcs = []430    for f_arn, func in iteritems(arn_to_lambda):431        func_name = f_arn.split(':function:')[-1]432        arn = func_arn(func_name)433        funcs.append({434            'Version': '$LATEST',435            'CodeSize': arn_to_lambda.get(arn).get_version('$LATEST').get('CodeSize'),436            'FunctionName': func_name,437            'FunctionArn': f_arn,438            'Handler': arn_to_lambda.get(arn).handler,439            'Runtime': arn_to_lambda.get(arn).runtime,440            'Timeout': LAMBDA_DEFAULT_TIMEOUT,441            # 'Description': ''442            # 'MemorySize': 192,443        })444    return funcs445@app.route('%s/functions' % PATH_ROOT, methods=['POST'])446def create_function():447    """ Create new function448        ---449        operationId: 'createFunction'450        parameters:451            - name: 'request'452              in: body453    """454    arn = 'n/a'455    try:456        data = json.loads(to_str(request.data))457        lambda_name = data['FunctionName']458        event_publisher.fire_event(event_publisher.EVENT_LAMBDA_CREATE_FUNC,459            payload={'n': event_publisher.get_hash(lambda_name)})460        arn = func_arn(lambda_name)461        if arn in arn_to_lambda:462            return error_response('Function already exist: %s' %463                lambda_name, 409, error_type='ResourceConflictException')464        arn_to_lambda[arn] = LambdaFunction(arn)465        arn_to_lambda[arn].versions = {'$LATEST': {'CodeSize': 50}}466        arn_to_lambda[arn].handler = data['Handler']467        arn_to_lambda[arn].runtime = data['Runtime']468        arn_to_lambda[arn].envvars = data.get('Environment', {}).get('Variables', {})469        result = set_function_code(data['Code'], lambda_name)470        if isinstance(result, Response):471            del arn_to_lambda[arn]472            return result473        result.update({474            'DeadLetterConfig': data.get('DeadLetterConfig'),475            'Description': data.get('Description'),476            'Environment': {'Error': {}, 'Variables': arn_to_lambda[arn].envvars},477            'FunctionArn': arn,478            'FunctionName': lambda_name,479            'Handler': arn_to_lambda[arn].handler,480            'MemorySize': data.get('MemorySize'),481            'Role': data.get('Role'),482            'Runtime': arn_to_lambda[arn].runtime,483            'Timeout': data.get('Timeout'),484            'TracingConfig': {},485            'VpcConfig': {'SecurityGroupIds': [None], 'SubnetIds': [None], 'VpcId': None}486        })487        return jsonify(result or {})488    except Exception as e:489        del arn_to_lambda[arn]490        return error_response('Unknown error: %s' % e)491@app.route('%s/functions/<function>' % PATH_ROOT, methods=['GET'])492def get_function(function):493    """ Get details for a single function494        ---495        operationId: 'getFunction'496        parameters:497            - name: 'request'498              in: body499            - name: 'function'500              in: path501    """502    funcs = do_list_functions()503    for func in funcs:504        if func['FunctionName'] == function:505            result = {506                'Configuration': func,507                'Code': {508                    'Location': '%s/code' % request.url509                }510            }511            return jsonify(result)512    result = {513        'ResponseMetadata': {514            'HTTPStatusCode': 404515        }516    }517    return make_response((jsonify(result), 404, {}))518@app.route('%s/functions/' % PATH_ROOT, methods=['GET'])519def list_functions():520    """ List functions521        ---522        operationId: 'listFunctions'523        parameters:524            - name: 'request'525              in: body526    """527    funcs = do_list_functions()528    result = {}529    result['Functions'] = funcs530    return jsonify(result)531@app.route('%s/functions/<function>' % PATH_ROOT, methods=['DELETE'])532def delete_function(function):533    """ Delete an existing function534        ---535        operationId: 'deleteFunction'536        parameters:537            - name: 'request'538              in: body539    """540    arn = func_arn(function)541    try:542        arn_to_lambda.pop(arn)543    except KeyError:544        return error_response('Function does not exist: %s' % function, 404, error_type='ResourceNotFoundException')545    event_publisher.fire_event(event_publisher.EVENT_LAMBDA_DELETE_FUNC,546        payload={'n': event_publisher.get_hash(function)})547    i = 0548    while i < len(event_source_mappings):549        mapping = event_source_mappings[i]550        if mapping['FunctionArn'] == arn:551            del event_source_mappings[i]552            i -= 1553        i += 1554    result = {}555    return jsonify(result)556@app.route('%s/functions/<function>/code' % PATH_ROOT, methods=['PUT'])557def update_function_code(function):558    """ Update the code of an existing function559        ---560        operationId: 'updateFunctionCode'561        parameters:562            - name: 'request'563              in: body564    """565    data = json.loads(to_str(request.data))566    result = set_function_code(data, function)567    return jsonify(result or {})568@app.route('%s/functions/<function>/code' % PATH_ROOT, methods=['GET'])569def get_function_code(function):570    """ Get the code of an existing function571        ---572        operationId: 'getFunctionCode'573        parameters:574    """575    arn = func_arn(function)576    lambda_cwd = arn_to_lambda[arn].cwd577    tmp_file = '%s/%s' % (lambda_cwd, LAMBDA_ZIP_FILE_NAME)578    return Response(load_file(tmp_file, mode='rb'),579            mimetype='application/zip',580            headers={'Content-Disposition': 'attachment; filename=lambda_archive.zip'})581@app.route('%s/functions/<function>/configuration' % PATH_ROOT, methods=['PUT'])582def update_function_configuration(function):583    """ Update the configuration of an existing function584        ---585        operationId: 'updateFunctionConfiguration'586        parameters:587            - name: 'request'588              in: body589    """590    data = json.loads(to_str(request.data))591    arn = func_arn(function)592    if data.get('Handler'):593        arn_to_lambda[arn].handler = data['Handler']594    if data.get('Runtime'):595        arn_to_lambda[arn].runtime = data['Runtime']596    if data.get('Environment'):597        arn_to_lambda[arn].envvars = data.get('Environment', {}).get('Variables', {})598    result = {}599    return jsonify(result)600@app.route('%s/functions/<function>/invocations' % PATH_ROOT, methods=['POST'])601def invoke_function(function):602    """ Invoke an existing function603        ---604        operationId: 'invokeFunction'605        parameters:606            - name: 'request'607              in: body608    """609    arn = func_arn(function)610    if arn not in arn_to_lambda:611        return error_response('Function does not exist: %s' % arn, 404, error_type='ResourceNotFoundException')612    qualifier = request.args['Qualifier'] if 'Qualifier' in request.args else '$LATEST'613    if not arn_to_lambda.get(arn).qualifier_exists(qualifier):614        return error_response('Function does not exist: {0}:{1}'.format(arn, qualifier), 404,615                              error_type='ResourceNotFoundException')616    lambda_function = arn_to_lambda.get(arn).function(qualifier)617    data = None618    if request.data:619        try:620            data = json.loads(to_str(request.data))621        except Exception:622            return error_response('The payload is not JSON', 415, error_type='UnsupportedMediaTypeException')623    result = run_lambda(lambda_function, func_arn=arn, event=data, context={})624    if isinstance(result, dict):625        return jsonify(result)626    if result:627        return result628    return make_response('', 200)629@app.route('%s/event-source-mappings/' % PATH_ROOT, methods=['GET'])630def list_event_source_mappings():631    """ List event source mappings632        ---633        operationId: 'listEventSourceMappings'634    """635    event_source_arn = request.args.get('EventSourceArn')636    function_name = request.args.get('FunctionName')637    mappings = event_source_mappings638    if event_source_arn:639        mappings = [m for m in mappings if event_source_arn == m.get('EventSourceArn')]640    if function_name:641        function_arn = func_arn(function_name)642        mappings = [m for m in mappings if function_arn == m.get('FunctionArn')]643    response = {644        'EventSourceMappings': mappings645    }646    return jsonify(response)647@app.route('%s/event-source-mappings/' % PATH_ROOT, methods=['POST'])648def create_event_source_mapping():649    """ Create new event source mapping650        ---651        operationId: 'createEventSourceMapping'652        parameters:653            - name: 'request'654              in: body655    """656    data = json.loads(to_str(request.data))657    mapping = add_event_source(data['FunctionName'], data['EventSourceArn'])658    return jsonify(mapping)659@app.route('%s/event-source-mappings/<mapping_uuid>' % PATH_ROOT, methods=['PUT'])660def update_event_source_mapping(mapping_uuid):661    """ Update an existing event source mapping662        ---663        operationId: 'updateEventSourceMapping'664        parameters:665            - name: 'request'666              in: body667    """668    data = json.loads(request.data)669    if not mapping_uuid:670        return jsonify({})671    function_name = data.get('FunctionName') or ''672    enabled = data.get('Enabled') or True673    batch_size = data.get('BatchSize') or 100674    mapping = update_event_source(mapping_uuid, function_name, enabled, batch_size)675    return jsonify(mapping)676@app.route('%s/event-source-mappings/<mapping_uuid>' % PATH_ROOT, methods=['DELETE'])677def delete_event_source_mapping(mapping_uuid):678    """ Delete an event source mapping679        ---680        operationId: 'deleteEventSourceMapping'681    """682    if not mapping_uuid:683        return jsonify({})684    mapping = delete_event_source(mapping_uuid)685    return jsonify(mapping)686@app.route('%s/functions/<function>/versions' % PATH_ROOT, methods=['POST'])687def publish_version(function):688    arn = func_arn(function)689    if arn not in arn_to_lambda:690        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')691    return jsonify(publish_new_function_version(arn))692@app.route('%s/functions/<function>/versions' % PATH_ROOT, methods=['GET'])693def list_versions(function):694    arn = func_arn(function)695    if arn not in arn_to_lambda:696        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')697    return jsonify({'Versions': do_list_versions(arn)})698@app.route('%s/functions/<function>/aliases' % PATH_ROOT, methods=['POST'])699def create_alias(function):700    arn = func_arn(function)701    if arn not in arn_to_lambda:702        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')703    data = json.loads(request.data)704    alias = data.get('Name')705    if alias in arn_to_lambda.get(arn).aliases:706        return error_response('Alias already exists: %s' % arn + ':' + alias, 404,707                              error_type='ResourceConflictException')708    version = data.get('FunctionVersion')709    description = data.get('Description')710    return jsonify(do_update_alias(arn, alias, version, description))711@app.route('%s/functions/<function>/aliases/<name>' % PATH_ROOT, methods=['PUT'])712def update_alias(function, name):713    arn = func_arn(function)714    if arn not in arn_to_lambda:715        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')716    if name not in arn_to_lambda.get(arn).aliases:717        return error_response('Alias not found: %s' % arn + ':' + name, 404,718                              error_type='ResourceNotFoundException')719    current_alias = arn_to_lambda.get(arn).aliases.get(name)720    data = json.loads(request.data)721    version = data.get('FunctionVersion') or current_alias.get('FunctionVersion')722    description = data.get('Description') or current_alias.get('Description')723    return jsonify(do_update_alias(arn, name, version, description))724@app.route('%s/functions/<function>/aliases' % PATH_ROOT, methods=['GET'])725def list_aliases(function):726    arn = func_arn(function)727    if arn not in arn_to_lambda:728        return error_response('Function not found: %s' % arn, 404, error_type='ResourceNotFoundException')729    return jsonify({'Aliases': sorted(arn_to_lambda.get(arn).aliases.values(),730                                      key=lambda x: x['Name'])})731def serve(port, quiet=True):...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
