示例#1
0
def test_create_function(make_stubber, make_unique_name, error_code):
    lambda_client = boto3.client('lambda')
    lambda_stubber = make_stubber(lambda_client)
    wrapper = LambdaWrapper(lambda_client, None)
    func_name = make_unique_name('func-')
    handler_name = make_unique_name('handler-')
    iam_role = unittest.mock.MagicMock(arn='arn:aws:iam:::role/test-role')
    test_package = 'test-package'
    func_arn = f'arn:aws:lambda:::function/{func_name}'

    lambda_stubber.stub_create_function(func_name,
                                        func_arn,
                                        iam_role.arn,
                                        handler_name,
                                        test_package,
                                        error_code=error_code)
    if error_code is None:
        lambda_stubber.stub_get_function(func_name, 'Active')

    if error_code is None:
        got_arn = wrapper.create_function(func_name, handler_name, iam_role,
                                          test_package)
        assert got_arn == func_arn
    else:
        with pytest.raises(ClientError) as exc_info:
            wrapper.create_function(func_name, handler_name, iam_role,
                                    test_package)
        assert exc_info.value.response['Error']['Code'] == error_code
示例#2
0
def test_update_function_configuration(make_stubber, error_code):
    lambda_client = boto3.client('lambda')
    lambda_stubber = make_stubber(lambda_client)
    wrapper = LambdaWrapper(lambda_client, None)
    func_name = 'test-func_name'
    env_vars = {'test-key': 'test-val'}

    lambda_stubber.stub_update_function_configuration(func_name,
                                                      env_vars,
                                                      error_code=error_code)

    if error_code is None:
        got_response = wrapper.update_function_configuration(
            func_name, env_vars)
        assert got_response
    else:
        with pytest.raises(ClientError) as exc_info:
            wrapper.update_function_configuration(func_name, env_vars)
        assert exc_info.value.response['Error']['Code'] == error_code
示例#3
0
def test_update_function_code(make_stubber, error_code):
    lambda_client = boto3.client('lambda')
    lambda_stubber = make_stubber(lambda_client)
    wrapper = LambdaWrapper(lambda_client, None)
    func_name = 'test-func_name'
    package = 'test-package'
    update_status = 'InProgress'

    lambda_stubber.stub_update_function_code(func_name,
                                             update_status,
                                             package=package,
                                             error_code=error_code)

    if error_code is None:
        got_response = wrapper.update_function_code(func_name, package)
        assert got_response['LastUpdateStatus'] == update_status
    else:
        with pytest.raises(ClientError) as exc_info:
            wrapper.update_function_code(func_name, package)
        assert exc_info.value.response['Error']['Code'] == error_code
示例#4
0
def test_invoke_function(make_stubber, make_unique_name, error_code):
    lambda_client = boto3.client('lambda')
    lambda_stubber = make_stubber(lambda_client)
    wrapper = LambdaWrapper(lambda_client, None)
    func_name = make_unique_name('func-')
    func_params = {'param1': 'test', 'param2': 35}
    response_payload = 'ahoy there'

    lambda_stubber.stub_invoke(func_name,
                               json.dumps(func_params),
                               response_payload,
                               log_type='None',
                               error_code=error_code)

    if error_code is None:
        response = wrapper.invoke_function(func_name, func_params)
        assert response['Payload'] == response_payload
    else:
        with pytest.raises(ClientError) as exc_info:
            wrapper.invoke_function(func_name, func_params)
        assert exc_info.value.response['Error']['Code'] == error_code
示例#5
0
def test_create_iam_role_for_lambda(make_stubber, make_unique_name,
                                    stub_runner, error_code, stop_on_method):
    iam_resource = boto3.resource('iam')
    iam_stubber = make_stubber(iam_resource.meta.client)
    wrapper = LambdaWrapper(None, iam_resource)
    role_name = make_unique_name('role-')

    with stub_runner(error_code, stop_on_method) as runner:
        runner.add(iam_stubber.stub_get_role,
                   role_name,
                   error_code='NoSuchEntity')
        runner.add(iam_stubber.stub_create_role, role_name)
        runner.add(
            iam_stubber.stub_attach_role_policy, role_name,
            'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole')

    if error_code is None:
        got_role, got_created = wrapper.create_iam_role_for_lambda(role_name)
        assert got_role.name == role_name
        assert got_created
    else:
        with pytest.raises(ClientError) as exc_info:
            wrapper.create_iam_role_for_lambda(role_name)
        assert exc_info.value.response['Error']['Code'] == error_code
示例#6
0
def test_get_function(make_stubber, error_code):
    lambda_client = boto3.client('lambda')
    lambda_stubber = make_stubber(lambda_client)
    wrapper = LambdaWrapper(lambda_client, None)
    func_name = 'test-func_name'

    lambda_stubber.stub_get_function(func_name, error_code=error_code)

    if error_code in (None, 'ResourceNotFoundException'):
        wrapper.get_function(func_name)
    else:
        with pytest.raises(ClientError) as exc_info:
            wrapper.get_function(func_name)
        assert exc_info.value.response['Error']['Code'] == error_code
示例#7
0
def test_delete_function(make_stubber, make_unique_name, error_code):
    lambda_client = boto3.client('lambda')
    lambda_stubber = make_stubber(lambda_client)
    wrapper = LambdaWrapper(lambda_client, None)
    func_name = make_unique_name('func-')

    lambda_stubber.stub_delete_function(func_name, error_code=error_code)

    if error_code is None:
        wrapper.delete_function(func_name)
    else:
        with pytest.raises(ClientError) as exc_info:
            wrapper.delete_function(func_name)
        assert exc_info.value.response['Error']['Code'] == error_code
示例#8
0
def test_list_functions(make_stubber, error_code):
    lambda_client = boto3.client('lambda')
    lambda_stubber = make_stubber(lambda_client)
    wrapper = LambdaWrapper(lambda_client, None)
    funcs = [{
        'FunctionName': f'test-func-{index}',
        'Description': f'test description {index}',
        'Runtime': f'test-runtime-{index}',
        'Handler': f'test-handler-{index}'
    } for index in range(3)]

    lambda_stubber.stub_list_functions(funcs, error_code=error_code)

    if error_code is None:
        wrapper.list_functions()
    else:
        with pytest.raises(ClientError) as exc_info:
            wrapper.list_functions()
        assert exc_info.value.response['Error']['Code'] == error_code
def run_scenario(lambda_client, iam_resource, basic_file, calculator_file,
                 lambda_name):
    """
    Runs the scenario.

    :param lambda_client: A Boto3 Lambda client.
    :param iam_resource: A Boto3 IAM resource.
    :param basic_file: The name of the file that contains the basic Lambda handler.
    :param calculator_file: The name of the file that contains the calculator Lambda handler.
    :param lambda_name: The name to give resources created for the scenario, such as the
                        IAM role and the Lambda function.
    """
    logging.basicConfig(level=logging.INFO,
                        format='%(levelname)s: %(message)s')

    print('-' * 88)
    print("Welcome to the AWS Lambda getting started with functions demo.")
    print('-' * 88)

    wrapper = LambdaWrapper(lambda_client, iam_resource)

    print("Checking for IAM role for Lambda...")
    iam_role, should_wait = wrapper.create_iam_role_for_lambda(lambda_name)
    if should_wait:
        logger.info("Giving AWS time to create resources...")
        wait(10)

    print(f"Looking for function {lambda_name}...")
    function = wrapper.get_function(lambda_name)
    if function is None:
        print("Zipping the Python script into a deployment package...")
        deployment_package = wrapper.create_deployment_package(
            basic_file, f"{lambda_name}.py")
        print(f"...and creating the {lambda_name} Lambda function.")
        wrapper.create_function(lambda_name, f'{lambda_name}.lambda_handler',
                                iam_role, deployment_package)
    else:
        print(f"Function {lambda_name} already exists.")
    print('-' * 88)

    print(f"Let's invoke {lambda_name}. This function increments a number.")
    action_params = {
        'action': 'increment',
        'number': q.ask("Give me a number to increment: ", q.is_int)
    }
    print(f"Invoking {lambda_name}...")
    response = wrapper.invoke_function(lambda_name, action_params)
    print(f"Incrementing {action_params['number']} resulted in "
          f"{json.load(response['Payload'])}")
    print('-' * 88)

    print(f"Let's update the function to an arithmetic calculator.")
    q.ask("Press Enter when you're ready.")
    print("Creating a new deployment package...")
    deployment_package = wrapper.create_deployment_package(
        calculator_file, f"{lambda_name}.py")
    print(f"...and updating the {lambda_name} Lambda function.")
    update_waiter = UpdateFunctionWaiter(lambda_client)
    wrapper.update_function_code(lambda_name, deployment_package)
    update_waiter.wait(lambda_name)
    print(
        f"This function uses an environment variable to control logging level."
    )
    print(f"Let's set it to DEBUG to get the most logging.")
    wrapper.update_function_configuration(
        lambda_name, {'LOG_LEVEL': logging.getLevelName(logging.DEBUG)})

    actions = ['plus', 'minus', 'times', 'divided-by']
    want_invoke = True
    while want_invoke:
        print(f"Let's invoke {lambda_name}. You can invoke these actions:")
        for index, action in enumerate(actions):
            print(f"{index + 1}: {action}")
        action_params = {}
        action_index = q.ask(
            "Enter the number of the action you want to take: ", q.is_int,
            q.in_range(1, len(actions)))
        action_params['action'] = actions[action_index - 1]
        print(f"You've chosen to invoke 'x {action_params['action']} y'.")
        action_params['x'] = q.ask("Enter a value for x: ", q.is_int)
        action_params['y'] = q.ask("Enter a value for y: ", q.is_int)
        print(f"Invoking {lambda_name}...")
        response = wrapper.invoke_function(lambda_name, action_params, True)
        print(
            f"Calculating {action_params['x']} {action_params['action']} {action_params['y']} "
            f"resulted in {json.load(response['Payload'])}")
        q.ask("Press Enter to see the logs from the call.")
        print(base64.b64decode(response['LogResult']).decode())
        want_invoke = q.ask("That was fun. Shall we do it again? (y/n) ",
                            q.is_yesno)
    print('-' * 88)

    if q.ask("Do you want to list all of the functions in your account? (y/n) "
             ):
        wrapper.list_functions()
    print('-' * 88)

    if q.ask("Ready to delete the function and role? (y/n) ", q.is_yesno):
        for policy in iam_role.attached_policies.all():
            policy.detach_role(RoleName=iam_role.name)
        iam_role.delete()
        print(f"Deleted role {lambda_name}.")
        wrapper.delete_function(lambda_name)
        print(f"Deleted function {lambda_name}.")

    print("\nThanks for watching!")
    print('-' * 88)
示例#10
0
def test_create_lambda_deployment_package(monkeypatch):
    monkeypatch.setattr(zipfile.ZipFile, 'write', lambda x, y, z: None)
    wrapper = LambdaWrapper(None, None)

    got_package = wrapper.create_deployment_package('test-file', 'other-file')
    assert got_package is not None