diff --git a/connectors-e2e-test/connectors-e2e-test-aws/pom.xml b/connectors-e2e-test/connectors-e2e-test-aws/pom.xml
new file mode 100644
index 0000000000..5c5f818a79
--- /dev/null
+++ b/connectors-e2e-test/connectors-e2e-test-aws/pom.xml
@@ -0,0 +1,77 @@
+
+ 4.0.0
+
+
+ io.camunda.connector
+ connector-parent
+ ../../parent/pom.xml
+ 8.4.0-SNAPSHOT
+
+
+ Tests
+ connectors-e2e-aws
+ jar
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
+
+
+ org.testcontainers
+ localstack
+ ${version.localstack}
+ test
+
+
+ com.amazonaws
+ aws-java-sdk-bom
+ ${version.aws-java-sdk}
+ pom
+ test
+
+
+ io.camunda.connector
+ connector-aws-lambda
+ ${project.version}
+ test
+
+
+
+ com.amazonaws
+ aws-lambda-java-events
+ ${version.aws-lambda-java-events}
+ test
+
+
+
+ com.amazonaws
+ aws-lambda-java-core
+ ${version.aws-lambda-java-core}
+ test
+
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+
+ io.camunda.connector
+ connectors-e2e-test-base
+ ${project.version}
+ test
+
+
+
\ No newline at end of file
diff --git a/connectors-e2e-test/connectors-e2e-test-aws/src/test/java/io/camunda/connector/e2e/AwsLambdaTest.java b/connectors-e2e-test/connectors-e2e-test-aws/src/test/java/io/camunda/connector/e2e/AwsLambdaTest.java
new file mode 100644
index 0000000000..fdacf8485c
--- /dev/null
+++ b/connectors-e2e-test/connectors-e2e-test-aws/src/test/java/io/camunda/connector/e2e/AwsLambdaTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
+ * under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. Camunda licenses this file to you under the Apache License,
+ * Version 2.0; 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 io.camunda.connector.e2e;
+
+import static io.camunda.zeebe.process.test.assertions.BpmnAssert.assertThat;
+
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.client.builder.AwsClientBuilder;
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
+import io.camunda.connector.aws.ObjectMapperSupplier;
+import io.camunda.zeebe.model.bpmn.Bpmn;
+import java.io.File;
+import java.io.IOException;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class AwsLambdaTest extends BaseAwsTest {
+
+ protected static final String ELEMENT_TEMPLATE_PATH =
+ "../../connectors/aws/aws-lambda/element-templates/aws-lambda-outbound-connector.json";
+ private static final String FUNCTION_NAME = "myLambdaFunction";
+ private static final String LAMBDA_FUNCTION_ZIP_FILE_PATH = "src/test/resources/function.zip";
+
+ private static AWSLambda lambdaClient;
+
+ /** Initializes the AWS Lambda client and sets up the Lambda function for testing. */
+ @BeforeAll
+ public static void initLambdaClient() throws IOException, InterruptedException {
+
+ lambdaClient =
+ AWSLambdaClientBuilder.standard()
+ .withCredentials(
+ new AWSStaticCredentialsProvider(
+ new BasicAWSCredentials(localstack.getAccessKey(), localstack.getSecretKey())))
+ .withEndpointConfiguration(
+ new AwsClientBuilder.EndpointConfiguration(
+ localstack.getEndpoint().toString(), localstack.getRegion()))
+ .build();
+
+ AwsLambdaTestHelper.waitForLambdaClientInitialization(lambdaClient);
+ AwsLambdaTestHelper.initializeLambdaFunction(
+ lambdaClient, LAMBDA_FUNCTION_ZIP_FILE_PATH, FUNCTION_NAME);
+ AwsLambdaTestHelper.waitForLambdaFunctionToBeReady(lambdaClient, FUNCTION_NAME);
+ }
+
+ @AfterAll
+ public static void cleanUpLambdaClient() {
+ if (lambdaClient != null) {
+ lambdaClient.shutdown();
+ }
+ }
+
+ /**
+ * Tests the integration of AWS Lambda within a Camunda BPMN process. This test deploys a BPMN
+ * model with a Lambda service task and asserts the execution results.
+ *
+ * @throws Exception if any exception occurs during the test execution
+ */
+ @Test
+ public void testLambdaFunction() throws Exception {
+
+ var model = Bpmn.createProcess().executable().startEvent().serviceTask("aws").endEvent().done();
+
+ var elementTemplate =
+ ElementTemplate.from(ELEMENT_TEMPLATE_PATH)
+ .property("authentication.type", "credentials")
+ .property("authentication.accessKey", localstack.getAccessKey())
+ .property("authentication.secretKey", localstack.getSecretKey())
+ .property("configuration.region", localstack.getRegion())
+ .property("awsFunction.operationType", "sync")
+ .property("awsFunction.functionName", FUNCTION_NAME)
+ .property("awsFunction.payload", "str")
+ .property("retryCount", "0")
+ .property("awsFunction.payload", "str")
+ .property("resultExpression", "={response: payload}")
+ .property("configuration.endpoint", localstack.getEndpoint().toString())
+ .writeTo(new File(tempDir, "template.json"));
+
+ var updatedModel =
+ new BpmnFile(model)
+ .writeToFile(new File(tempDir, "test.bpmn"))
+ .apply(elementTemplate, "aws", new File(tempDir, "result.bpmn"));
+
+ var bpmnTest =
+ ZeebeTest.with(zeebeClient)
+ .deploy(updatedModel)
+ .createInstance()
+ .waitForProcessCompletion();
+
+ Object expectedResult =
+ ObjectMapperSupplier.getMapperInstance()
+ .readValue(
+ "{\"statusCode\":200,\"body\":\"{\\\"message\\\": \\\"Hello from your Python Lambda function!\\\", \\\"receivedEvent\\\": \\\"str\\\"}\"}",
+ Object.class);
+ assertThat(bpmnTest.getProcessInstanceEvent()).hasVariableWithValue("response", expectedResult);
+ }
+}
diff --git a/connectors-e2e-test/connectors-e2e-test-aws/src/test/java/io/camunda/connector/e2e/AwsLambdaTestHelper.java b/connectors-e2e-test/connectors-e2e-test-aws/src/test/java/io/camunda/connector/e2e/AwsLambdaTestHelper.java
new file mode 100644
index 0000000000..d863a8458c
--- /dev/null
+++ b/connectors-e2e-test/connectors-e2e-test-aws/src/test/java/io/camunda/connector/e2e/AwsLambdaTestHelper.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
+ * under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. Camunda licenses this file to you under the Apache License,
+ * Version 2.0; 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 io.camunda.connector.e2e;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.CreateFunctionRequest;
+import com.amazonaws.services.lambda.model.DeleteFunctionRequest;
+import com.amazonaws.services.lambda.model.FunctionCode;
+import com.amazonaws.services.lambda.model.GetFunctionRequest;
+import com.amazonaws.services.lambda.model.GetFunctionResult;
+import com.amazonaws.services.lambda.model.ResourceNotFoundException;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testcontainers.containers.localstack.LocalStackContainer;
+
+/**
+ * Utility class providing helper methods for setting up and managing AWS Lambda and LocalStack in
+ * the context of end-to-end testing.
+ */
+public class AwsLambdaTestHelper {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AwsLambdaTestHelper.class);
+
+ /**
+ * Waits for LocalStack to become operational. Checks periodically if LocalStack is healthy.
+ * Throws a runtime exception if LocalStack does not become healthy within the timeout period.
+ *
+ * @param localstack The LocalStack container instance.
+ * @throws InterruptedException if the waiting thread is interrupted.
+ */
+ static void waitForLocalStackToBeHealthy(LocalStackContainer localstack)
+ throws InterruptedException {
+ long startTime = System.currentTimeMillis();
+ long maxDurationMillis = 60000; // 1 minute
+ boolean isHealthy = false;
+
+ while (System.currentTimeMillis() - startTime < maxDurationMillis) {
+ if (localstack.isCreated() && localstack.isHealthy() && localstack.isRunning()) {
+ isHealthy = true;
+ break;
+ }
+ Thread.sleep(500); // Wait for 1 second before checking again
+ }
+
+ if (!isHealthy) {
+ throw new RuntimeException(
+ "LocalStack did not become healthy within the expected time. "
+ + "Status: created = "
+ + localstack.isCreated()
+ + ", healthy = "
+ + localstack.isHealthy()
+ + ", running = "
+ + localstack.isRunning());
+ }
+ }
+
+ /**
+ * Waits for the AWS Lambda client to be initialized. This method periodically checks if the
+ * Lambda client is ready by attempting to list functions. If it doesn't initialize within the
+ * specified timeout, a runtime exception is thrown.
+ *
+ * @param lambdaClient The AWS Lambda client.
+ * @throws InterruptedException if the waiting thread is interrupted.
+ */
+ static void waitForLambdaClientInitialization(final AWSLambda lambdaClient)
+ throws InterruptedException {
+ long startTime = System.currentTimeMillis();
+ long maxDurationMillis = 30000; // 30 seconds
+ while (System.currentTimeMillis() - startTime < maxDurationMillis) {
+ try {
+ lambdaClient.listFunctions(); // Check if Lambda client is ready
+ return; // If the request succeeds, exit the method
+ } catch (Exception e) {
+ // Log the exception or handle it as necessary
+ }
+ Thread.sleep(100); // Wait for 100 milliseconds before retrying
+ }
+ throw new RuntimeException("Lambda client did not initialize within the expected time.");
+ }
+
+ /**
+ * Initializes the Lambda function for testing. This includes checking if the function already
+ * exists and deleting it if so, then creating a new function using the provided ZIP file path.
+ *
+ * @param lambdaClient The AWS Lambda client.
+ * @param lambdaFunctionZipFilePath The file path to the ZIP file containing the Lambda function
+ * code.
+ * @param functionName The name of the Lambda function to be created.
+ * @throws IOException if an error occurs during file operations.
+ */
+ static void initializeLambdaFunction(
+ final AWSLambda lambdaClient,
+ final String lambdaFunctionZipFilePath,
+ final String functionName)
+ throws IOException {
+ try {
+ lambdaClient.getFunction(new GetFunctionRequest().withFunctionName(functionName));
+ LOGGER.info("Function already exists, deleting: " + functionName);
+ lambdaClient.deleteFunction(new DeleteFunctionRequest().withFunctionName(functionName));
+ } catch (ResourceNotFoundException e) {
+ LOGGER.info("Function does not exist, no need to delete: " + functionName);
+ }
+
+ File zipFile = Paths.get(lambdaFunctionZipFilePath).toFile();
+ CreateFunctionRequest functionRequest =
+ new CreateFunctionRequest()
+ .withFunctionName("myLambdaFunction")
+ .withRuntime("python3.9")
+ .withRole("arn:aws:iam::000000000000:role/lambda-execute")
+ .withHandler("lambda_function.lambda_handler")
+ .withCode(
+ new FunctionCode()
+ .withZipFile(ByteBuffer.wrap(Files.readAllBytes(zipFile.toPath()))));
+
+ lambdaClient.createFunction(functionRequest);
+ }
+
+ /**
+ * Waits for the specified Lambda function to be ready for invocation. This method checks the
+ * function's state and waits until it becomes 'Active'. A runtime exception is thrown if the
+ * function is not ready within the number of attempts.
+ *
+ * @param lambdaClient The AWS Lambda client.
+ * @param functionName The name of the Lambda function to check.
+ * @throws InterruptedException if the waiting thread is interrupted.
+ */
+ static void waitForLambdaFunctionToBeReady(
+ final AWSLambda lambdaClient, final String functionName) throws InterruptedException {
+ LOGGER.info("Waiting for Lambda function to be ready...");
+ int attempts = 30;
+
+ while (attempts > 0) {
+ try {
+ GetFunctionResult function =
+ lambdaClient.getFunction(new GetFunctionRequest().withFunctionName(functionName));
+ if (function.getConfiguration().getState().equals("Active")) {
+ LOGGER.info("Lambda function is ready for invocation.");
+ return;
+ }
+ } catch (ResourceNotFoundException e) {
+ LOGGER.info("Lambda function does not exist yet. Waiting...");
+ }
+ Thread.sleep(1000); // Wait for 1 second before retrying
+ attempts--;
+ }
+ throw new RuntimeException("Lambda function is not ready after waiting.");
+ }
+
+ /**
+ * Removes Lambda Docker containers that are not automatically cleaned up. This method is a
+ * workaround to ensure that all related Docker containers are stopped and removed.
+ */
+ static void removeLambdaContainers() {
+ try {
+ // Assuming 'docker' command is available on the path
+ ProcessBuilder builder = new ProcessBuilder();
+
+ // List all containers using the specific Lambda image
+ builder.command(
+ "docker", "ps", "-a", "-q", "--filter", "ancestor=public.ecr.aws/lambda/python:3.9");
+ Process process = builder.start();
+ List containerIds =
+ new BufferedReader(new InputStreamReader(process.getInputStream())).lines().toList();
+ process.waitFor();
+
+ // Stop and remove containers
+ for (String containerId : containerIds) {
+ LOGGER.info("Stopping and removing container: " + containerId);
+ // Stop container
+ new ProcessBuilder("docker", "stop", containerId).start().waitFor();
+ // Remove container
+ new ProcessBuilder("docker", "rm", containerId).start().waitFor();
+ }
+ } catch (IOException | InterruptedException e) {
+ LOGGER.error("Failed to stop and remove Lambda containers", e);
+ }
+ }
+}
diff --git a/connectors-e2e-test/connectors-e2e-test-aws/src/test/java/io/camunda/connector/e2e/BaseAwsTest.java b/connectors-e2e-test/connectors-e2e-test-aws/src/test/java/io/camunda/connector/e2e/BaseAwsTest.java
new file mode 100644
index 0000000000..1d820781dc
--- /dev/null
+++ b/connectors-e2e-test/connectors-e2e-test-aws/src/test/java/io/camunda/connector/e2e/BaseAwsTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
+ * under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. Camunda licenses this file to you under the Apache License,
+ * Version 2.0; 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 io.camunda.connector.e2e;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.testcontainers.containers.localstack.LocalStackContainer.Service.LAMBDA;
+
+import io.camunda.connector.e2e.app.TestConnectorRuntimeApplication;
+import io.camunda.connector.runtime.inbound.importer.ProcessDefinitionSearch;
+import io.camunda.operate.CamundaOperateClient;
+import io.camunda.zeebe.client.ZeebeClient;
+import io.camunda.zeebe.spring.test.ZeebeSpringTest;
+import java.io.File;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.testcontainers.containers.localstack.LocalStackContainer;
+import org.testcontainers.utility.DockerImageName;
+
+@SpringBootTest(
+ classes = {TestConnectorRuntimeApplication.class},
+ properties = {
+ "spring.main.allow-bean-definition-overriding=true",
+ "camunda.connector.webhook.enabled=false",
+ "camunda.connector.polling.enabled=false"
+ },
+ webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ZeebeSpringTest
+@ExtendWith(MockitoExtension.class)
+public abstract class BaseAwsTest {
+ private static final DockerImageName localstackImage =
+ DockerImageName.parse("localstack/localstack");
+ @TempDir File tempDir;
+ @Autowired ZeebeClient zeebeClient;
+ @MockBean ProcessDefinitionSearch processDefinitionSearch;
+ @Autowired CamundaOperateClient camundaOperateClient;
+
+ static LocalStackContainer localstack;
+
+ /**
+ * Initializes the LocalStack container with required services before executing any tests. This
+ * simulates the AWS environment for integration testing.
+ *
+ * @throws InterruptedException if the thread is interrupted during LocalStack container startup.
+ */
+ @BeforeAll
+ static void initializeLocalStackContainer() throws InterruptedException {
+
+ localstack =
+ new LocalStackContainer(localstackImage)
+ .withServices(LAMBDA)
+ .withEnv("DEFAULT_REGION", "us-east-1")
+ .withEnv("AWS_ACCESS_KEY_ID", "myTestAccessKey")
+ .withEnv("AWS_SECRET_ACCESS_KEY", "myTestSecretKey")
+ .withEnv("LAMBDA_RUNTIME_ENVIRONMENT_TIMEOUT", "30");
+ localstack.start();
+
+ AwsLambdaTestHelper.waitForLocalStackToBeHealthy(localstack);
+ }
+
+ @BeforeEach
+ void beforeEach() {
+ doNothing().when(processDefinitionSearch).query(any());
+ }
+
+ /** Stops the LocalStack container and cleans up any associated resources. */
+ @AfterAll
+ public static void cleanUpAfterTests() {
+ localstack.stop();
+ AwsLambdaTestHelper.removeLambdaContainers();
+ }
+}
diff --git a/connectors-e2e-test/connectors-e2e-test-aws/src/test/resources/function.zip b/connectors-e2e-test/connectors-e2e-test-aws/src/test/resources/function.zip
new file mode 100644
index 0000000000..c016038780
Binary files /dev/null and b/connectors-e2e-test/connectors-e2e-test-aws/src/test/resources/function.zip differ
diff --git a/connectors-e2e-test/connectors-e2e-test-aws/src/test/resources/lambda_function.py b/connectors-e2e-test/connectors-e2e-test-aws/src/test/resources/lambda_function.py
new file mode 100644
index 0000000000..cda547efab
--- /dev/null
+++ b/connectors-e2e-test/connectors-e2e-test-aws/src/test/resources/lambda_function.py
@@ -0,0 +1,11 @@
+import json
+# for test need to compile this in zip : `zip function.zip lambda_function.py`
+def lambda_handler(event, context):
+ response_body = {
+ 'message': 'Hello from your Python Lambda function!',
+ 'receivedEvent': event
+ }
+
+ return {
+ json.dumps(response_body)
+ }
\ No newline at end of file
diff --git a/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/AwsConfiguration.java b/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/AwsConfiguration.java
index b69f312a1a..1623ab5924 100644
--- a/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/AwsConfiguration.java
+++ b/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/AwsConfiguration.java
@@ -8,4 +8,6 @@
public interface AwsConfiguration {
String region();
+
+ String endpoint();
}
diff --git a/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsAuthentication.java b/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsAuthentication.java
index 90f4df6721..f54541ac66 100644
--- a/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsAuthentication.java
+++ b/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsAuthentication.java
@@ -10,6 +10,9 @@
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.camunda.connector.aws.model.impl.AwsAuthentication.AwsDefaultCredentialsChainAuthentication;
import io.camunda.connector.aws.model.impl.AwsAuthentication.AwsStaticCredentialsAuthentication;
+import io.camunda.connector.generator.java.annotation.TemplateDiscriminatorProperty;
+import io.camunda.connector.generator.java.annotation.TemplateProperty;
+import io.camunda.connector.generator.java.annotation.TemplateSubType;
import jakarta.validation.constraints.NotBlank;
// Note on `defaultImpl`. This is left for backwards compatibility
@@ -24,10 +27,35 @@
value = AwsDefaultCredentialsChainAuthentication.class,
name = "defaultCredentialsChain"),
})
+@TemplateDiscriminatorProperty(
+ label = "Authentication",
+ group = "authentication",
+ name = "type",
+ defaultValue = "credentials",
+ description =
+ "Specify AWS authentication strategy. Learn more at the documentation page")
public sealed interface AwsAuthentication
permits AwsDefaultCredentialsChainAuthentication, AwsStaticCredentialsAuthentication {
- record AwsDefaultCredentialsChainAuthentication() implements AwsAuthentication {}
-
- record AwsStaticCredentialsAuthentication(@NotBlank String accessKey, @NotBlank String secretKey)
+ @TemplateSubType(id = "credentials", label = "Credentials")
+ record AwsStaticCredentialsAuthentication(
+ @TemplateProperty(
+ group = "authentication",
+ label = "Access key",
+ description =
+ "Provide an access key of a user with permissions to invoke specified AWS Lambda function")
+ @NotBlank
+ String accessKey,
+ @TemplateProperty(
+ group = "authentication",
+ label = "Secret key",
+ description =
+ "Provide a secret key of a user with permissions to invoke specified AWS Lambda function")
+ @NotBlank
+ String secretKey)
implements AwsAuthentication {}
+
+ @TemplateSubType(
+ id = "defaultCredentialsChain",
+ label = "Default Credentials Chain (Hybrid/Self-Managed only)")
+ record AwsDefaultCredentialsChainAuthentication() implements AwsAuthentication {}
}
diff --git a/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsBaseConfiguration.java b/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsBaseConfiguration.java
index 7d9cdb8898..818934bc78 100644
--- a/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsBaseConfiguration.java
+++ b/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsBaseConfiguration.java
@@ -7,5 +7,18 @@
package io.camunda.connector.aws.model.impl;
import io.camunda.connector.aws.model.AwsConfiguration;
+import io.camunda.connector.generator.java.annotation.TemplateProperty;
-public record AwsBaseConfiguration(String region) implements AwsConfiguration {}
+public record AwsBaseConfiguration(
+ @TemplateProperty(
+ group = "configuration",
+ description = "Specify the AWS region",
+ optional = true)
+ String region,
+ @TemplateProperty(
+ group = "configuration",
+ description = "Specify endpoint if need to use custom endpoint",
+ type = TemplateProperty.PropertyType.Hidden,
+ optional = true)
+ String endpoint)
+ implements AwsConfiguration {}
diff --git a/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsBaseRequest.java b/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsBaseRequest.java
index 36ccf664fa..19b86fa1bc 100644
--- a/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsBaseRequest.java
+++ b/connectors/aws/aws-base/src/main/java/io/camunda/connector/aws/model/impl/AwsBaseRequest.java
@@ -6,14 +6,19 @@
*/
package io.camunda.connector.aws.model.impl;
+import io.camunda.connector.generator.java.annotation.TemplateProperty;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.Objects;
public class AwsBaseRequest {
- @Valid @NotNull private AwsAuthentication authentication;
+ @TemplateProperty(group = "authentication", id = "type")
+ @Valid
+ @NotNull
+ private AwsAuthentication authentication;
+ @TemplateProperty(group = "configuration")
private AwsBaseConfiguration configuration;
public AwsAuthentication getAuthentication() {
diff --git a/connectors/aws/aws-lambda/README.md b/connectors/aws/aws-lambda/README.md
index b3c4bd79fd..3dd3e04f81 100644
--- a/connectors/aws/aws-lambda/README.md
+++ b/connectors/aws/aws-lambda/README.md
@@ -45,4 +45,4 @@ mvn clean package
## Element Template
-The element templates can be found in the [element-templates/aws-lambda-connector.json](element-templates/aws-lambda-connector.json) file.
+The element templates can be found in the [element-templates/aws-lambda-outbound-connector.json](element-templates/aws-lambda-outbound-connector.json) file.
diff --git a/connectors/aws/aws-lambda/element-templates/aws-lambda-connector.json b/connectors/aws/aws-lambda/element-templates/aws-lambda-connector.json
deleted file mode 100644
index 19362afbdf..0000000000
--- a/connectors/aws/aws-lambda/element-templates/aws-lambda-connector.json
+++ /dev/null
@@ -1,218 +0,0 @@
-{
- "$schema": "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json",
- "name": "AWS Lambda Outbound Connector",
- "id": "io.camunda.connectors.AWSLAMBDA.v2",
- "version": 4,
- "description": "Invoke a function",
- "documentationRef": "https://docs.camunda.io/docs/components/connectors/out-of-the-box-connectors/aws-lambda/",
- "category": {
- "id": "connectors",
- "name": "Connectors"
- },
- "appliesTo": [
- "bpmn:Task"
- ],
- "elementType": {
- "value": "bpmn:ServiceTask"
- },
- "groups": [
- {
- "id": "authentication",
- "label": "Authentication"
- },
- {
- "id": "configuration",
- "label": "Configuration"
- },
- {
- "id": "operation",
- "label": "Select operation"
- },
- {
- "id": "operationDetails",
- "label": "Operation details"
- },
- {
- "id": "output",
- "label": "Output mapping"
- },
- {
- "id": "errors",
- "label": "Error handling"
- }
- ],
- "properties": [
- {
- "type": "Hidden",
- "value": "io.camunda:aws-lambda:1",
- "binding": {
- "type": "zeebe:taskDefinition:type"
- }
- },
- {
- "id": "authenticationType",
- "label": "Authentication",
- "description": "Specify AWS authentication strategy. Learn more at the documentation page",
- "group": "authentication",
- "type": "Dropdown",
- "optional": false,
- "value": "credentials",
- "choices": [
- {
- "name": "Credentials",
- "value": "credentials"
- },
- {
- "name": "Default Credentials Chain (Hybrid/Self-Managed only)",
- "value": "defaultCredentialsChain"
- }
- ],
- "binding": {
- "type": "zeebe:input",
- "name": "authentication.type"
- },
- "constraints": {
- "notEmpty": true
- }
- },
- {
- "label": "Access key",
- "description": "Provide an access key of a user with permissions to invoke specified AWS Lambda function",
- "group": "authentication",
- "type": "String",
- "binding": {
- "type": "zeebe:input",
- "name": "authentication.accessKey"
- },
- "constraints": {
- "notEmpty": true
- },
- "condition": {
- "property": "authenticationType",
- "equals": "credentials"
- }
- },
- {
- "label": "Secret key",
- "description": "Provide a secret key of a user with permissions to invoke specified AWS Lambda function",
- "group": "authentication",
- "type": "String",
- "binding": {
- "type": "zeebe:input",
- "name": "authentication.secretKey"
- },
- "constraints": {
- "notEmpty": true
- },
- "condition": {
- "property": "authenticationType",
- "equals": "credentials"
- }
- },
- {
- "label": "Region",
- "description": "Specify the AWS region",
- "group": "configuration",
- "type": "String",
- "feel": "optional",
- "binding": {
- "type": "zeebe:input",
- "name": "configuration.region"
- },
- "constraints": {
- "notEmpty": true,
- "maxLength": 255
- }
- },
- {
- "id": "operationType",
- "group": "operation",
- "type": "Dropdown",
- "value": "sync",
- "choices": [
- {
- "name": "Invoke function (sync)",
- "value": "sync"
- }
- ],
- "binding": {
- "type": "zeebe:input",
- "name": "awsFunction.operationType",
- "key": "awsFunction.operationType"
- }
- },
- {
- "label": "Function name",
- "description": "Enter a name, ARN or alias of your function",
- "group": "operationDetails",
- "type": "String",
- "feel": "optional",
- "binding": {
- "type": "zeebe:input",
- "name": "awsFunction.functionName"
- },
- "constraints": {
- "notEmpty": true,
- "maxLength": 255
- },
- "condition": {
- "property": "operationType",
- "equals": "sync"
- }
- },
- {
- "label": "Payload",
- "description": "Provide payload for your function as JSON",
- "group": "operationDetails",
- "type": "Text",
- "feel": "required",
- "optional": false,
- "binding": {
- "type": "zeebe:input",
- "name": "awsFunction.payload"
- },
- "constraints": {
- "notEmpty": true
- },
- "condition": {
- "property": "operationType",
- "equals": "sync"
- }
- },
- {
- "label": "Result variable",
- "description": "Enter name of variable to store the response in. Details in the documentation",
- "group": "output",
- "type": "String",
- "binding": {
- "type": "zeebe:taskHeader",
- "key": "resultVariable"
- }
- },
- {
- "label": "Result expression",
- "description": "Expression to map the response into process variables. Details in the documentation",
- "group": "output",
- "type": "Text",
- "feel": "required",
- "binding": {
- "type": "zeebe:taskHeader",
- "key": "resultExpression"
- }
- },
- {
- "label": "Error expression",
- "description": "Expression to handle errors. Details in the documentation",
- "group": "errors",
- "type": "Text",
- "feel": "required",
- "binding": {
- "type": "zeebe:taskHeader",
- "key": "errorExpression"
- }
- }
- ],
- "icon": {
- "contents": "data:image/svg+xml;utf8,%3Csvg width='18' height='18' viewBox='0 0 48 48' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Ctitle%3EIcon-Resource/Compute/Res_Amazon-Lambda_Lambda-Function_48_Light%3C/title%3E%3Cg id='Icon-Resource/Compute/Res_Amazon-Lambda_Lambda-Function_48' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cpath d='M24,44 C12.972,44 4,35.028 4,24 C4,12.972 12.972,4 24,4 C35.028,4 44,12.972 44,24 C44,35.028 35.028,44 24,44 L24,44 Z M24,2 C11.869,2 2,11.869 2,24 C2,36.131 11.869,46 24,46 C36.131,46 46,36.131 46,24 C46,11.869 36.131,2 24,2 L24,2 Z M17.231,35.25 L11.876,35.25 L18.221,21.959 L20.902,27.492 L17.231,35.25 Z M19.114,19.215 C18.946,18.87 18.597,18.651 18.214,18.651 L18.211,18.651 C17.826,18.652 17.477,18.874 17.312,19.221 L9.389,35.819 C9.24,36.129 9.262,36.493 9.445,36.783 C9.628,37.074 9.947,37.25 10.291,37.25 L17.864,37.25 C18.251,37.25 18.603,37.027 18.769,36.678 L22.915,27.915 C23.044,27.642 23.043,27.323 22.911,27.051 L19.114,19.215 Z M36.125,35.25 L30.673,35.25 L20.761,13.953 C20.597,13.601 20.243,13.375 19.854,13.375 L16.251,13.375 L16.255,9.25 L23.475,9.25 L33.339,30.545 C33.503,30.898 33.856,31.125 34.246,31.125 L36.125,31.125 L36.125,35.25 Z M37.125,29.125 L34.885,29.125 L25.021,7.83 C24.856,7.477 24.503,7.25 24.113,7.25 L15.256,7.25 C14.704,7.25 14.257,7.697 14.256,8.249 L14.25,14.374 C14.25,14.64 14.355,14.894 14.543,15.082 C14.73,15.27 14.984,15.375 15.25,15.375 L19.217,15.375 L29.129,36.672 C29.293,37.024 29.646,37.25 30.035,37.25 L37.125,37.25 C37.678,37.25 38.125,36.803 38.125,36.25 L38.125,30.125 C38.125,29.572 37.678,29.125 37.125,29.125 L37.125,29.125 Z' id='Amazon-Lambda-Lambda-Function_Resource-Icon_light-bg' fill='%23D45B07'%3E%3C/path%3E%3C/g%3E%3C/svg%3E"
- }
-}
diff --git a/connectors/aws/aws-lambda/element-templates/aws-lambda-outbound-connector.json b/connectors/aws/aws-lambda/element-templates/aws-lambda-outbound-connector.json
new file mode 100644
index 0000000000..631f27475a
--- /dev/null
+++ b/connectors/aws/aws-lambda/element-templates/aws-lambda-outbound-connector.json
@@ -0,0 +1,232 @@
+{
+ "$schema" : "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json",
+ "name" : "AWS Lambda Outbound Connector",
+ "id" : "io.camunda.connectors.AWSLAMBDA.v2",
+ "description" : "Invoke a function",
+ "documentationRef" : "https://docs.camunda.io/docs/components/connectors/out-of-the-box-connectors/aws-lambda/",
+ "version" : 5,
+ "category" : {
+ "id" : "connectors",
+ "name" : "Connectors"
+ },
+ "appliesTo" : [ "bpmn:Task" ],
+ "elementType" : {
+ "value" : "bpmn:ServiceTask"
+ },
+ "groups" : [ {
+ "id" : "authentication",
+ "label" : "Authentication"
+ }, {
+ "id" : "configuration",
+ "label" : "Configuration"
+ }, {
+ "id" : "operation",
+ "label" : "Select operation"
+ }, {
+ "id" : "operationDetails",
+ "label" : "Operation details"
+ }, {
+ "id" : "output",
+ "label" : "Output mapping"
+ }, {
+ "id" : "error",
+ "label" : "Error handling"
+ }, {
+ "id" : "retries",
+ "label" : "Retries"
+ } ],
+ "properties" : [ {
+ "value" : "io.camunda:aws-lambda:1",
+ "binding" : {
+ "property" : "type",
+ "type" : "zeebe:taskDefinition"
+ },
+ "type" : "Hidden"
+ }, {
+ "id" : "authentication.type",
+ "label" : "Authentication",
+ "description" : "Specify AWS authentication strategy. Learn more at the documentation page",
+ "value" : "credentials",
+ "group" : "authentication",
+ "binding" : {
+ "name" : "authentication.type",
+ "type" : "zeebe:input"
+ },
+ "type" : "Dropdown",
+ "choices" : [ {
+ "name" : "Default Credentials Chain (Hybrid/Self-Managed only)",
+ "value" : "defaultCredentialsChain"
+ }, {
+ "name" : "Credentials",
+ "value" : "credentials"
+ } ]
+ }, {
+ "id" : "authentication.accessKey",
+ "label" : "Access key",
+ "description" : "Provide an access key of a user with permissions to invoke specified AWS Lambda function",
+ "optional" : false,
+ "constraints" : {
+ "notEmpty" : true
+ },
+ "feel" : "optional",
+ "group" : "authentication",
+ "binding" : {
+ "name" : "authentication.accessKey",
+ "type" : "zeebe:input"
+ },
+ "condition" : {
+ "property" : "authentication.type",
+ "equals" : "credentials",
+ "type" : "simple"
+ },
+ "type" : "String"
+ }, {
+ "id" : "authentication.secretKey",
+ "label" : "Secret key",
+ "description" : "Provide a secret key of a user with permissions to invoke specified AWS Lambda function",
+ "optional" : false,
+ "constraints" : {
+ "notEmpty" : true
+ },
+ "feel" : "optional",
+ "group" : "authentication",
+ "binding" : {
+ "name" : "authentication.secretKey",
+ "type" : "zeebe:input"
+ },
+ "condition" : {
+ "property" : "authentication.type",
+ "equals" : "credentials",
+ "type" : "simple"
+ },
+ "type" : "String"
+ }, {
+ "id" : "configuration.region",
+ "label" : "Region",
+ "description" : "Specify the AWS region",
+ "optional" : true,
+ "feel" : "optional",
+ "group" : "configuration",
+ "binding" : {
+ "name" : "configuration.region",
+ "type" : "zeebe:input"
+ },
+ "type" : "String"
+ }, {
+ "id" : "configuration.endpoint",
+ "label" : "Endpoint",
+ "description" : "Specify endpoint if need to use custom endpoint",
+ "optional" : true,
+ "feel" : "optional",
+ "group" : "configuration",
+ "binding" : {
+ "name" : "configuration.endpoint",
+ "type" : "zeebe:input"
+ },
+ "type" : "Hidden"
+ }, {
+ "id" : "awsFunction.operationType",
+ "label" : "Operation type",
+ "optional" : false,
+ "value" : "sync",
+ "group" : "operation",
+ "binding" : {
+ "name" : "awsFunction.operationType",
+ "type" : "zeebe:input"
+ },
+ "type" : "Dropdown",
+ "choices" : [ {
+ "name" : "Invoke function (sync)",
+ "value" : "sync"
+ } ]
+ }, {
+ "id" : "awsFunction.functionName",
+ "label" : "Function name",
+ "description" : "Enter a name, ARN or alias of your function",
+ "optional" : false,
+ "constraints" : {
+ "notEmpty" : true
+ },
+ "feel" : "optional",
+ "group" : "operationDetails",
+ "binding" : {
+ "name" : "awsFunction.functionName",
+ "type" : "zeebe:input"
+ },
+ "type" : "String"
+ }, {
+ "id" : "awsFunction.payload",
+ "label" : "Payload",
+ "description" : "Provide payload for your function as JSON",
+ "optional" : false,
+ "constraints" : {
+ "notEmpty" : true
+ },
+ "feel" : "optional",
+ "group" : "operationDetails",
+ "binding" : {
+ "name" : "awsFunction.payload",
+ "type" : "zeebe:input"
+ },
+ "type" : "Text"
+ }, {
+ "id" : "resultVariable",
+ "label" : "Result variable",
+ "description" : "Name of variable to store the response in",
+ "group" : "output",
+ "binding" : {
+ "key" : "resultVariable",
+ "type" : "zeebe:taskHeader"
+ },
+ "type" : "String"
+ }, {
+ "id" : "resultExpression",
+ "label" : "Result expression",
+ "description" : "Expression to map the response into process variables",
+ "feel" : "required",
+ "group" : "output",
+ "binding" : {
+ "key" : "resultExpression",
+ "type" : "zeebe:taskHeader"
+ },
+ "type" : "Text"
+ }, {
+ "id" : "errorExpression",
+ "label" : "Error expression",
+ "description" : "Expression to handle errors. Details in the documentation.",
+ "feel" : "required",
+ "group" : "error",
+ "binding" : {
+ "key" : "errorExpression",
+ "type" : "zeebe:taskHeader"
+ },
+ "type" : "Text"
+ }, {
+ "id" : "retryCount",
+ "label" : "Retries",
+ "description" : "Number of retries",
+ "value" : "3",
+ "feel" : "optional",
+ "group" : "retries",
+ "binding" : {
+ "property" : "retries",
+ "type" : "zeebe:taskDefinition"
+ },
+ "type" : "String"
+ }, {
+ "id" : "retryBackoff",
+ "label" : "Retry backoff",
+ "description" : "ISO-8601 duration to wait between retries",
+ "value" : "PT0S",
+ "feel" : "optional",
+ "group" : "retries",
+ "binding" : {
+ "key" : "retryBackoff",
+ "type" : "zeebe:taskHeader"
+ },
+ "type" : "String"
+ } ],
+ "icon" : {
+ "contents" : "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nMTgnIGhlaWdodD0nMTgnIHZpZXdCb3g9JzAgMCA0OCA0OCcgdmVyc2lvbj0nMS4xJyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnCiAgICAgeG1sbnM6eGxpbms9J2h0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsnPgogICAgPHRpdGxlPkljb24tUmVzb3VyY2UvQ29tcHV0ZS9SZXNfQW1hem9uLUxhbWJkYV9MYW1iZGEtRnVuY3Rpb25fNDhfTGlnaHQ8L3RpdGxlPgogICAgPGcgaWQ9J0ljb24tUmVzb3VyY2UvQ29tcHV0ZS9SZXNfQW1hem9uLUxhbWJkYV9MYW1iZGEtRnVuY3Rpb25fNDgnIHN0cm9rZT0nbm9uZScgc3Ryb2tlLXdpZHRoPScxJyBmaWxsPSdub25lJwogICAgICAgZmlsbC1ydWxlPSdldmVub2RkJz4KICAgICAgICA8cGF0aCBkPSdNMjQsNDQgQzEyLjk3Miw0NCA0LDM1LjAyOCA0LDI0IEM0LDEyLjk3MiAxMi45NzIsNCAyNCw0IEMzNS4wMjgsNCA0NCwxMi45NzIgNDQsMjQgQzQ0LDM1LjAyOCAzNS4wMjgsNDQgMjQsNDQgTDI0LDQ0IFogTTI0LDIgQzExLjg2OSwyIDIsMTEuODY5IDIsMjQgQzIsMzYuMTMxIDExLjg2OSw0NiAyNCw0NiBDMzYuMTMxLDQ2IDQ2LDM2LjEzMSA0NiwyNCBDNDYsMTEuODY5IDM2LjEzMSwyIDI0LDIgTDI0LDIgWiBNMTcuMjMxLDM1LjI1IEwxMS44NzYsMzUuMjUgTDE4LjIyMSwyMS45NTkgTDIwLjkwMiwyNy40OTIgTDE3LjIzMSwzNS4yNSBaIE0xOS4xMTQsMTkuMjE1IEMxOC45NDYsMTguODcgMTguNTk3LDE4LjY1MSAxOC4yMTQsMTguNjUxIEwxOC4yMTEsMTguNjUxIEMxNy44MjYsMTguNjUyIDE3LjQ3NywxOC44NzQgMTcuMzEyLDE5LjIyMSBMOS4zODksMzUuODE5IEM5LjI0LDM2LjEyOSA5LjI2MiwzNi40OTMgOS40NDUsMzYuNzgzIEM5LjYyOCwzNy4wNzQgOS45NDcsMzcuMjUgMTAuMjkxLDM3LjI1IEwxNy44NjQsMzcuMjUgQzE4LjI1MSwzNy4yNSAxOC42MDMsMzcuMDI3IDE4Ljc2OSwzNi42NzggTDIyLjkxNSwyNy45MTUgQzIzLjA0NCwyNy42NDIgMjMuMDQzLDI3LjMyMyAyMi45MTEsMjcuMDUxIEwxOS4xMTQsMTkuMjE1IFogTTM2LjEyNSwzNS4yNSBMMzAuNjczLDM1LjI1IEwyMC43NjEsMTMuOTUzIEMyMC41OTcsMTMuNjAxIDIwLjI0MywxMy4zNzUgMTkuODU0LDEzLjM3NSBMMTYuMjUxLDEzLjM3NSBMMTYuMjU1LDkuMjUgTDIzLjQ3NSw5LjI1IEwzMy4zMzksMzAuNTQ1IEMzMy41MDMsMzAuODk4IDMzLjg1NiwzMS4xMjUgMzQuMjQ2LDMxLjEyNSBMMzYuMTI1LDMxLjEyNSBMMzYuMTI1LDM1LjI1IFogTTM3LjEyNSwyOS4xMjUgTDM0Ljg4NSwyOS4xMjUgTDI1LjAyMSw3LjgzIEMyNC44NTYsNy40NzcgMjQuNTAzLDcuMjUgMjQuMTEzLDcuMjUgTDE1LjI1Niw3LjI1IEMxNC43MDQsNy4yNSAxNC4yNTcsNy42OTcgMTQuMjU2LDguMjQ5IEwxNC4yNSwxNC4zNzQgQzE0LjI1LDE0LjY0IDE0LjM1NSwxNC44OTQgMTQuNTQzLDE1LjA4MiBDMTQuNzMsMTUuMjcgMTQuOTg0LDE1LjM3NSAxNS4yNSwxNS4zNzUgTDE5LjIxNywxNS4zNzUgTDI5LjEyOSwzNi42NzIgQzI5LjI5MywzNy4wMjQgMjkuNjQ2LDM3LjI1IDMwLjAzNSwzNy4yNSBMMzcuMTI1LDM3LjI1IEMzNy42NzgsMzcuMjUgMzguMTI1LDM2LjgwMyAzOC4xMjUsMzYuMjUgTDM4LjEyNSwzMC4xMjUgQzM4LjEyNSwyOS41NzIgMzcuNjc4LDI5LjEyNSAzNy4xMjUsMjkuMTI1IEwzNy4xMjUsMjkuMTI1IFonCiAgICAgICAgICAgICAgaWQ9J0FtYXpvbi1MYW1iZGEtTGFtYmRhLUZ1bmN0aW9uX1Jlc291cmNlLUljb25fbGlnaHQtYmcnIGZpbGw9JyNENDVCMDcnPjwvcGF0aD4KICAgIDwvZz4KPC9zdmc+"
+ }
+}
\ No newline at end of file
diff --git a/connectors/aws/aws-lambda/pom.xml b/connectors/aws/aws-lambda/pom.xml
index d176ce402a..5c8ccf66ca 100644
--- a/connectors/aws/aws-lambda/pom.xml
+++ b/connectors/aws/aws-lambda/pom.xml
@@ -40,4 +40,23 @@
+
+
+
+ io.camunda.connector
+ element-template-generator-maven-plugin
+ ${project.version}
+
+
+ io.camunda.connector.awslambda.LambdaConnectorFunction
+
+
+ io.camunda.connector:connector-aws-base
+
+ aws-lambda-outbound-connector
+
+
+
+
+
diff --git a/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/AwsLambdaSupplier.java b/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/AwsLambdaSupplier.java
index f5ed5adaef..62086f18e3 100644
--- a/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/AwsLambdaSupplier.java
+++ b/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/AwsLambdaSupplier.java
@@ -7,6 +7,7 @@
package io.camunda.connector.awslambda;
import com.amazonaws.auth.AWSCredentialsProvider;
+import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.lambda.AWSLambda;
import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
@@ -19,4 +20,14 @@ public AWSLambda awsLambdaService(
.withRegion(region)
.build();
}
+
+ public AWSLambda awsLambdaService(
+ final AWSCredentialsProvider credentialsProvider,
+ final String region,
+ final String endpoint) {
+ return AWSLambdaClientBuilder.standard()
+ .withCredentials(credentialsProvider)
+ .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, region))
+ .build();
+ }
}
diff --git a/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/LambdaConnectorFunction.java b/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/LambdaConnectorFunction.java
index 45b69d9b04..57d8bf9e96 100644
--- a/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/LambdaConnectorFunction.java
+++ b/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/LambdaConnectorFunction.java
@@ -17,13 +17,31 @@
import io.camunda.connector.aws.AwsUtils;
import io.camunda.connector.aws.CredentialsProviderSupport;
import io.camunda.connector.aws.ObjectMapperSupplier;
+import io.camunda.connector.aws.model.impl.AwsBaseConfiguration;
import io.camunda.connector.awslambda.model.AwsLambdaRequest;
import io.camunda.connector.awslambda.model.AwsLambdaResult;
+import io.camunda.connector.generator.java.annotation.ElementTemplate;
+import java.util.Optional;
@OutboundConnector(
name = "AWS Lambda",
inputVariables = {"authentication", "configuration", "awsFunction"},
type = "io.camunda:aws-lambda:1")
+@ElementTemplate(
+ id = "io.camunda.connectors.AWSLAMBDA.v2",
+ name = "AWS Lambda Outbound Connector",
+ description = "Invoke a function",
+ inputDataClass = AwsLambdaRequest.class,
+ version = 5,
+ propertyGroups = {
+ @ElementTemplate.PropertyGroup(id = "authentication", label = "Authentication"),
+ @ElementTemplate.PropertyGroup(id = "configuration", label = "Configuration"),
+ @ElementTemplate.PropertyGroup(id = "operation", label = "Select operation"),
+ @ElementTemplate.PropertyGroup(id = "operationDetails", label = "Operation details")
+ },
+ documentationRef =
+ "https://docs.camunda.io/docs/components/connectors/out-of-the-box-connectors/aws-lambda/",
+ icon = "icon.svg")
public class LambdaConnectorFunction implements OutboundConnectorFunction {
private final AwsLambdaSupplier awsLambdaSupplier;
@@ -49,10 +67,9 @@ private InvokeResult invokeLambdaFunction(AwsLambdaRequest request) {
var region =
AwsUtils.extractRegionOrDefault(
request.getConfiguration(), request.getAwsFunction().getRegion());
- final AWSLambda awsLambda =
- awsLambdaSupplier.awsLambdaService(
- CredentialsProviderSupport.credentialsProvider(request), region);
+ AWSLambda awsLambda = createAwsLambdaClient(request, region);
try {
+
final InvokeRequest invokeRequest =
new InvokeRequest()
.withFunctionName(request.getAwsFunction().getFunctionName())
@@ -66,4 +83,14 @@ private InvokeResult invokeLambdaFunction(AwsLambdaRequest request) {
}
}
}
+
+ private AWSLambda createAwsLambdaClient(AwsLambdaRequest request, String region) {
+ Optional endpoint =
+ Optional.ofNullable(request.getConfiguration()).map(AwsBaseConfiguration::endpoint);
+
+ var credentialsProvider = CredentialsProviderSupport.credentialsProvider(request);
+ return endpoint
+ .map(ep -> awsLambdaSupplier.awsLambdaService(credentialsProvider, region, ep))
+ .orElseGet(() -> awsLambdaSupplier.awsLambdaService(credentialsProvider, region));
+ }
}
diff --git a/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/model/FunctionRequestData.java b/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/model/FunctionRequestData.java
index 6b29ddc845..493546ad70 100644
--- a/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/model/FunctionRequestData.java
+++ b/connectors/aws/aws-lambda/src/main/java/io/camunda/connector/awslambda/model/FunctionRequestData.java
@@ -6,17 +6,42 @@
*/
package io.camunda.connector.awslambda.model;
-import jakarta.validation.constraints.NotEmpty;
+import io.camunda.connector.feel.annotation.FEEL;
+import io.camunda.connector.generator.java.annotation.TemplateProperty;
+import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.Objects;
public class FunctionRequestData {
- @NotEmpty private String functionName;
- @NotNull private Object payload;
+ @TemplateProperty(
+ group = "operation",
+ type = TemplateProperty.PropertyType.Dropdown,
+ defaultValue = "sync",
+ choices = {
+ @TemplateProperty.DropdownPropertyChoice(value = "sync", label = "Invoke function (sync)")
+ })
private OperationType operationType; // this is not use and not implemented yet
- @Deprecated private String region;
+ @NotBlank
+ @TemplateProperty(
+ group = "operationDetails",
+ label = "Function name",
+ description = "Enter a name, ARN or alias of your function")
+ private String functionName;
+
+ @NotNull
+ @FEEL
+ @TemplateProperty(
+ group = "operationDetails",
+ label = "Payload",
+ type = TemplateProperty.PropertyType.Text,
+ description = "Provide payload for your function as JSON")
+ private Object payload;
+
+ @TemplateProperty(ignore = true)
+ @Deprecated
+ private String region;
public String getFunctionName() {
return functionName;
diff --git a/connectors/aws/aws-lambda/src/main/resources/icon.svg b/connectors/aws/aws-lambda/src/main/resources/icon.svg
new file mode 100644
index 0000000000..498e1cb682
--- /dev/null
+++ b/connectors/aws/aws-lambda/src/main/resources/icon.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/parent/pom.xml b/parent/pom.xml
index f58b9aa865..80893b3285 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -88,6 +88,11 @@ limitations under the License.
1.4.14
1.12.629
+ 3.11.4
+ 1.2.2
+
+
+ 1.19.3
2.2.0
v3-rev20231128-2.0.0
diff --git a/pom.xml b/pom.xml
index 1d97670a00..5321defb6b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,7 @@
connectors-e2e-test/connectors-e2e-test-http
connectors-e2e-test/connectors-e2e-test-automation-anywhere
connectors-e2e-test/connectors-e2e-test-kafka
+ connectors-e2e-test/connectors-e2e-test-aws