def download_and_extract(archive_url, target_dir, retries=0, sleep=3, tmp_archive=None): mkdir(target_dir) tmp_archive = tmp_archive or new_tmp_file() if not os.path.exists(tmp_archive): # create temporary placeholder file, to avoid duplicate parallel downloads save_file(tmp_archive, '') for i in range(retries + 1): try: download(archive_url, tmp_archive) break except Exception: time.sleep(sleep) _, ext = os.path.splitext(tmp_archive) if ext == '.zip': unzip(tmp_archive, target_dir) elif ext == '.gz' or ext == '.bz2': untar(tmp_archive, target_dir) else: raise Exception('Unsupported archive format: %s' % ext)
def download_and_extract(archive_url, target_dir, retries=0, sleep=3, tmp_archive=None): mkdir(target_dir) if tmp_archive: _, ext = os.path.splitext(tmp_archive) else: _, ext = os.path.splitext(archive_url) tmp_archive = tmp_archive or new_tmp_file() if not os.path.exists(tmp_archive) or os.path.getsize(tmp_archive) <= 0: # create temporary placeholder file, to avoid duplicate parallel downloads save_file(tmp_archive, "") for i in range(retries + 1): try: download(archive_url, tmp_archive) break except Exception: time.sleep(sleep) if ext == ".zip": unzip(tmp_archive, target_dir) elif ext == ".gz" or ext == ".bz2": untar(tmp_archive, target_dir) else: raise Exception("Unsupported archive format: %s" % ext)
def test_java_runtime_with_lib(self): java_jar_with_lib = load_file(TEST_LAMBDA_JAVA_WITH_LIB, mode='rb') # create ZIP file from JAR file jar_dir = new_tmp_dir() zip_dir = new_tmp_dir() unzip(TEST_LAMBDA_JAVA_WITH_LIB, jar_dir) shutil.move(os.path.join(jar_dir, 'lib'), os.path.join(zip_dir, 'lib')) jar_without_libs_file = testutil.create_zip_file(jar_dir) shutil.copy(jar_without_libs_file, os.path.join(zip_dir, 'lib', 'lambda.jar')) java_zip_with_lib = testutil.create_zip_file(zip_dir, get_content=True) for archive in [java_jar_with_lib, java_zip_with_lib]: lambda_name = 'test-%s' % short_uid() testutil.create_lambda_function( func_name=lambda_name, zip_file=archive, runtime=LAMBDA_RUNTIME_JAVA8, handler='cloud.localstack.sample.LambdaHandlerWithLib') result = self.lambda_client.invoke(FunctionName=lambda_name, Payload=b'{"echo":"echo"}') result_data = result['Payload'].read() self.assertEqual(result['StatusCode'], 200) self.assertIn('echo', to_str(result_data)) # clean up testutil.delete_lambda_function(lambda_name)
def get_lambda_code(func_name, retries=1, cache_time=None, env=None, region=None): if MOCK_OBJ: return "" env = aws_stack.get_environment(env) if cache_time is None and not aws_stack.is_local_env(env): cache_time = AWS_LAMBDA_CODE_CACHE_TIMEOUT lambda_client = _connect("lambda", env=env, region=region) out = lambda_client.get_function(FunctionName=func_name) loc = out["Code"]["Location"] hash = md5(loc) folder = TMP_DOWNLOAD_FILE_PATTERN.replace("*", hash) filename = "archive.zip" archive = "%s/%s" % (folder, filename) try: mkdir(folder) if not os.path.isfile(archive): download(loc, archive, verify_ssl=False) if len(os.listdir(folder)) <= 1: zip_path = os.path.join(folder, filename) unzip(zip_path, folder) except Exception as e: print("WARN: %s" % e) rm_rf(archive) if retries > 0: return get_lambda_code(func_name, retries=retries - 1, cache_time=1, env=env) else: print("WARNING: Unable to retrieve lambda code: %s" % e) # traverse subdirectories and get script sources result = {} for root, subdirs, files in os.walk(folder): for file in files: prefix = root.split(folder)[-1] key = "%s/%s" % (prefix, file) if re.match(r".+\.py$", key) or re.match(r".+\.js$", key): codefile = "%s/%s" % (root, file) result[key] = load_file(codefile) # cleanup cache clean_cache( file_pattern=TMP_DOWNLOAD_FILE_PATTERN, last_clean_time=last_cache_cleanup_time, max_age=TMP_DOWNLOAD_CACHE_MAX_AGE, ) # TODO: delete only if cache_time is over rm_rf(folder) return result
def download_and_extract(): if not os.path.exists(tmp_archive): download(archive_url, tmp_archive) _, ext = os.path.splitext(tmp_archive) if ext == '.zip': unzip(tmp_archive, target_dir) elif ext == '.gz' or ext == '.bz2': untar(tmp_archive, target_dir) else: raise Exception('Unsupported archive format: %s' % ext)
def download_and_extract(): if not os.path.exists(tmp_archive): # create temporary placeholder file, to avoid duplicate parallel downloads save_file(tmp_archive, '') download(archive_url, tmp_archive) _, ext = os.path.splitext(tmp_archive) if ext == '.zip': unzip(tmp_archive, target_dir) elif ext == '.gz' or ext == '.bz2': untar(tmp_archive, target_dir) else: raise Exception('Unsupported archive format: %s' % ext)
def get_lambda_code(func_name, retries=1, cache_time=None, env=None): if MOCK_OBJ: return '' env = aws_stack.get_environment(env) if cache_time is None and not aws_stack.is_local_env(env): cache_time = AWS_LAMBDA_CODE_CACHE_TIMEOUT out = cmd_lambda('get-function --function-name %s' % func_name, env, cache_time) out = json.loads(out) loc = out['Code']['Location'] hash = md5(loc) folder = TMP_DOWNLOAD_FILE_PATTERN.replace('*', hash) filename = 'archive.zip' archive = '%s/%s' % (folder, filename) try: mkdir(folder) if not os.path.isfile(archive): download(loc, archive, verify_ssl=False) if len(os.listdir(folder)) <= 1: zip_path = os.path.join(folder, filename) unzip(zip_path, folder) except Exception as e: print('WARN: %s' % e) rm_rf(archive) if retries > 0: return get_lambda_code(func_name, retries=retries - 1, cache_time=1, env=env) else: print('WARNING: Unable to retrieve lambda code: %s' % e) # traverse subdirectories and get script sources result = {} for root, subdirs, files in os.walk(folder): for file in files: prefix = root.split(folder)[-1] key = '%s/%s' % (prefix, file) if re.match(r'.+\.py$', key) or re.match(r'.+\.js$', key): codefile = '%s/%s' % (root, file) result[key] = load_file(codefile) # cleanup cache clean_cache(file_pattern=TMP_DOWNLOAD_FILE_PATTERN, last_clean_time=last_cache_cleanup_time, max_age=TMP_DOWNLOAD_CACHE_MAX_AGE) # TODO: delete only if cache_time is over rm_rf(folder) return result
def get_lambda_code(func_name, retries=1, cache_time=None, env=None): if MOCK_OBJ: return '' env = aws_stack.get_environment(env) if cache_time is None and env.region != REGION_LOCAL: cache_time = AWS_LAMBDA_CODE_CACHE_TIMEOUT out = cmd_lambda('get-function --function-name %s' % func_name, env, cache_time) out = json.loads(out) loc = out['Code']['Location'] hash = md5(loc) folder = TMP_DOWNLOAD_FILE_PATTERN.replace('*', hash) filename = 'archive.zip' archive = '%s/%s' % (folder, filename) try: mkdir(folder) if not os.path.isfile(archive): download(loc, archive, verify_ssl=False) if len(os.listdir(folder)) <= 1: zip_path = os.path.join(folder, filename) unzip(zip_path, folder) except Exception as e: print('WARN: %s' % e) rm_rf(archive) if retries > 0: return get_lambda_code(func_name, retries=retries - 1, cache_time=1, env=env) else: print('WARNING: Unable to retrieve lambda code: %s' % e) # traverse subdirectories and get script sources result = {} for root, subdirs, files in os.walk(folder): for file in files: prefix = root.split(folder)[-1] key = '%s/%s' % (prefix, file) if re.match(r'.+\.py$', key) or re.match(r'.+\.js$', key): codefile = '%s/%s' % (root, file) result[key] = load_file(codefile) # cleanup cache clean_cache(file_pattern=TMP_DOWNLOAD_FILE_PATTERN, last_clean_time=last_cache_cleanup_time, max_age=TMP_DOWNLOAD_CACHE_MAX_AGE) # TODO: delete only if cache_time is over rm_rf(folder) return result
def set_function_code(code, lambda_name): def generic_handler(event, context): raise Exception(('Unable to find executor for Lambda function "%s". ' + 'Note that Node.js and .NET Core Lambdas currently require LAMBDA_EXECUTOR=docker') % lambda_name) lambda_cwd = None arn = func_arn(lambda_name) lambda_details = arn_to_lambda[arn] runtime = lambda_details.runtime handler_name = lambda_details.handler lambda_environment = lambda_details.envvars if not handler_name: handler_name = LAMBDA_DEFAULT_HANDLER # Stop/remove any containers that this arn uses. LAMBDA_EXECUTOR.cleanup(arn) zip_file_content = None is_local_mount = code.get('S3Bucket') == BUCKET_MARKER_LOCAL if is_local_mount: # Mount or use a local folder lambda executors can reference # WARNING: this means we're pointing lambda_cwd to a local path in the user's # file system! We must ensure that there is no data loss (i.e., we must *not* add # this folder to TMP_FILES or similar). lambda_cwd = code['S3Key'] else: # Save the zip file to a temporary file that the lambda executors can reference zip_file_content = get_zip_bytes(code) if isinstance(zip_file_content, Response): return zip_file_content tmp_dir = '%s/zipfile.%s' % (config.TMP_FOLDER, short_uid()) mkdir(tmp_dir) tmp_file = '%s/%s' % (tmp_dir, LAMBDA_ZIP_FILE_NAME) save_file(tmp_file, zip_file_content) TMP_FILES.append(tmp_dir) lambda_cwd = tmp_dir # Set the appropriate lambda handler. lambda_handler = generic_handler if runtime == LAMBDA_RUNTIME_JAVA8: # The Lambda executors for Docker subclass LambdaExecutorContainers, # which runs Lambda in Docker by passing all *.jar files in the function # working directory as part of the classpath. Because of this, we need to # save the zip_file_content as a .jar here. if is_jar_archive(zip_file_content): jar_tmp_file = '{working_dir}/{file_name}'.format( working_dir=tmp_dir, file_name=LAMBDA_JAR_FILE_NAME) save_file(jar_tmp_file, zip_file_content) lambda_handler = get_java_handler(zip_file_content, handler_name, tmp_file) if isinstance(lambda_handler, Response): return lambda_handler else: handler_file = get_handler_file_from_name(handler_name, runtime=runtime) handler_function = get_handler_function_from_name(handler_name, runtime=runtime) if not is_local_mount: # Lambda code must be uploaded in Zip format if not is_zip_file(zip_file_content): raise Exception( 'Uploaded Lambda code for runtime ({}) is not in Zip format'.format(runtime)) unzip(tmp_file, lambda_cwd) main_file = '%s/%s' % (lambda_cwd, handler_file) if os.path.isfile(main_file): # make sure the file is actually readable, then read contents ensure_readable(main_file) with open(main_file, 'rb') as file_obj: zip_file_content = file_obj.read() else: # Raise an error if (1) this is not a local mount lambda, or (2) we're # running Lambdas locally (not in Docker), or (3) we're using remote Docker. # -> We do *not* want to raise an error if we're using local mount in non-remote Docker if not is_local_mount or not use_docker() or config.LAMBDA_REMOTE_DOCKER: file_list = run('ls -la %s' % lambda_cwd) LOG.debug('Lambda archive content:\n%s' % file_list) return error_response( 'Unable to find handler script in Lambda archive.', 400, error_type='ValidationError') if runtime.startswith('python') and not use_docker(): try: lambda_handler = exec_lambda_code( zip_file_content, handler_function=handler_function, lambda_cwd=lambda_cwd, lambda_env=lambda_environment) except Exception as e: raise Exception('Unable to get handler function from lambda code.', e) add_function_mapping(lambda_name, lambda_handler, lambda_cwd) return {'FunctionName': lambda_name}
def set_function_code(code, lambda_name): def generic_handler(event, context): raise Exception(( 'Unable to find executor for Lambda function "%s". ' + 'Note that Node.js and .NET Core Lambdas currently require LAMBDA_EXECUTOR=docker' ) % lambda_name) lambda_cwd = None arn = func_arn(lambda_name) runtime = arn_to_lambda[arn].runtime handler_name = arn_to_lambda.get(arn).handler lambda_environment = arn_to_lambda.get(arn).envvars if not handler_name: handler_name = LAMBDA_DEFAULT_HANDLER # Stop/remove any containers that this arn uses. LAMBDA_EXECUTOR.cleanup(arn) # Save the zip file to a temporary file that the lambda executors can reference. zip_file_content = get_zip_bytes(code) if isinstance(zip_file_content, Response): return zip_file_content tmp_dir = '%s/zipfile.%s' % (config.TMP_FOLDER, short_uid()) mkdir(tmp_dir) tmp_file = '%s/%s' % (tmp_dir, LAMBDA_ZIP_FILE_NAME) save_file(tmp_file, zip_file_content) TMP_FILES.append(tmp_dir) lambda_cwd = tmp_dir # Set the appropriate lambda handler. lambda_handler = generic_handler if runtime == LAMBDA_RUNTIME_JAVA8: # The Lambda executors for Docker subclass LambdaExecutorContainers, # which runs Lambda in Docker by passing all *.jar files in the function # working directory as part of the classpath. Because of this, we need to # save the zip_file_content as a .jar here. if is_jar_archive(zip_file_content): jar_tmp_file = '{working_dir}/{file_name}'.format( working_dir=tmp_dir, file_name=LAMBDA_JAR_FILE_NAME) save_file(jar_tmp_file, zip_file_content) lambda_handler = get_java_handler(zip_file_content, handler_name, tmp_file) if isinstance(lambda_handler, Response): return lambda_handler else: handler_file = get_handler_file_from_name(handler_name, runtime=runtime) handler_function = get_handler_function_from_name(handler_name, runtime=runtime) # Lambda code must be uploaded in the Zip format. if not is_zip_file(zip_file_content): raise Exception( 'Uploaded Lambda code for runtime ({}) is not in Zip format'. format(runtime)) unzip(tmp_file, tmp_dir) main_file = '%s/%s' % (tmp_dir, handler_file) if os.path.isfile(main_file): # make sure the file is actually readable, then read contents ensure_readable(main_file) with open(main_file, 'rb') as file_obj: zip_file_content = file_obj.read() else: file_list = run('ls -la %s' % tmp_dir) LOG.debug('Lambda archive content:\n%s' % file_list) return error_response( 'Unable to find handler script in Lambda archive.', 400, error_type='ValidationError') if runtime.startswith('python') and not use_docker(): try: lambda_handler = exec_lambda_code( zip_file_content, handler_function=handler_function, lambda_cwd=lambda_cwd, lambda_env=lambda_environment) except Exception as e: raise Exception( 'Unable to get handler function from lambda code.', e) add_function_mapping(lambda_name, lambda_handler, lambda_cwd) return {'FunctionName': lambda_name}
def set_function_code(code, lambda_name): def generic_handler(event, context): raise Exception(( 'Unable to find executor for Lambda function "%s". ' + 'Note that Node.js Lambdas currently require LAMBDA_EXECUTOR=docker' ) % lambda_name) lambda_handler = generic_handler lambda_cwd = None arn = func_arn(lambda_name) runtime = arn_to_lambda[arn].runtime handler_name = arn_to_lambda.get(arn).handler lambda_environment = arn_to_lambda.get(arn).envvars if not handler_name: handler_name = LAMBDA_DEFAULT_HANDLER handler_file = get_handler_file_from_name(handler_name, runtime=runtime) handler_function = get_handler_function_from_name(handler_name, runtime=runtime) # Stop/remove any containers that this arn uses. LAMBDA_EXECUTOR.cleanup(arn) if 'S3Bucket' in code: s3_client = aws_stack.connect_to_service('s3') bytes_io = BytesIO() try: s3_client.download_fileobj(code['S3Bucket'], code['S3Key'], bytes_io) zip_file_content = bytes_io.getvalue() except Exception as e: return error_response( 'Unable to fetch Lambda archive from S3: %s' % e, 404) elif 'ZipFile' in code: zip_file_content = code['ZipFile'] zip_file_content = base64.b64decode(zip_file_content) else: return error_response('No valid Lambda archive specified.', 400) # save tmp file tmp_dir = '%s/zipfile.%s' % (config.TMP_FOLDER, short_uid()) run('mkdir -p %s' % tmp_dir) tmp_file = '%s/%s' % (tmp_dir, LAMBDA_ZIP_FILE_NAME) save_file(tmp_file, zip_file_content) TMP_FILES.append(tmp_dir) lambda_cwd = tmp_dir # check if this is a ZIP file is_zip = is_zip_file(zip_file_content) if is_zip: unzip(tmp_file, tmp_dir) main_file = '%s/%s' % (tmp_dir, handler_file) if not os.path.isfile(main_file): # check if this is a zip file that contains a single JAR file jar_files = glob.glob('%s/*.jar' % tmp_dir) if len(jar_files) == 1: main_file = jar_files[0] if os.path.isfile(main_file): # make sure the file is actually readable, then read contents ensure_readable(main_file) with open(main_file, 'rb') as file_obj: zip_file_content = file_obj.read() else: file_list = run('ls -la %s' % tmp_dir) LOG.debug('Lambda archive content:\n%s' % file_list) return error_response( 'Unable to find handler script in Lambda archive.', 400, error_type='ValidationError') # it could be a JAR file (regardless of whether wrapped in a ZIP file or not) is_jar = is_jar_archive(zip_file_content) if is_jar: def execute(event, context): result, log_output = lambda_executors.EXECUTOR_LOCAL.execute_java_lambda( event, context, handler=arn_to_lambda[arn].handler, main_file=main_file) return result lambda_handler = execute elif runtime.startswith('python') and not use_docker(): try: lambda_handler = exec_lambda_code( zip_file_content, handler_function=handler_function, lambda_cwd=lambda_cwd, lambda_env=lambda_environment) except Exception as e: raise Exception('Unable to get handler function from lambda code.', e) if not is_zip and not is_jar: raise Exception('Uploaded Lambda code is neither a ZIP nor JAR file.') add_function_mapping(lambda_name, lambda_handler, lambda_cwd) return {'FunctionName': lambda_name}
def download_and_extract(): if not os.path.exists(tmp_archive): download(archive_url, tmp_archive) unzip(tmp_archive, target_dir)
def set_function_code(code, lambda_name, lambda_cwd=None): def generic_handler(event, context): raise ClientError(('Unable to find executor for Lambda function "%s". Note that ' + 'Node.js, Golang, and .Net Core Lambdas currently require LAMBDA_EXECUTOR=docker') % lambda_name) arn = func_arn(lambda_name) lambda_details = arn_to_lambda[arn] runtime = lambda_details.runtime lambda_environment = lambda_details.envvars handler_name = lambda_details.handler or LAMBDA_DEFAULT_HANDLER code_passed = code code = code or lambda_details.code is_local_mount = code.get('S3Bucket') == BUCKET_MARKER_LOCAL zip_file_content = None if code_passed: lambda_cwd = lambda_cwd or set_archive_code(code_passed, lambda_name) if not is_local_mount: # Save the zip file to a temporary file that the lambda executors can reference zip_file_content = get_zip_bytes(code_passed) else: lambda_cwd = lambda_cwd or lambda_details.cwd # get local lambda working directory tmp_file = '%s/%s' % (lambda_cwd, LAMBDA_ZIP_FILE_NAME) if not zip_file_content: zip_file_content = load_file(tmp_file, mode='rb') # Set the appropriate lambda handler. lambda_handler = generic_handler if runtime == LAMBDA_RUNTIME_JAVA8: # The Lambda executors for Docker subclass LambdaExecutorContainers, # which runs Lambda in Docker by passing all *.jar files in the function # working directory as part of the classpath. Because of this, we need to # save the zip_file_content as a .jar here. lambda_handler, zip_file_content = get_java_handler(zip_file_content, handler_name, tmp_file) if is_jar_archive(zip_file_content): jar_tmp_file = '{working_dir}/{file_name}'.format( working_dir=lambda_cwd, file_name=LAMBDA_JAR_FILE_NAME) save_file(jar_tmp_file, zip_file_content) else: handler_file = get_handler_file_from_name(handler_name, runtime=runtime) handler_function = get_handler_function_from_name(handler_name, runtime=runtime) if not is_local_mount: # Lambda code must be uploaded in Zip format if not is_zip_file(zip_file_content): raise ClientError( 'Uploaded Lambda code for runtime ({}) is not in Zip format'.format(runtime)) unzip(tmp_file, lambda_cwd) main_file = '%s/%s' % (lambda_cwd, handler_file) if not os.path.exists(main_file): # Raise an error if (1) this is not a local mount lambda, or (2) we're # running Lambdas locally (not in Docker), or (3) we're using remote Docker. # -> We do *not* want to raise an error if we're using local mount in non-remote Docker if not is_local_mount or not use_docker() or config.LAMBDA_REMOTE_DOCKER: file_list = run('cd "%s"; du -d 3 .' % lambda_cwd) config_debug = ('Config for local mount, docker, remote: "%s", "%s", "%s"' % (is_local_mount, use_docker(), config.LAMBDA_REMOTE_DOCKER)) LOG.debug('Lambda archive content:\n%s' % file_list) raise ClientError(error_response( 'Unable to find handler script in Lambda archive. %s' % config_debug, 400, error_type='ValidationError')) if runtime.startswith('python') and not use_docker(): try: # make sure the file is actually readable, then read contents ensure_readable(main_file) zip_file_content = load_file(main_file, mode='rb') # extract handler lambda_handler = exec_lambda_code( zip_file_content, handler_function=handler_function, lambda_cwd=lambda_cwd, lambda_env=lambda_environment) except Exception as e: raise ClientError('Unable to get handler function from lambda code.', e) add_function_mapping(lambda_name, lambda_handler, lambda_cwd) return {'FunctionName': lambda_name}
def set_function_code(code, lambda_name): def generic_handler(event, context): raise Exception(( 'Unable to find executor for Lambda function "%s". ' + 'Note that Node.js Lambdas currently require LAMBDA_EXECUTOR=docker' ) % lambda_name) lambda_handler = generic_handler lambda_cwd = None arn = func_arn(lambda_name) runtime = arn_to_lambda[arn].runtime handler_name = arn_to_lambda.get(arn).handler lambda_environment = arn_to_lambda.get(arn).envvars if not handler_name: handler_name = LAMBDA_DEFAULT_HANDLER handler_file = get_handler_file_from_name(handler_name, runtime=runtime) handler_function = get_handler_function_from_name(handler_name, runtime=runtime) if 'S3Bucket' in code: s3_client = aws_stack.connect_to_service('s3') bytes_io = BytesIO() try: s3_client.download_fileobj(code['S3Bucket'], code['S3Key'], bytes_io) zip_file_content = bytes_io.getvalue() except Exception as e: return error_response( 'Unable to fetch Lambda archive from S3: %s' % e, 404) elif 'ZipFile' in code: zip_file_content = code['ZipFile'] zip_file_content = base64.b64decode(zip_file_content) else: return error_response('No valid Lambda archive specified.', 400) # save tmp file tmp_dir = '%s/zipfile.%s' % (config.TMP_FOLDER, short_uid()) run('mkdir -p %s' % tmp_dir) tmp_file = '%s/%s' % (tmp_dir, LAMBDA_ZIP_FILE_NAME) save_file(tmp_file, zip_file_content) TMP_FILES.append(tmp_dir) lambda_cwd = tmp_dir # check if this is a ZIP file is_zip = is_zip_file(zip_file_content) if is_zip: unzip(tmp_file, tmp_dir) main_file = '%s/%s' % (tmp_dir, handler_file) if not os.path.isfile(main_file): # check if this is a zip file that contains a single JAR file jar_files = glob.glob('%s/*.jar' % tmp_dir) if len(jar_files) == 1: main_file = jar_files[0] if os.path.isfile(main_file): with open(main_file, 'rb') as file_obj: zip_file_content = file_obj.read() else: file_list = run('ls -la %s' % tmp_dir) LOG.debug('Lambda archive content:\n%s' % file_list) return error_response( 'Unable to find handler script in Lambda archive.', 400, error_type='ValidationError') # it could be a JAR file (regardless of whether wrapped in a ZIP file or not) is_jar = is_jar_archive(zip_file_content) if is_jar: def execute(event, context): event_file = EVENT_FILE_PATTERN.replace('*', short_uid()) save_file(event_file, json.dumps(event)) TMP_FILES.append(event_file) class_name = arn_to_lambda[arn].handler.split('::')[0] classpath = '%s:%s' % (LAMBDA_EXECUTOR_JAR, main_file) cmd = 'java -cp %s %s %s %s' % (classpath, LAMBDA_EXECUTOR_CLASS, class_name, event_file) async = False # flip async flag depending on origin if 'Records' in event: # TODO: add more event supporting async lambda execution if 'Sns' in event['Records'][0]: async = True result, log_output = run_lambda_executor(cmd, async=async) LOG.info('Lambda output: %s' % log_output.replace('\n', '\n> ')) return result
def download_and_extract(): if not os.path.exists(tmp_archive): download(archive_url, tmp_archive) unzip(tmp_archive, target_dir)
def set_function_code(code, lambda_name): def generic_handler(event, context): raise Exception(('Unable to find executor for Lambda function "%s". ' + 'Note that Node.js and .NET Core Lambdas currently require LAMBDA_EXECUTOR=docker') % lambda_name) lambda_handler = generic_handler lambda_cwd = None arn = func_arn(lambda_name) runtime = arn_to_lambda[arn].runtime handler_name = arn_to_lambda.get(arn).handler lambda_environment = arn_to_lambda.get(arn).envvars if not handler_name: handler_name = LAMBDA_DEFAULT_HANDLER handler_file = get_handler_file_from_name(handler_name, runtime=runtime) handler_function = get_handler_function_from_name(handler_name, runtime=runtime) # Stop/remove any containers that this arn uses. LAMBDA_EXECUTOR.cleanup(arn) if 'S3Bucket' in code: s3_client = aws_stack.connect_to_service('s3') bytes_io = BytesIO() try: s3_client.download_fileobj(code['S3Bucket'], code['S3Key'], bytes_io) zip_file_content = bytes_io.getvalue() except Exception as e: return error_response('Unable to fetch Lambda archive from S3: %s' % e, 404) elif 'ZipFile' in code: zip_file_content = code['ZipFile'] zip_file_content = base64.b64decode(zip_file_content) else: return error_response('No valid Lambda archive specified.', 400) # save tmp file tmp_dir = '%s/zipfile.%s' % (config.TMP_FOLDER, short_uid()) mkdir(tmp_dir) tmp_file = '%s/%s' % (tmp_dir, LAMBDA_ZIP_FILE_NAME) save_file(tmp_file, zip_file_content) TMP_FILES.append(tmp_dir) lambda_cwd = tmp_dir # check if this is a ZIP file is_zip = is_zip_file(zip_file_content) if is_zip: unzip(tmp_file, tmp_dir) main_file = '%s/%s' % (tmp_dir, handler_file) if not os.path.isfile(main_file): # check if this is a zip file that contains a single JAR file jar_files = glob.glob('%s/*.jar' % tmp_dir) if len(jar_files) == 1: main_file = jar_files[0] if os.path.isfile(main_file): # make sure the file is actually readable, then read contents ensure_readable(main_file) with open(main_file, 'rb') as file_obj: zip_file_content = file_obj.read() else: file_list = run('ls -la %s' % tmp_dir) LOG.debug('Lambda archive content:\n%s' % file_list) return error_response('Unable to find handler script in Lambda archive.', 400, error_type='ValidationError') # it could be a JAR file (regardless of whether wrapped in a ZIP file or not) is_jar = is_jar_archive(zip_file_content) if is_jar: def execute(event, context): result, log_output = lambda_executors.EXECUTOR_LOCAL.execute_java_lambda(event, context, handler=arn_to_lambda[arn].handler, main_file=main_file) return result lambda_handler = execute elif runtime.startswith('python') and not use_docker(): try: lambda_handler = exec_lambda_code(zip_file_content, handler_function=handler_function, lambda_cwd=lambda_cwd, lambda_env=lambda_environment) except Exception as e: raise Exception('Unable to get handler function from lambda code.', e) if not is_zip and not is_jar: raise Exception('Uploaded Lambda code is neither a ZIP nor JAR file.') add_function_mapping(lambda_name, lambda_handler, lambda_cwd) return {'FunctionName': lambda_name}