aws / aws-lambda-runtime-interface-emulator

Apache License 2.0
915 stars 95 forks source link

Lambda RIE as Standalone App/Container for Testing #83

Open driverpt opened 1 year ago

driverpt commented 1 year ago

Hello,

For Testing purposes, in this case Java, it would be great that AWS makes Lambda RIE available as Standalone App/Container so we can easily add this to JUnit 5 + Test Containers and be able to do Integration Tests (via Public ECR Gallery) on our Clients.

Thanks

ghost commented 1 year ago

Thank you for bring this to our attention.

Just to understand the problem better, why can https://gallery.ecr.aws/lambda/java not be used?

driverpt commented 1 year ago

Ok, so what I'm trying to do is create automated tests using JUnit 5 + TestContainers + GraalVM for a custom Lambda Runtime Client and this could be achieved just by exposing a simple Dummy Lambda Emulator and overriding AWS_LAMBDA_RUNTIME_API Environment Variable/Property and use the proper Assertions.

Do you think this is possible to achieve?

ghost commented 1 year ago

So you are not able to use https://gallery.ecr.aws/lambda/java because you are not using the included Java Lambda Runtime Interface Client (RIC), but you are building your own RIC and want to test that?

driverpt commented 1 year ago

Hello @bodelsc , no. I'm just looking for a Runtime API Emulator/Simulator that I can just Pub/Sub and assert responses to test a Custom HTTP Client

ghost commented 1 year ago

The AWS base images for Lambda include the AWS Lambda Runtime Interface Emulator(RIE). For your purpose can you not copy your function's code into the container, start it and then use HTTP to make requests?

See

driverpt commented 1 year ago

Is it possible to Start the Container Standalone without Function Code inside?

ghost commented 1 year ago

I am unsure about starting, but you can create one, copy in code etc and then start it.

E.g.

docker_name=$(docker create --publish 9000:8080 "public.ecr.aws/lambda/nodejs:16" "app.handler")
echo -e 'exports.handler = async () => {\n\tconsole.log("Hello world!");\n};' > /tmp/app.js
docker cp "/tmp/app.js" "${docker_name}:/var/task/app.js"
docker start "${docker_name}"           
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
docker logs "${docker_name}"                                             
docker stop "${docker_name}" 
docker rm "${docker_name}" 
kferrone commented 1 year ago

I want to do the same.

I took a stab at it like this:

FROM ubuntu 

RUN apt-get update && \
    apt-get install -y curl && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN mkdir -p ~/.aws-lambda-rie && \
    curl -Lo ~/.aws-lambda-rie/aws-lambda-rie \
      https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64 && \
    chmod +x ~/.aws-lambda-rie/aws-lambda-rie && \
    mv ~/.aws-lambda-rie/aws-lambda-rie /usr/local/bin/aws-lambda-rie

ENTRYPOINT [ "aws-lambda-rie" ]

Then a docker compose:

version: '3.9'
services:
  lilfunc: 
    build: .
    image: lilfunc:latest
    container_name: lilfunc
    environment:
      AWS_LAMBDA_RUNTIME_API: rie:8080
    depends_on:
    - rie
  rie:
    build:
      context: .
      dockerfile: Dockerfile.rie
    image: rie:latest
    container_name: rie
    ports:
    - 9000:8080

But this happens in the function container:

Attaching to rie, lilfunc Traceback (most recent call last): File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main return _run_code(code, main_globals, None, File "/usr/lib/python3.9/runpy.py", line 87, in _run_code exec(code, run_globals) File "/function/awslambdaric/main.py", line 25, in main(sys.argv) File "/function/awslambdaric/main.py", line 21, in main bootstrap.run(app_root, handler, lambda_runtime_api_addr) File "/function/awslambdaric/bootstrap.py", line 399, in run event_request = lambda_runtime_client.wait_next_invocation() File "/function/awslambdaric/lambda_runtime_client.py", line 68, in wait_next_invocation response_body, headers = runtime_client.next() AttributeError: 'NoneType' object has no attribute 'next' lilfunc exited with code 1

driverpt commented 1 year ago

I ended up creating a simple app that simulates lambda runtime api server.

https://github.com/driverpt/aws-lambda-runtime-simulator