2

I created a code to invoke a AWS lambda function created somewhere else.

I would like to use moto for testing it, but I don't really understand how to do it and I continue to obtain errors.

This is a simple example of the main code:

import boto3
import json


class SimpleLambda:
    def __init__(self):
        self.aws_lambda = boto3.client("lambda", region_name="eu-west-2")

    def __call__(self):
        try:
            lambda_response = self.aws_lambda.invoke(
                FunctionName="test-lambda",
                Payload=json.dumps(
                    {
                        "Records": [
                            {
                                "Source": "test_source",
                                "Version": "test_version",
                            }
                        ]
                    }
                ),
            )
            return lambda_response["Payload"].read()
        except Exception as err:
            print(f"Could not invoke simple lambda: {err}")
            return None

and the test:

import os
import pytest
import unittest.mock as mock

import boto3
from moto import mock_lambda

from aws_lambda import SimpleLambda


@pytest.fixture
def aws_credentials():
    os.environ["AWS_ACCESS_KEY_ID"] = "testing"
    os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
    os.environ["AWS_SECURITY_TOKEN"] = "testing"
    os.environ["AWS_SESSION_TOKEN"] = "testing"


@pytest.fixture
def lambda_client(aws_credentials):
    with mock_lambda():
        yield boto3.client("lambda", region_name="eu-west-2")


@pytest.fixture
def lambda_test(lambda_client):
    lambda_client.create_function(
        FunctionName="test-lambda",
        Role="arn:aws:iam::123456789012:role/doesnotexist",
        Code={"ZipFile": b"test"}
    )
    yield


def test_simple_lambda_call(lambda_client, lambda_test):
    simple_lambda = SimpleLambda()

    test = simple_lambda()

I obtain the error:

botocore.errorfactory.InvalidParameterValueException: An error occurred (InvalidParameterValueException) when calling the CreateFunction operation: The role defined for the function cannot be assumed by Lambda.

I found several example about how to use moto with S3 bucket, but nothing with lambda.

Running the code in this other question, I obtain the same error.

Any advice?

cicciodevoto
  • 305
  • 4
  • 19

1 Answers1

2

Moto also validates whether the IAM role exists, just like AWS does.

So make sure that the IAM role is created first:

with mock_iam():
    iam = boto3.client("iam", region_name="eu-west-2")
    iam_role = iam.create_role(
        RoleName="my-role",
        AssumeRolePolicyDocument="some policy",
        Path="/my-path/",
    )["Role"]["Arn"]
Bert Blommers
  • 1,788
  • 2
  • 13
  • 19
  • 1
    Thanks that solved the boto error, but now I have another one. The payload contains the message `error running docker: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))` Do I have to start in some way the moto server? – cicciodevoto Nov 06 '22 at 07:23
  • That error is specific to Docker, and indicates that the Docker-service is not started/reachable. See https://stackoverflow.com/questions/64952238/docker-errors-dockerexception-error-while-fetching-server-api-version for some solutions to this – Bert Blommers Nov 06 '22 at 13:09
  • Thanks again. So that means I have to start Docker service using the terminal before to run the test. Am I right? Is there a way to start it in python? – cicciodevoto Nov 06 '22 at 20:32
  • 1
    I'm not aware of a good way to start it in Python @cicciodevoto - personally I always have it started on boot. – Bert Blommers Nov 06 '22 at 20:36