You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pp...@apache.org on 2021/02/24 12:23:08 UTC

[camel-quarkus] branch master updated: Test AWS 2 Lambda

This is an automated email from the ASF dual-hosted git repository.

ppalaga pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/master by this push:
     new 7c262c7  Test AWS 2 Lambda
7c262c7 is described below

commit 7c262c76ad0651da52bbeccf55e15623adef5ce6
Author: Peter Palaga <pp...@redhat.com>
AuthorDate: Tue Feb 23 21:25:58 2021 +0100

    Test AWS 2 Lambda
---
 .../pages/reference/extensions/aws2-lambda.adoc    |   6 +
 extensions/aws2-lambda/deployment/pom.xml          |   4 +
 extensions/aws2-lambda/runtime/pom.xml             |   4 +
 .../aws2-lambda/pom.xml                            |  67 +++++++++--
 .../aws2/lambda/it/Aws2LambdaResource.java         | 127 +++++++++++++++++++++
 .../src/main/resources/application.properties      |  20 ++++
 .../component/aws2/lambda/it/Aws2LambdaIT.java     |  27 +++++
 .../component/aws2/lambda/it/Aws2LambdaTest.java   | 121 ++++++++++++++++++++
 .../lambda/it/Aws2LambdaTestEnvCustomizer.java     |  76 ++++++++++++
 ...quarkus.test.support.aws2.Aws2TestEnvCustomizer |   1 +
 integration-tests-aws2/pom.xml                     |   1 +
 .../test/support/aws2/Aws2TestEnvContext.java      |   1 +
 integration-tests/aws2-grouped/pom.xml             |  17 +++
 .../integration-test-pom.xml                       |   2 +-
 14 files changed, 464 insertions(+), 10 deletions(-)

diff --git a/docs/modules/ROOT/pages/reference/extensions/aws2-lambda.adoc b/docs/modules/ROOT/pages/reference/extensions/aws2-lambda.adoc
index 6f6427a..a9fb380 100644
--- a/docs/modules/ROOT/pages/reference/extensions/aws2-lambda.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/aws2-lambda.adoc
@@ -31,3 +31,9 @@ Please refer to the above link for usage and configuration details.
 ----
 
 Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.
+
+== SSL in native mode
+
+This extension auto-enables SSL support in native mode. Hence you do not need to add
+`quarkus.ssl.native=true` to your `application.properties` yourself. See also
+https://quarkus.io/guides/native-and-ssl[Quarkus SSL guide].
diff --git a/extensions/aws2-lambda/deployment/pom.xml b/extensions/aws2-lambda/deployment/pom.xml
index ce79981..b10ee84 100644
--- a/extensions/aws2-lambda/deployment/pom.xml
+++ b/extensions/aws2-lambda/deployment/pom.xml
@@ -36,6 +36,10 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-support-aws2-deployment</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-aws2-lambda</artifactId>
         </dependency>
     </dependencies>
diff --git a/extensions/aws2-lambda/runtime/pom.xml b/extensions/aws2-lambda/runtime/pom.xml
index c54a4d9..56eab22 100644
--- a/extensions/aws2-lambda/runtime/pom.xml
+++ b/extensions/aws2-lambda/runtime/pom.xml
@@ -53,6 +53,10 @@
             <artifactId>camel-quarkus-core</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-support-aws2</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-aws2-lambda</artifactId>
         </dependency>
diff --git a/tooling/create-extension-templates/integration-test-pom.xml b/integration-tests-aws2/aws2-lambda/pom.xml
similarity index 57%
copy from tooling/create-extension-templates/integration-test-pom.xml
copy to integration-tests-aws2/aws2-lambda/pom.xml
index c5eefb4..7a9669a 100644
--- a/tooling/create-extension-templates/integration-test-pom.xml
+++ b/integration-tests-aws2/aws2-lambda/pom.xml
@@ -23,14 +23,14 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-[#if nativeSupported][=itestParentArtifactId][#else]build-parent-it[/#if]</artifactId>
-        <version>[=version]</version>
-        <relativePath>[#if nativeSupported]../pom.xml[#else]../../../poms/build-parent-it/pom.xml[/#if]</relativePath>
+        <artifactId>camel-quarkus-integration-tests-aws2</artifactId>
+        <version>1.8.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
     </parent>
 
-    <artifactId>camel-quarkus-[#if nativeSupported]integration-test-[=artifactIdBase][#else][=artifactIdBase]-integration-test[/#if]</artifactId>
-    <name>Camel Quarkus :: [#if nativeSupported]Integration Tests :: [=nameBase][#else][=nameBase] :: Integration Test[/#if]</name>
-    <description>Integration tests for Camel Quarkus [=nameBase] extension</description>
+    <artifactId>camel-quarkus-integration-test-aws2-lambda</artifactId>
+    <name>Camel Quarkus :: Integration Tests :: AWS 2 Lambda</name>
+    <description>Integration tests for Camel Quarkus AWS 2 Lambda extension</description>
 
     <dependencyManagement>
         <dependencies>
@@ -47,12 +47,20 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-[=artifactIdBase]</artifactId>
+            <artifactId>camel-quarkus-main</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-aws2-lambda</artifactId>
         </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-resteasy</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-jackson</artifactId>
+        </dependency>
 
         <!-- test dependencies -->
         <dependency>
@@ -65,8 +73,50 @@
             <artifactId>rest-assured</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-integration-tests-support-aws2</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.awaitility</groupId>
+            <artifactId>awaitility</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>iam</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory -->
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-aws2-lambda-deployment</artifactId>
+            <version>${project.version}</version>
+            <type>pom</type>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>*</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-main-deployment</artifactId>
+            <version>${project.version}</version>
+            <type>pom</type>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>*</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
     </dependencies>
-[#if nativeSupported ]
 
     <profiles>
         <profile>
@@ -98,5 +148,4 @@
         </profile>
     </profiles>
 
-[/#if]
 </project>
diff --git a/integration-tests-aws2/aws2-lambda/src/main/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaResource.java b/integration-tests-aws2/aws2-lambda/src/main/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaResource.java
new file mode 100644
index 0000000..0992a3c
--- /dev/null
+++ b/integration-tests-aws2/aws2-lambda/src/main/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaResource.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.aws2.lambda.it;
+
+import java.net.URI;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.aws2.lambda.Lambda2Constants;
+import org.apache.camel.component.aws2.lambda.Lambda2Operations;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import software.amazon.awssdk.services.lambda.model.FunctionConfiguration;
+import software.amazon.awssdk.services.lambda.model.InvalidParameterValueException;
+import software.amazon.awssdk.services.lambda.model.ListFunctionsResponse;
+
+@Path("/aws2-lambda")
+@ApplicationScoped
+public class Aws2LambdaResource {
+    @ConfigProperty(name = "aws-lambda.role-arn")
+    String roleArn;
+
+    @Inject
+    ProducerTemplate producerTemplate;
+
+    @Path("/create/{functionName}")
+    @POST
+    @Consumes("application/zip")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response createFunction(byte[] message, @PathParam("functionName") String functionName) throws Exception {
+        final String response = producerTemplate.requestBodyAndHeaders(
+                componentUri(functionName, Lambda2Operations.createFunction),
+                message,
+                new LinkedHashMap<String, Object>() {
+                    {
+                        put(Lambda2Constants.ROLE, roleArn);
+                        put(Lambda2Constants.RUNTIME, "nodejs12.x");
+                        put(Lambda2Constants.HANDLER, "index.handler");
+                    }
+                },
+                String.class);
+        return Response
+                .created(new URI("https://camel.apache.org/"))
+                .entity(response)
+                .build();
+    }
+
+    @Path("/listFunctions")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<String> listFunctions() throws Exception {
+        return producerTemplate.requestBody(
+                componentUri("foo", Lambda2Operations.listFunctions),
+                null,
+                ListFunctionsResponse.class)
+                .functions().stream()
+                .map(FunctionConfiguration::functionName)
+                .collect(Collectors.toList());
+    }
+
+    @Path("/invoke/{functionName}")
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public String invoke(byte[] message, @PathParam("functionName") String functionName) throws Exception {
+        return producerTemplate.requestBody(
+                componentUri(functionName, Lambda2Operations.invokeFunction),
+                message,
+                String.class);
+    }
+
+    @Path("/delete/{functionName}")
+    @DELETE
+    @Produces(MediaType.APPLICATION_JSON)
+    public void delete(@PathParam("functionName") String functionName) throws Exception {
+        producerTemplate.requestBody(
+                componentUri(functionName, Lambda2Operations.deleteFunction),
+                null,
+                Object.class);
+    }
+
+    private static String componentUri(String functionName, Lambda2Operations operation) {
+        return "aws2-lambda:" + functionName + "?operation=" + operation;
+    }
+
+    @Provider
+    public static class ExceptionMapper implements javax.ws.rs.ext.ExceptionMapper<CamelExecutionException> {
+        @Override
+        public Response toResponse(CamelExecutionException exception) {
+            if (exception.getCause() instanceof InvalidParameterValueException) {
+                return Response.status(Status.BAD_REQUEST).entity(exception.getCause().getMessage()).build();
+            }
+            return Response.status(Status.INTERNAL_SERVER_ERROR).entity(exception.getMessage()).build();
+        }
+    }
+
+}
diff --git a/integration-tests-aws2/aws2-lambda/src/main/resources/application.properties b/integration-tests-aws2/aws2-lambda/src/main/resources/application.properties
new file mode 100644
index 0000000..f8883f8
--- /dev/null
+++ b/integration-tests-aws2/aws2-lambda/src/main/resources/application.properties
@@ -0,0 +1,20 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+camel.component.aws2-lambda.access-key=${AWS_ACCESS_KEY}
+camel.component.aws2-lambda.secret-key=${AWS_SECRET_KEY}
+camel.component.aws2-lambda.region=${AWS_REGION:us-east-1}
diff --git a/integration-tests-aws2/aws2-lambda/src/test/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaIT.java b/integration-tests-aws2/aws2-lambda/src/test/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaIT.java
new file mode 100644
index 0000000..e573cef
--- /dev/null
+++ b/integration-tests-aws2/aws2-lambda/src/test/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaIT.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.aws2.lambda.it;
+
+import io.quarkus.test.junit.NativeImageTest;
+import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
+
+//TODO disabled because of https://github.com/apache/camel-quarkus/issues/2216
+@EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY", matches = "[a-zA-Z0-9]+")
+@NativeImageTest
+class Aws2LambdaIT extends Aws2LambdaTest {
+
+}
diff --git a/integration-tests-aws2/aws2-lambda/src/test/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaTest.java b/integration-tests-aws2/aws2-lambda/src/test/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaTest.java
new file mode 100644
index 0000000..48e0548
--- /dev/null
+++ b/integration-tests-aws2/aws2-lambda/src/test/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaTest.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.aws2.lambda.it;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import io.restassured.response.ExtractableResponse;
+import org.apache.camel.quarkus.test.support.aws2.Aws2TestResource;
+import org.awaitility.Awaitility;
+import org.hamcrest.Matchers;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
+
+//TODO disabled because of https://github.com/apache/camel-quarkus/issues/2216
+@EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY", matches = "[a-zA-Z0-9]+")
+@QuarkusTest
+@QuarkusTestResource(Aws2TestResource.class)
+class Aws2LambdaTest {
+    private static final Logger LOG = Logger.getLogger(Aws2LambdaTest.class);
+
+    @Test
+    public void e2e() {
+        final String functionName = "cqFunction" + java.util.UUID.randomUUID().toString().replace("-", "");
+        final String name = "Joe " + java.util.UUID.randomUUID().toString().replace("-", "");
+
+        /* The role is not created immediately, so we need to retry */
+        Awaitility.await()
+                .pollDelay(6, TimeUnit.SECONDS) // never succeeded earlier than 6 seconds after creating the role
+                .pollInterval(1, TimeUnit.SECONDS)
+                .atMost(120, TimeUnit.SECONDS)
+                .until(
+                        () -> {
+                            ExtractableResponse<?> response = RestAssured.given()
+                                    .contentType("application/zip")
+                                    .body(createFunctionZip())
+                                    .post("/aws2-lambda/create/" + functionName)
+                                    .then()
+                                    .extract();
+                            switch (response.statusCode()) {
+                            case 201:
+                                LOG.infof("Function %s created", functionName);
+                                return true;
+                            case 400:
+                                LOG.infof("Could not create function %s yet (will retry): %d %s", functionName,
+                                        response.statusCode(),
+                                        response.body().asString());
+                                return false;
+                            default:
+                                throw new RuntimeException(
+                                        "Unexpected status from /aws2-lambda/create " + response.statusCode() + " "
+                                                + response.body().asString());
+                            }
+                        });
+
+        RestAssured.given()
+                .accept(ContentType.JSON)
+                .get("/aws2-lambda/listFunctions")
+                .then()
+                .statusCode(200)
+                .body("$", Matchers.hasItem(functionName));
+
+        RestAssured.given()
+                .contentType(ContentType.JSON)
+                .body("{ \"firstName\": \"" + name + "\"}")
+                .post("/aws2-lambda/invoke/" + functionName)
+                .then()
+                .statusCode(200)
+                .body("greetings", Matchers.is("Hello " + name));
+
+        RestAssured.given()
+                .delete("/aws2-lambda/delete/" + functionName)
+                .then()
+                .statusCode(204);
+
+    }
+
+    static byte[] createFunctionZip() {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (ZipOutputStream out = new ZipOutputStream(baos)) {
+            out.putNextEntry(new ZipEntry("index.js"));
+            out.write(FUNCTION_SOURCE.getBytes(StandardCharsets.UTF_8));
+            out.closeEntry();
+        } catch (IOException e) {
+            throw new RuntimeException("Could not create a zip file", e);
+        }
+        return baos.toByteArray();
+    }
+
+    private static final String FUNCTION_SOURCE = "exports.handler = function(event, context, callback) {\n"
+            + "   console.log(\"Received event: \", event);\n"
+            + "   var data = {\n"
+            + "       \"greetings\": \"Hello \" + event.firstName\n"
+            + "   };\n"
+            + "   callback(null, data);\n"
+            + "}\n";
+
+}
diff --git a/integration-tests-aws2/aws2-lambda/src/test/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaTestEnvCustomizer.java b/integration-tests-aws2/aws2-lambda/src/test/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaTestEnvCustomizer.java
new file mode 100644
index 0000000..e626d1d
--- /dev/null
+++ b/integration-tests-aws2/aws2-lambda/src/test/java/org/apache/camel/quarkus/component/aws2/lambda/it/Aws2LambdaTestEnvCustomizer.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.aws2.lambda.it;
+
+import java.util.Locale;
+
+import org.apache.camel.quarkus.test.support.aws2.Aws2TestEnvContext;
+import org.apache.camel.quarkus.test.support.aws2.Aws2TestEnvCustomizer;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.testcontainers.containers.localstack.LocalStackContainer.Service;
+import software.amazon.awssdk.services.iam.IamClient;
+import software.amazon.awssdk.services.iam.model.CreateRoleRequest;
+import software.amazon.awssdk.services.iam.model.DeleteRoleRequest;
+import software.amazon.awssdk.services.iam.model.GetRoleRequest;
+import software.amazon.awssdk.services.iam.waiters.IamWaiter;
+
+public class Aws2LambdaTestEnvCustomizer implements Aws2TestEnvCustomizer {
+
+    @Override
+    public Service[] localstackServices() {
+        return new Service[] { Service.LAMBDA, Service.IAM };
+    }
+
+    @Override
+    public Service[] exportCredentialsForLocalstackServices() {
+        return new Service[] { Service.LAMBDA };
+    }
+
+    @Override
+    public void customize(Aws2TestEnvContext envContext) {
+
+        final String id = RandomStringUtils.randomAlphanumeric(16).toLowerCase(Locale.ROOT);
+        final String roleName = "cq-lambda-" + id;
+
+        final IamClient iamClient = envContext.client(Service.IAM, IamClient::builder);
+        final String roleArn = iamClient.createRole(
+                CreateRoleRequest.builder()
+                        .roleName(roleName)
+                        .path("/service-role/")
+                        .assumeRolePolicyDocument("{\n"
+                                + "  \"Version\": \"2012-10-17\",\n"
+                                + "  \"Statement\": [\n"
+                                + "    {\n"
+                                + "      \"Effect\": \"Allow\",\n"
+                                + "      \"Principal\": {\n"
+                                + "        \"Service\": \"lambda.amazonaws.com\"\n"
+                                + "      },\n"
+                                + "      \"Action\": \"sts:AssumeRole\"\n"
+                                + "    }\n"
+                                + "  ]\n"
+                                + "}")
+                        .build())
+                .role().arn();
+        envContext.closeable(() -> iamClient.deleteRole(DeleteRoleRequest.builder().roleName(roleName).build()));
+
+        try (IamWaiter w = iamClient.waiter()) {
+            w.waitUntilRoleExists(GetRoleRequest.builder().roleName(roleName).build());
+        }
+
+        envContext.property("aws-lambda.role-arn", roleArn);
+    }
+}
diff --git a/integration-tests-aws2/aws2-lambda/src/test/resources/META-INF/services/org.apache.camel.quarkus.test.support.aws2.Aws2TestEnvCustomizer b/integration-tests-aws2/aws2-lambda/src/test/resources/META-INF/services/org.apache.camel.quarkus.test.support.aws2.Aws2TestEnvCustomizer
new file mode 100644
index 0000000..8e05664
--- /dev/null
+++ b/integration-tests-aws2/aws2-lambda/src/test/resources/META-INF/services/org.apache.camel.quarkus.test.support.aws2.Aws2TestEnvCustomizer
@@ -0,0 +1 @@
+org.apache.camel.quarkus.component.aws2.lambda.it.Aws2LambdaTestEnvCustomizer
\ No newline at end of file
diff --git a/integration-tests-aws2/pom.xml b/integration-tests-aws2/pom.xml
index c20091f..9a74761 100644
--- a/integration-tests-aws2/pom.xml
+++ b/integration-tests-aws2/pom.xml
@@ -41,6 +41,7 @@
         <module>aws2-cw</module>
         <module>aws2-ddb</module>
         <module>aws2-kinesis</module>
+        <module>aws2-lambda</module>
         <module>aws2-s3</module>
         <module>aws2-sqs-sns</module>
     </modules>
diff --git a/integration-tests-support/aws2/src/main/java/org/apache/camel/quarkus/test/support/aws2/Aws2TestEnvContext.java b/integration-tests-support/aws2/src/main/java/org/apache/camel/quarkus/test/support/aws2/Aws2TestEnvContext.java
index 6167883..2d057ae 100644
--- a/integration-tests-support/aws2/src/main/java/org/apache/camel/quarkus/test/support/aws2/Aws2TestEnvContext.java
+++ b/integration-tests-support/aws2/src/main/java/org/apache/camel/quarkus/test/support/aws2/Aws2TestEnvContext.java
@@ -72,6 +72,7 @@ public class Aws2TestEnvContext {
                     case DYNAMODB:
                     case DYNAMODB_STREAMS:
                     case CLOUDWATCH:
+                    case LAMBDA:
                         // TODO https://github.com/apache/camel-quarkus/issues/2216
                         break;
                     default:
diff --git a/integration-tests/aws2-grouped/pom.xml b/integration-tests/aws2-grouped/pom.xml
index 52051e1..c7af25e 100644
--- a/integration-tests/aws2-grouped/pom.xml
+++ b/integration-tests/aws2-grouped/pom.xml
@@ -69,6 +69,10 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-aws2-lambda</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-aws2-s3</artifactId>
         </dependency>
         <dependency>
@@ -151,6 +155,19 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-aws2-lambda-deployment</artifactId>
+            <version>${project.version}</version>
+            <type>pom</type>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>*</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-aws2-s3-deployment</artifactId>
             <version>${project.version}</version>
             <type>pom</type>
diff --git a/tooling/create-extension-templates/integration-test-pom.xml b/tooling/create-extension-templates/integration-test-pom.xml
index c5eefb4..2518507 100644
--- a/tooling/create-extension-templates/integration-test-pom.xml
+++ b/tooling/create-extension-templates/integration-test-pom.xml
@@ -23,7 +23,7 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-[#if nativeSupported][=itestParentArtifactId][#else]build-parent-it[/#if]</artifactId>
+        <artifactId>[#if nativeSupported][=itestParentArtifactId][#else]camel-quarkus-build-parent-it[/#if]</artifactId>
         <version>[=version]</version>
         <relativePath>[#if nativeSupported]../pom.xml[#else]../../../poms/build-parent-it/pom.xml[/#if]</relativePath>
     </parent>