quarkusio / quarkus-quickstarts

Quarkus quickstart code
https://quarkus.io
Apache License 2.0
1.97k stars 1.47k forks source link

Dev Services for Amazon Services docs not backed by Lambda sample using LocalStack #1368

Open tinyg210 opened 10 months ago

tinyg210 commented 10 months ago

Hi, I'm trying to follow the docs for the Dev Services for Amazon Services, particularly the one for Lambda that uses LocalStack. I run into a few issues and I'm not sure if the docs are correct since there's no linked sample to this particular scenario.

My setup: Apache Maven 3.9.4 Java version: 17.0.3, vendor: Oracle Corporation Default locale: en_GB, platform encoding: UTF-8 OS name: "mac os x", version: "14.0", arch: "x86_64", family: "mac"

  1. The create new project command doesn't know which extension to use for amazon-lambda:
    mvn io.quarkus.platform:quarkus-maven-plugin:3.6.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=amazon-lambda-quickstart \
    -DclassName="org.acme.lambda.QuarkusLambdaSyncResource" \
    -Dpath="/sync" \
    -Dextensions="resteasy-reactive-jackson,amazon-lambda"

    results into:

    [INFO] [ERROR] ❗  Multiple extensions matching 'amazon-lambda'
     - io.quarkus:quarkus-amazon-lambda
     - io.quarkiverse.amazonservices:quarkus-amazon-lambda
     - io.quarkus:quarkus-amazon-lambda-http
     - io.quarkus:quarkus-amazon-lambda-rest
     - io.quarkus:quarkus-amazon-lambda-xray
     - io.quarkus:quarkus-funqy-amazon-lambda
     try using the exact name or the full GAV (group id, artifact id, and version).

I then choose io.quarkus:quarkus-amazon-lambda and the project is created, with a Person entity and a Lambda function. I add the necessary dependency as instructed.

  1. Running mvn clean package fails with the following stack trace:

    -------------------------------------------------------------------------------
    Test set: org.acme.lambda.lambda.LambdaHandlerTest
    -------------------------------------------------------------------------------
    Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.096 s <<< FAILURE! -- in org.acme.lambda.lambda.LambdaHandlerTest
    org.acme.lambda.lambda.LambdaHandlerTest.testSimpleLambdaSuccess -- Time elapsed: 1.544 s <<< FAILURE!
    java.lang.AssertionError: 
    1 expectation failed.
    Expected status code <200> but was <404>.
    
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:73)
    at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:108)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:57)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:277)
    at io.restassured.internal.ResponseSpecificationImpl$HamcrestAssertionClosure.validate(ResponseSpecificationImpl.groovy:512)
    at io.restassured.internal.ResponseSpecificationImpl$HamcrestAssertionClosure$validate$1.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
    at io.restassured.internal.ResponseSpecificationImpl.validateResponseIfRequired(ResponseSpecificationImpl.groovy:696)
    at io.restassured.internal.ResponseSpecificationImpl.this$2$validateResponseIfRequired(ResponseSpecificationImpl.groovy)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:198)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:62)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185)
    at io.restassured.internal.ResponseSpecificationImpl.statusCode(ResponseSpecificationImpl.groovy:135)
    at io.restassured.specification.ResponseSpecification$statusCode$0.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185)
    at io.restassured.internal.ResponseSpecificationImpl.statusCode(ResponseSpecificationImpl.groovy:143)
    at io.restassured.internal.ValidatableResponseOptionsImpl.statusCode(ValidatableResponseOptionsImpl.java:89)
    at org.acme.lambda.lambda.LambdaHandlerTest.testSimpleLambdaSuccess(LambdaHandlerTest.java:26)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:1013)
    at io.quarkus.test.junit.QuarkusTestExtension.interceptTestMethod(QuarkusTestExtension.java:827)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

    There is no LocalStack container starting while running the test, but the docs say that Quarkus Amazon Services automatically starts a LocalStack container in dev mode and when running tests.

I added how the project looks at the point of failure: https://github.com/tinyg210/sample-quarkus-lambda-from-docs

There is a lot of abstraction and "magic" behind the Dev Services and I can't tell what is missing and if in fact something is missing. Btw, Lambda functions in LocalStack spin up in a separate container, but if the Dev Services are using Testcontainers in the background, that should not be an issue.

Can someone please explain how this works behind the scenes and what's missing from this setup?

scrocquesel commented 10 months ago

I guess there is a misunderstanding on who's who.

io.quarkiverse.amazonservices:quarkus-amazon-lambda is the quarkus wrapper around the lambda client from the aws sdk to manage lambda while io.quarkus:quarkus-amazon-lambda is the extension to build applications to be run in lambda. The documentation of the latter is https://quarkus.io/guides/aws-lambda.

Regarding the quarkiverse extension (sdk client), we do not currently provide a thoroughfull quickstart but you can look into our integration tests. You should pay attention to the test case and how we create a test lambda application in DevServices for AWS.

Those two extensions should work together so that you may be able to start/stop/create/delete a lambda application from a lambda application.