Source code for runhouse.resources.functions.aws_lambda_factory

from pathlib import Path
from typing import Callable, Dict, List, Optional, Union

from runhouse.resources.envs import Env
from runhouse.resources.functions.aws_lambda import LambdaFunction
from runhouse.resources.functions.function import Function
from runhouse.utils import extract_module_path


CRED_PATH = f"{Path.home()}/.aws/credentials"
DEFAULT_PY_VERSION = "python3.9"
LOG_GROUP_PREFIX = "/aws/lambda/"


[docs]def aws_lambda_fn( fn: Optional[Callable] = None, name: Optional[str] = None, env: Optional[Union[Dict, List[str], Env]] = None, runtime: Optional[str] = None, timeout: Optional[int] = None, memory_size: Optional[int] = None, tmp_size: Optional[int] = None, retention_time: Optional[int] = None, load_from_den: bool = True, dryrun: bool = False, ): """Builds an instance of :class:`LambdaFunction`. Args: fn (Optional[Callable]): The Lambda function to be executed. name (Optional[str]): Name of the Lambda Function to create or retrieve. This can be either from a local config or from the RNS. env (Optional[Dict or List[str] or Env]): Specifies the requirements that will be installed, and the environment vars that should be attached to the Lambda. Accepts three possible types:\n 1. A dict which should contain the following keys:\n a. reqs: a list of the python libraries, to be installed by the Lambda, or just a ``requirements.txt`` string.\n b. env_vars: dictionary containing the env_vars that will be a part of the lambda configuration.\n 2. A list of strings, containing all the required python packages.\n 3. An instance of Runhouse Env class.\n By default, ``runhouse`` package will be installed, and env_vars will include ``{HOME: /tmp/home}``. runtime: (Optional[str]): The coding language of the function. Should be one of the following: python3.7, python3.8, python3.9, python3.10, python3.11. (Default: ``python3.9``) timeout: Optional[int]: The maximum amount of time (in seconds) during which the Lambda will run in AWS without timing-out. (Default: ``900``, Min: ``3``, Max: ``900``) memory_size: Optional[int], The amount of memory (in MB) to be allocated to the Lambda. (Default: ``10240``, Min: ``128``, Max: ``10240``) tmp_size: Optional[int], This size of the /tmp folder in the aws lambda file system. (Default: ``10240``, Min: ``512``, Max: ``10240``). retention_time: Optional[int] The time (in days) the Lambda execution logs will be saved in AWS cloudwatch. After that, they will be deleted. (Default: ``30`` days) load_from_den (bool): Whether to try loading the Function resource from Den. (Default: ``True``) dryrun (bool): Whether to create the Function if it doesn't exist, or load the Function object as a dryrun. (Default: ``False``). Returns: LambdaFunction: The resulting AWS Lambda Function object. .. note:: When creating a Lambda function for the first time (not reloading it), a callable function is a mandatory argument. Examples: >>> import runhouse as rh >>> # Pass in a callable function when creating a Lambda >>> def multiply(a, b): >>> return a * b >>> multiply_lambda = rh.aws_lambda_fn(fn=multiply, name="lambdas_mult_func") >>> mult_res = multiply_lambda(4, 5) # returns 20. >>> # Load function from above >>> reloaded_function = rh.aws_lambda_fn(name="lambdas_mult_func") >>> reloaded_function_res = reloaded_function(3, 4) # returns 12. """ # TODO: [SB] in the next phase, maybe add the option to create func from git. if name and not any([runtime, fn]): # Try reloading existing function return LambdaFunction.from_name( name=name, load_from_den=load_from_den, dryrun=dryrun ) if not fn or not isinstance(fn, Callable): raise RuntimeError( "Please provide a callable function OR use from_handler_file method" + "in order to create a Lambda function." ) # Env setup. env = LambdaFunction._validate_and_create_env(env) # extract function pointers, path to code and arg names from callable function. handler_function_name = fn.__name__ fn_pointers = Function._extract_pointers(fn) ( local_path_containing_function, should_add, ) = Function._get_local_path_containing_module( fn_pointers[0], reqs=[] if env is None else env.reqs ) if should_add and env is not None: env.reqs = [str(local_path_containing_function)] + env.reqs paths_to_code = [extract_module_path(fn)] if name is None: name = fn.__name__ # ------- arguments validation ------- ( paths_to_code, env, runtime, timeout, memory_size, tmp_size, retention_time, ) = LambdaFunction.arguments_validation( paths_to_code, env, runtime, timeout, memory_size, tmp_size, retention_time ) new_function = LambdaFunction( fn_pointers=fn_pointers, paths_to_code=paths_to_code, handler_function_name=handler_function_name, runtime=runtime, name=name, env=env, dryrun=dryrun, timeout=timeout, memory_size=memory_size, tmp_size=tmp_size, retention_time=retention_time, ) if dryrun: return new_function return new_function.deploy()