How to use do_update_alias method in localstack

Best Python code snippet using localstack_python

lambda_api.py

Source:lambda_api.py Github

copy

Full Screen

...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')...

Full Screen

Full Screen

34072_lambda_api.py

Source:34072_lambda_api.py Github

copy

Full Screen

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

Full Screen

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run localstack automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful