From a8752c7e533c66522c5a3411b36c434298ff237e Mon Sep 17 00:00:00 2001 From: Rahul Barwal Date: Thu, 25 Sep 2025 17:50:05 +0530 Subject: [PATCH 1/7] feat: add support for listing function versions and aliases in AWS Lambda Plugin - Implemented new commands `LIST_FUNCTION_VERSIONS` and `LIST_FUNCTION_ALIASES` in the AwsLambdaPlugin to retrieve function versions and aliases respectively. - Updated the invoke.json to include optional fields for function version and alias. - Created new JSON files for listing function versions and aliases with appropriate configurations. - Enhanced the plugin's test suite to cover the new functionalities, ensuring correct behavior for version and alias retrieval. This update improves the AWS Lambda Plugin's capabilities, allowing users to manage function versions and aliases more effectively. --- .../com/external/plugins/AwsLambdaPlugin.java | 138 +++++++++- .../src/main/resources/editor/invoke.json | 56 ++++ .../main/resources/editor/listAliases.json | 42 +++ .../main/resources/editor/listVersions.json | 42 +++ .../src/main/resources/editor/root.json | 11 +- .../external/plugins/AwsLambdaPluginTest.java | 240 ++++++++++++++++++ 6 files changed, 518 insertions(+), 11 deletions(-) create mode 100644 app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/listAliases.json create mode 100644 app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/listVersions.json diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java index 907e8f4913fc..195e55260491 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java @@ -9,7 +9,11 @@ import com.amazonaws.services.lambda.model.FunctionConfiguration; import com.amazonaws.services.lambda.model.InvokeRequest; import com.amazonaws.services.lambda.model.InvokeResult; +import com.amazonaws.services.lambda.model.ListAliasesRequest; +import com.amazonaws.services.lambda.model.ListAliasesResult; import com.amazonaws.services.lambda.model.ListFunctionsResult; +import com.amazonaws.services.lambda.model.ListVersionsByFunctionRequest; +import com.amazonaws.services.lambda.model.ListVersionsByFunctionResult; import com.amazonaws.services.lambda.model.ResourceNotFoundException; import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError; import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException; @@ -70,6 +74,10 @@ public Mono execute( ActionExecutionResult result; switch (Objects.requireNonNull(command)) { case "LIST_FUNCTIONS" -> result = listFunctions(actionConfiguration, connection); + case "LIST_FUNCTION_VERSIONS" -> result = + listFunctionVersions(actionConfiguration, connection); + case "LIST_FUNCTION_ALIASES" -> result = + listFunctionAliases(actionConfiguration, connection); case "INVOKE_FUNCTION" -> result = invokeFunction(actionConfiguration, connection); default -> throw new IllegalStateException("Unexpected value: " + command); } @@ -98,24 +106,84 @@ public Mono trigger( throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, "request type is missing"); } - ActionExecutionResult actionExecutionResult = listFunctions(null, connection); - ArrayNode body = (ArrayNode) actionExecutionResult.getBody(); - List> functionNames = StreamSupport.stream(body.spliterator(), false) - .map(function -> function.get("functionName").asText()) - .sorted() - .map(functionName -> Map.of("label", functionName, "value", functionName)) - .collect(Collectors.toList()); + + String requestType = request.getRequestType(); + ActionExecutionResult actionExecutionResult; + List> options; + + switch (requestType) { + case "FUNCTION_NAMES" -> { + actionExecutionResult = listFunctions(null, connection); + ArrayNode body = (ArrayNode) actionExecutionResult.getBody(); + options = StreamSupport.stream(body.spliterator(), false) + .map(function -> function.get("functionName").asText()) + .sorted() + .map(functionName -> Map.of("label", functionName, "value", functionName)) + .collect(Collectors.toList()); + } + case "FUNCTION_VERSIONS" -> { + String functionName = request.getParams().get("functionName"); + if (!StringUtils.hasText(functionName)) { + throw new AppsmithPluginException( + AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, + "function name is required for listing versions"); + } + actionExecutionResult = listFunctionVersions(null, connection, functionName); + ArrayNode body = (ArrayNode) actionExecutionResult.getBody(); + options = StreamSupport.stream(body.spliterator(), false) + .map(version -> version.get("version").asText()) + .sorted() + .map(version -> Map.of("label", version, "value", version)) + .collect(Collectors.toList()); + } + case "FUNCTION_ALIASES" -> { + String functionName = request.getParams().get("functionName"); + if (!StringUtils.hasText(functionName)) { + throw new AppsmithPluginException( + AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, + "function name is required for listing aliases"); + } + actionExecutionResult = listFunctionAliases(null, connection, functionName); + ArrayNode body = (ArrayNode) actionExecutionResult.getBody(); + options = StreamSupport.stream(body.spliterator(), false) + .map(alias -> alias.get("name").asText()) + .sorted() + .map(alias -> Map.of("label", alias, "value", alias)) + .collect(Collectors.toList()); + } + default -> throw new AppsmithPluginException( + AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, "Unsupported request type: " + requestType); + } TriggerResultDTO triggerResultDTO = new TriggerResultDTO(); - triggerResultDTO.setTrigger(functionNames); + triggerResultDTO.setTrigger(options); return Mono.just(triggerResultDTO); } ActionExecutionResult invokeFunction(ActionConfiguration actionConfiguration, AWSLambda connection) { InvokeRequest invokeRequest = new InvokeRequest(); - invokeRequest.setFunctionName( - getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionName", STRING_TYPE)); + + // Build function name with version/alias if specified + String functionName = + getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionName", STRING_TYPE); + String functionVersion = + getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionVersion", STRING_TYPE); + String functionAlias = + getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionAlias", STRING_TYPE); + + // Construct the full function name + String fullFunctionName = functionName; + if (StringUtils.hasText(functionAlias)) { + // If alias is specified, use it (alias takes precedence over version) + fullFunctionName = functionName + ":" + functionAlias; + } else if (StringUtils.hasText(functionVersion)) { + // If version is specified and no alias, use version + fullFunctionName = functionName + ":" + functionVersion; + } + // If neither version nor alias is specified, use the function name as-is (defaults to $LATEST) + + invokeRequest.setFunctionName(fullFunctionName); invokeRequest.setPayload( getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "body", STRING_TYPE)); invokeRequest.setInvocationType( @@ -145,6 +213,56 @@ ActionExecutionResult listFunctions(ActionConfiguration actionConfiguration, AWS return result; } + ActionExecutionResult listFunctionVersions( + ActionConfiguration actionConfiguration, AWSLambda connection, String functionName) { + if (actionConfiguration != null) { + functionName = + getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionName", STRING_TYPE); + } + + ListVersionsByFunctionRequest request = new ListVersionsByFunctionRequest(); + request.setFunctionName(functionName); + + ListVersionsByFunctionResult listVersionsResult = connection.listVersionsByFunction(request); + List versions = listVersionsResult.getVersions(); + + ActionExecutionResult result = new ActionExecutionResult(); + result.setBody(objectMapper.valueToTree(versions)); + result.setIsExecutionSuccess(true); + return result; + } + + ActionExecutionResult listFunctionVersions(ActionConfiguration actionConfiguration, AWSLambda connection) { + String functionName = + getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionName", STRING_TYPE); + return listFunctionVersions(null, connection, functionName); + } + + ActionExecutionResult listFunctionAliases( + ActionConfiguration actionConfiguration, AWSLambda connection, String functionName) { + if (actionConfiguration != null) { + functionName = + getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionName", STRING_TYPE); + } + + ListAliasesRequest request = new ListAliasesRequest(); + request.setFunctionName(functionName); + + ListAliasesResult listAliasesResult = connection.listAliases(request); + List aliases = listAliasesResult.getAliases(); + + ActionExecutionResult result = new ActionExecutionResult(); + result.setBody(objectMapper.valueToTree(aliases)); + result.setIsExecutionSuccess(true); + return result; + } + + ActionExecutionResult listFunctionAliases(ActionConfiguration actionConfiguration, AWSLambda connection) { + String functionName = + getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionName", STRING_TYPE); + return listFunctionAliases(null, connection, functionName); + } + @Override public Mono datasourceCreate(DatasourceConfiguration datasourceConfiguration) { log.debug(Thread.currentThread().getName() + ": datasourceCreate() called for AWS Lambda plugin."); diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/invoke.json b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/invoke.json index fb9b4df44900..ae54b3c89d46 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/invoke.json +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/invoke.json @@ -36,6 +36,62 @@ } } }, + { + "label": "Function version", + "tooltipText": "Optional: Specify a version number (e.g., 1, 2, $LATEST) or leave empty for $LATEST.", + "subtitle": "", + "isRequired": false, + "propertyName": "function_version", + "configProperty": "actionConfiguration.formData.functionVersion.data", + "controlType": "DROP_DOWN", + "initialValue": "", + "options": [], + "placeholderText": "Leave empty for $LATEST version", + "fetchOptionsConditionally": true, + "setFirstOptionAsDefault": false, + "alternateViewTypes": ["json"], + "conditionals": { + "enable": "{{actionConfiguration.formData.functionName.data}}", + "fetchDynamicValues": { + "condition": "{{actionConfiguration.formData.command.data === 'INVOKE_FUNCTION' && actionConfiguration.formData.functionName.data}}", + "config": { + "params": { + "requestType": "FUNCTION_VERSIONS", + "displayType": "DROP_DOWN", + "functionName": "{{actionConfiguration.formData.functionName.data}}" + } + } + } + } + }, + { + "label": "Function alias", + "tooltipText": "Optional: Specify an alias name (e.g., PROD, STAGING) or leave empty for no alias.", + "subtitle": "", + "isRequired": false, + "propertyName": "function_alias", + "configProperty": "actionConfiguration.formData.functionAlias.data", + "controlType": "DROP_DOWN", + "initialValue": "", + "options": [], + "placeholderText": "Leave empty for no alias", + "fetchOptionsConditionally": true, + "setFirstOptionAsDefault": false, + "alternateViewTypes": ["json"], + "conditionals": { + "enable": "{{actionConfiguration.formData.functionName.data}}", + "fetchDynamicValues": { + "condition": "{{actionConfiguration.formData.command.data === 'INVOKE_FUNCTION' && actionConfiguration.formData.functionName.data}}", + "config": { + "params": { + "requestType": "FUNCTION_ALIASES", + "displayType": "DROP_DOWN", + "functionName": "{{actionConfiguration.formData.functionName.data}}" + } + } + } + } + }, { "label": "Type of invocation", "tooltipText": "Should the invocation be synchronous or asynchronous?", diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/listAliases.json b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/listAliases.json new file mode 100644 index 000000000000..7bce6ca7e5b1 --- /dev/null +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/listAliases.json @@ -0,0 +1,42 @@ +{ + "identifier": "LIST_FUNCTION_ALIASES", + "controlType": "SECTION_V2", + "conditionals": { + "show": "{{actionConfiguration.formData.command.data === 'LIST_FUNCTION_ALIASES'}}" + }, + "children": [ + { + "controlType": "DOUBLE_COLUMN_ZONE", + "label": "Function details", + "children": [ + { + "label": "Function name", + "tooltipText": "The name of the AWS Lambda function to list aliases for.", + "subtitle": "", + "isRequired": true, + "propertyName": "function_name", + "configProperty": "actionConfiguration.formData.functionName.data", + "controlType": "DROP_DOWN", + "initialValue": "", + "options": [], + "placeholderText": "All function names will be fetched.", + "fetchOptionsConditionally": true, + "setFirstOptionAsDefault": true, + "alternateViewTypes": ["json"], + "conditionals": { + "enable": "{{true}}", + "fetchDynamicValues": { + "condition": "{{actionConfiguration.formData.command.data === 'LIST_FUNCTION_ALIASES'}}", + "config": { + "params": { + "requestType": "FUNCTION_NAMES", + "displayType": "DROP_DOWN" + } + } + } + } + } + ] + } + ] +} diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/listVersions.json b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/listVersions.json new file mode 100644 index 000000000000..56b868934c4e --- /dev/null +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/listVersions.json @@ -0,0 +1,42 @@ +{ + "identifier": "LIST_FUNCTION_VERSIONS", + "controlType": "SECTION_V2", + "conditionals": { + "show": "{{actionConfiguration.formData.command.data === 'LIST_FUNCTION_VERSIONS'}}" + }, + "children": [ + { + "controlType": "DOUBLE_COLUMN_ZONE", + "label": "Function details", + "children": [ + { + "label": "Function name", + "tooltipText": "The name of the AWS Lambda function to list versions for.", + "subtitle": "", + "isRequired": true, + "propertyName": "function_name", + "configProperty": "actionConfiguration.formData.functionName.data", + "controlType": "DROP_DOWN", + "initialValue": "", + "options": [], + "placeholderText": "All function names will be fetched.", + "fetchOptionsConditionally": true, + "setFirstOptionAsDefault": true, + "alternateViewTypes": ["json"], + "conditionals": { + "enable": "{{true}}", + "fetchDynamicValues": { + "condition": "{{actionConfiguration.formData.command.data === 'LIST_FUNCTION_VERSIONS'}}", + "config": { + "params": { + "requestType": "FUNCTION_NAMES", + "displayType": "DROP_DOWN" + } + } + } + } + } + ] + } + ] +} diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/root.json b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/root.json index 00bc0a8e402c..7d320fc43d68 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/root.json +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/root.json @@ -13,12 +13,21 @@ "description": "Choose the method you would like to use", "configProperty": "actionConfiguration.formData.command.data", "controlType": "DROP_DOWN", + "isRequired": true, "initialValue": "LIST_FUNCTIONS", "options": [ { "label": "List all functions", "value": "LIST_FUNCTIONS" }, + { + "label": "List function versions", + "value": "LIST_FUNCTION_VERSIONS" + }, + { + "label": "List function aliases", + "value": "LIST_FUNCTION_ALIASES" + }, { "label": "Invoke a function", "value": "INVOKE_FUNCTION" @@ -30,5 +39,5 @@ ] } ], - "files": ["list.json", "invoke.json"] + "files": ["list.json", "listVersions.json", "listAliases.json", "invoke.json"] } diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java b/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java index 7a41e59d7cdc..f2feb856cfd8 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java @@ -1,9 +1,14 @@ package com.external.plugins; import com.amazonaws.services.lambda.AWSLambda; +import com.amazonaws.services.lambda.model.AliasConfiguration; import com.amazonaws.services.lambda.model.FunctionConfiguration; import com.amazonaws.services.lambda.model.InvokeResult; +import com.amazonaws.services.lambda.model.ListAliasesRequest; +import com.amazonaws.services.lambda.model.ListAliasesResult; import com.amazonaws.services.lambda.model.ListFunctionsResult; +import com.amazonaws.services.lambda.model.ListVersionsByFunctionRequest; +import com.amazonaws.services.lambda.model.ListVersionsByFunctionResult; import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException; import com.appsmith.external.models.ActionConfiguration; import com.appsmith.external.models.ActionExecutionResult; @@ -193,4 +198,239 @@ public void testTrigger_missingRequestType() { pluginExecutor.trigger(mockLambda, datasourceConfiguration, request).block(); }); } + + @Test + public void testExecuteListFunctionVersions() { + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + + Map configMap = new HashMap<>(); + setDataValueSafelyInFormData(configMap, "command", "LIST_FUNCTION_VERSIONS"); + setDataValueSafelyInFormData(configMap, "functionName", "test-aws-lambda"); + + ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setFormData(configMap); + + // Mock the Lambda connection + AWSLambda mockLambda = mock(AWSLambda.class); + ListVersionsByFunctionResult mockVersionsResult = new ListVersionsByFunctionResult(); + mockVersionsResult.setVersions(List.of( + new FunctionConfiguration().withVersion("$LATEST"), + new FunctionConfiguration().withVersion("1"), + new FunctionConfiguration().withVersion("2"))); + when(mockLambda.listVersionsByFunction(any(ListVersionsByFunctionRequest.class))) + .thenReturn(mockVersionsResult); + + Mono resultMono = + pluginExecutor.execute(mockLambda, datasourceConfiguration, actionConfiguration); + StepVerifier.create(resultMono) + .assertNext(result -> { + assertEquals(3, ((ArrayNode) result.getBody()).size()); + }) + .verifyComplete(); + } + + @Test + public void testExecuteListFunctionAliases() { + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + + Map configMap = new HashMap<>(); + setDataValueSafelyInFormData(configMap, "command", "LIST_FUNCTION_ALIASES"); + setDataValueSafelyInFormData(configMap, "functionName", "test-aws-lambda"); + + ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setFormData(configMap); + + // Mock the Lambda connection + AWSLambda mockLambda = mock(AWSLambda.class); + ListAliasesResult mockAliasesResult = new ListAliasesResult(); + mockAliasesResult.setAliases( + List.of(new AliasConfiguration().withName("PROD"), new AliasConfiguration().withName("STAGING"))); + when(mockLambda.listAliases(any(ListAliasesRequest.class))).thenReturn(mockAliasesResult); + + Mono resultMono = + pluginExecutor.execute(mockLambda, datasourceConfiguration, actionConfiguration); + StepVerifier.create(resultMono) + .assertNext(result -> { + assertEquals(2, ((ArrayNode) result.getBody()).size()); + }) + .verifyComplete(); + } + + @Test + public void testExecuteInvokeFunctionWithVersion() { + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + + Map configMap = new HashMap<>(); + setDataValueSafelyInFormData(configMap, "command", "INVOKE_FUNCTION"); + setDataValueSafelyInFormData(configMap, "body", "{\"data\": \"\"}"); + setDataValueSafelyInFormData(configMap, "functionName", "test-aws-lambda"); + setDataValueSafelyInFormData(configMap, "functionVersion", "2"); + + ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setFormData(configMap); + + // Mock the Lambda connection + AWSLambda mockLambda = mock(AWSLambda.class); + InvokeResult mockResult = new InvokeResult(); + mockResult.setPayload(ByteBuffer.wrap("Hello World from version 2".getBytes())); + when(mockLambda.invoke(any())).thenReturn(mockResult); + + Mono resultMono = + pluginExecutor.execute(mockLambda, datasourceConfiguration, actionConfiguration); + StepVerifier.create(resultMono) + .assertNext(result -> { + assertTrue(result.getIsExecutionSuccess()); + assertEquals("Hello World from version 2", result.getBody().toString()); + }) + .verifyComplete(); + } + + @Test + public void testExecuteInvokeFunctionWithAlias() { + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + + Map configMap = new HashMap<>(); + setDataValueSafelyInFormData(configMap, "command", "INVOKE_FUNCTION"); + setDataValueSafelyInFormData(configMap, "body", "{\"data\": \"\"}"); + setDataValueSafelyInFormData(configMap, "functionName", "test-aws-lambda"); + setDataValueSafelyInFormData(configMap, "functionAlias", "PROD"); + + ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setFormData(configMap); + + // Mock the Lambda connection + AWSLambda mockLambda = mock(AWSLambda.class); + InvokeResult mockResult = new InvokeResult(); + mockResult.setPayload(ByteBuffer.wrap("Hello World from PROD alias".getBytes())); + when(mockLambda.invoke(any())).thenReturn(mockResult); + + Mono resultMono = + pluginExecutor.execute(mockLambda, datasourceConfiguration, actionConfiguration); + StepVerifier.create(resultMono) + .assertNext(result -> { + assertTrue(result.getIsExecutionSuccess()); + assertEquals("Hello World from PROD alias", result.getBody().toString()); + }) + .verifyComplete(); + } + + @Test + public void testExecuteInvokeFunctionWithAliasTakesPrecedenceOverVersion() { + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + + Map configMap = new HashMap<>(); + setDataValueSafelyInFormData(configMap, "command", "INVOKE_FUNCTION"); + setDataValueSafelyInFormData(configMap, "body", "{\"data\": \"\"}"); + setDataValueSafelyInFormData(configMap, "functionName", "test-aws-lambda"); + setDataValueSafelyInFormData(configMap, "functionVersion", "2"); + setDataValueSafelyInFormData(configMap, "functionAlias", "PROD"); + + ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setFormData(configMap); + + // Mock the Lambda connection + AWSLambda mockLambda = mock(AWSLambda.class); + InvokeResult mockResult = new InvokeResult(); + mockResult.setPayload(ByteBuffer.wrap("Hello World from PROD alias (alias takes precedence)".getBytes())); + when(mockLambda.invoke(any())).thenReturn(mockResult); + + Mono resultMono = + pluginExecutor.execute(mockLambda, datasourceConfiguration, actionConfiguration); + StepVerifier.create(resultMono) + .assertNext(result -> { + assertTrue(result.getIsExecutionSuccess()); + assertEquals( + "Hello World from PROD alias (alias takes precedence)", + result.getBody().toString()); + }) + .verifyComplete(); + } + + @Test + public void testTriggerFunctionNames() { + AWSLambda mockLambda = mock(AWSLambda.class); + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + + ListFunctionsResult mockFunctionsResult = new ListFunctionsResult(); + mockFunctionsResult.setFunctions(List.of( + new FunctionConfiguration().withFunctionName("function1"), + new FunctionConfiguration().withFunctionName("function2"))); + when(mockLambda.listFunctions()).thenReturn(mockFunctionsResult); + + TriggerRequestDTO request = new TriggerRequestDTO(); + request.setRequestType("FUNCTION_NAMES"); + + Mono resultMono = + pluginExecutor.trigger(mockLambda, datasourceConfiguration, request); + StepVerifier.create(resultMono) + .assertNext(result -> { + assertEquals(2, result.getTrigger().size()); + }) + .verifyComplete(); + } + + @Test + public void testTriggerFunctionVersions() { + AWSLambda mockLambda = mock(AWSLambda.class); + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + + ListVersionsByFunctionResult mockVersionsResult = new ListVersionsByFunctionResult(); + mockVersionsResult.setVersions(List.of( + new FunctionConfiguration().withVersion("$LATEST"), + new FunctionConfiguration().withVersion("1"), + new FunctionConfiguration().withVersion("2"))); + when(mockLambda.listVersionsByFunction(any(ListVersionsByFunctionRequest.class))) + .thenReturn(mockVersionsResult); + + TriggerRequestDTO request = new TriggerRequestDTO(); + request.setRequestType("FUNCTION_VERSIONS"); + Map params = new HashMap<>(); + params.put("functionName", "test-function"); + request.setParams(params); + + Mono resultMono = + pluginExecutor.trigger(mockLambda, datasourceConfiguration, request); + StepVerifier.create(resultMono) + .assertNext(result -> { + assertEquals(3, result.getTrigger().size()); + }) + .verifyComplete(); + } + + @Test + public void testTriggerFunctionAliases() { + AWSLambda mockLambda = mock(AWSLambda.class); + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + + ListAliasesResult mockAliasesResult = new ListAliasesResult(); + mockAliasesResult.setAliases( + List.of(new AliasConfiguration().withName("PROD"), new AliasConfiguration().withName("STAGING"))); + when(mockLambda.listAliases(any(ListAliasesRequest.class))).thenReturn(mockAliasesResult); + + TriggerRequestDTO request = new TriggerRequestDTO(); + request.setRequestType("FUNCTION_ALIASES"); + Map params = new HashMap<>(); + params.put("functionName", "test-function"); + request.setParams(params); + + Mono resultMono = + pluginExecutor.trigger(mockLambda, datasourceConfiguration, request); + StepVerifier.create(resultMono) + .assertNext(result -> { + assertEquals(2, result.getTrigger().size()); + }) + .verifyComplete(); + } + + @Test + public void testTriggerUnsupportedRequestType() { + AWSLambda mockLambda = mock(AWSLambda.class); + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + TriggerRequestDTO request = new TriggerRequestDTO(); + request.setRequestType("UNSUPPORTED_TYPE"); + + assertThrows(AppsmithPluginException.class, () -> { + pluginExecutor.trigger(mockLambda, datasourceConfiguration, request).block(); + }); + } } From 84e3a8e318645c6b0f34896145b18ace12684991 Mon Sep 17 00:00:00 2001 From: Rahul Barwal Date: Thu, 25 Sep 2025 18:49:40 +0530 Subject: [PATCH 2/7] fix: update parameter retrieval in AwsLambdaPlugin for function name - Changed the method of retrieving the function name parameter from `request.getParams()` to `request.getParameters()` for better type safety and consistency. - This update ensures that the function name is correctly fetched as a String, preventing potential runtime errors. This fix enhances the reliability of the AWS Lambda Plugin's functionality related to function versions and aliases. --- .../src/main/java/com/external/plugins/AwsLambdaPlugin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java index 195e55260491..9a76bbb05f3a 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java @@ -122,7 +122,7 @@ public Mono trigger( .collect(Collectors.toList()); } case "FUNCTION_VERSIONS" -> { - String functionName = request.getParams().get("functionName"); + String functionName = (String) request.getParameters().get("functionName"); if (!StringUtils.hasText(functionName)) { throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, @@ -137,7 +137,7 @@ public Mono trigger( .collect(Collectors.toList()); } case "FUNCTION_ALIASES" -> { - String functionName = request.getParams().get("functionName"); + String functionName = (String) request.getParameters().get("functionName"); if (!StringUtils.hasText(functionName)) { throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, From 3733f685ea5893048489ee61b8b17cd5e7879566 Mon Sep 17 00:00:00 2001 From: Nilansh Bansal Date: Thu, 25 Sep 2025 18:51:18 +0530 Subject: [PATCH 3/7] Apply suggestion from @coderabbitai[bot] Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../src/main/java/com/external/plugins/AwsLambdaPlugin.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java index 195e55260491..ba203ed87a49 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java @@ -110,6 +110,7 @@ public Mono trigger( String requestType = request.getRequestType(); ActionExecutionResult actionExecutionResult; List> options; + Map params = request.getParams() == null ? Map.of() : request.getParams(); switch (requestType) { case "FUNCTION_NAMES" -> { @@ -122,7 +123,7 @@ public Mono trigger( .collect(Collectors.toList()); } case "FUNCTION_VERSIONS" -> { - String functionName = request.getParams().get("functionName"); + String functionName = params.get("functionName"); if (!StringUtils.hasText(functionName)) { throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, @@ -137,7 +138,7 @@ public Mono trigger( .collect(Collectors.toList()); } case "FUNCTION_ALIASES" -> { - String functionName = request.getParams().get("functionName"); + String functionName = params.get("functionName"); if (!StringUtils.hasText(functionName)) { throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, From ea5ea45437d8ac74dad63441a116123504be3fad Mon Sep 17 00:00:00 2001 From: Nilansh Bansal Date: Thu, 25 Sep 2025 18:52:38 +0530 Subject: [PATCH 4/7] Apply suggestion from @coderabbitai[bot] Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../src/main/java/com/external/plugins/AwsLambdaPlugin.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java index ba203ed87a49..1565f484b203 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java @@ -220,6 +220,11 @@ ActionExecutionResult listFunctionVersions( functionName = getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionName", STRING_TYPE); } + if (!StringUtils.hasText(functionName)) { + throw new AppsmithPluginException( + AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, + "function name is required for listing versions"); + } ListVersionsByFunctionRequest request = new ListVersionsByFunctionRequest(); request.setFunctionName(functionName); From ca09991c00bb3e54c6250e1d98e04865cc4c26b2 Mon Sep 17 00:00:00 2001 From: nilansh Date: Thu, 25 Sep 2025 19:19:19 +0530 Subject: [PATCH 5/7] fixed issues --- .../com/external/plugins/AwsLambdaPlugin.java | 29 ++++++++++++------- .../external/plugins/AwsLambdaPluginTest.java | 14 ++++----- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java index 1565f484b203..66235ef21452 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java @@ -110,7 +110,7 @@ public Mono trigger( String requestType = request.getRequestType(); ActionExecutionResult actionExecutionResult; List> options; - Map params = request.getParams() == null ? Map.of() : request.getParams(); + Map params = request.getParameters() == null ? Map.of() : request.getParameters(); switch (requestType) { case "FUNCTION_NAMES" -> { @@ -123,7 +123,7 @@ public Mono trigger( .collect(Collectors.toList()); } case "FUNCTION_VERSIONS" -> { - String functionName = params.get("functionName"); + String functionName = (String) params.get("functionName"); if (!StringUtils.hasText(functionName)) { throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, @@ -138,7 +138,7 @@ public Mono trigger( .collect(Collectors.toList()); } case "FUNCTION_ALIASES" -> { - String functionName = params.get("functionName"); + String functionName = (String) params.get("functionName"); if (!StringUtils.hasText(functionName)) { throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, @@ -165,26 +165,33 @@ public Mono trigger( ActionExecutionResult invokeFunction(ActionConfiguration actionConfiguration, AWSLambda connection) { InvokeRequest invokeRequest = new InvokeRequest(); - // Build function name with version/alias if specified + // Validate and set function name (required parameter) String functionName = getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionName", STRING_TYPE); + if (!StringUtils.hasText(functionName)) { + throw new AppsmithPluginException( + AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, + "Function name is required for Lambda invocation"); + } + + // Get version and alias parameters String functionVersion = getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionVersion", STRING_TYPE); String functionAlias = getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "functionAlias", STRING_TYPE); - // Construct the full function name - String fullFunctionName = functionName; + // Set function name (without qualifier) + invokeRequest.setFunctionName(functionName); + + // Use setQualifier for version/alias instead of embedding in function name if (StringUtils.hasText(functionAlias)) { // If alias is specified, use it (alias takes precedence over version) - fullFunctionName = functionName + ":" + functionAlias; + invokeRequest.setQualifier(functionAlias); } else if (StringUtils.hasText(functionVersion)) { // If version is specified and no alias, use version - fullFunctionName = functionName + ":" + functionVersion; + invokeRequest.setQualifier(functionVersion); } - // If neither version nor alias is specified, use the function name as-is (defaults to $LATEST) - - invokeRequest.setFunctionName(fullFunctionName); + // If neither version nor alias is specified, defaults to $LATEST invokeRequest.setPayload( getDataValueSafelyFromFormData(actionConfiguration.getFormData(), "body", STRING_TYPE)); invokeRequest.setInvocationType( diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java b/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java index f2feb856cfd8..5abb3b7cdf32 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java @@ -364,7 +364,7 @@ public void testTriggerFunctionNames() { pluginExecutor.trigger(mockLambda, datasourceConfiguration, request); StepVerifier.create(resultMono) .assertNext(result -> { - assertEquals(2, result.getTrigger().size()); + assertEquals(2, ((List) result.getTrigger()).size()); }) .verifyComplete(); } @@ -384,15 +384,15 @@ public void testTriggerFunctionVersions() { TriggerRequestDTO request = new TriggerRequestDTO(); request.setRequestType("FUNCTION_VERSIONS"); - Map params = new HashMap<>(); + Map params = new HashMap<>(); params.put("functionName", "test-function"); - request.setParams(params); + request.setParameters(params); Mono resultMono = pluginExecutor.trigger(mockLambda, datasourceConfiguration, request); StepVerifier.create(resultMono) .assertNext(result -> { - assertEquals(3, result.getTrigger().size()); + assertEquals(3, ((List) result.getTrigger()).size()); }) .verifyComplete(); } @@ -409,15 +409,15 @@ public void testTriggerFunctionAliases() { TriggerRequestDTO request = new TriggerRequestDTO(); request.setRequestType("FUNCTION_ALIASES"); - Map params = new HashMap<>(); + Map params = new HashMap<>(); params.put("functionName", "test-function"); - request.setParams(params); + request.setParameters(params); Mono resultMono = pluginExecutor.trigger(mockLambda, datasourceConfiguration, request); StepVerifier.create(resultMono) .assertNext(result -> { - assertEquals(2, result.getTrigger().size()); + assertEquals(2, ((List) result.getTrigger()).size()); }) .verifyComplete(); } From d840a7f6d6630421b1fc23bab288b6c2b34d3da3 Mon Sep 17 00:00:00 2001 From: nilansh Date: Thu, 25 Sep 2025 19:41:05 +0530 Subject: [PATCH 6/7] addressed coderabbit comments --- .../external/plugins/AwsLambdaPluginTest.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java b/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java index 5abb3b7cdf32..671725793494 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/test/java/com/external/plugins/AwsLambdaPluginTest.java @@ -3,6 +3,7 @@ import com.amazonaws.services.lambda.AWSLambda; import com.amazonaws.services.lambda.model.AliasConfiguration; import com.amazonaws.services.lambda.model.FunctionConfiguration; +import com.amazonaws.services.lambda.model.InvokeRequest; import com.amazonaws.services.lambda.model.InvokeResult; import com.amazonaws.services.lambda.model.ListAliasesRequest; import com.amazonaws.services.lambda.model.ListAliasesResult; @@ -19,6 +20,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import org.testcontainers.junit.jupiter.Testcontainers; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -36,6 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @Testcontainers @@ -275,6 +278,9 @@ public void testExecuteInvokeFunctionWithVersion() { mockResult.setPayload(ByteBuffer.wrap("Hello World from version 2".getBytes())); when(mockLambda.invoke(any())).thenReturn(mockResult); + // Capture the InvokeRequest to verify the qualifier is set correctly + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(InvokeRequest.class); + Mono resultMono = pluginExecutor.execute(mockLambda, datasourceConfiguration, actionConfiguration); StepVerifier.create(resultMono) @@ -283,6 +289,12 @@ public void testExecuteInvokeFunctionWithVersion() { assertEquals("Hello World from version 2", result.getBody().toString()); }) .verifyComplete(); + + // Verify that the InvokeRequest was called with the correct qualifier + verify(mockLambda).invoke(requestCaptor.capture()); + InvokeRequest capturedRequest = requestCaptor.getValue(); + assertEquals("test-aws-lambda", capturedRequest.getFunctionName()); + assertEquals("2", capturedRequest.getQualifier()); } @Test @@ -304,6 +316,9 @@ public void testExecuteInvokeFunctionWithAlias() { mockResult.setPayload(ByteBuffer.wrap("Hello World from PROD alias".getBytes())); when(mockLambda.invoke(any())).thenReturn(mockResult); + // Capture the InvokeRequest to verify the qualifier is set correctly + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(InvokeRequest.class); + Mono resultMono = pluginExecutor.execute(mockLambda, datasourceConfiguration, actionConfiguration); StepVerifier.create(resultMono) @@ -312,6 +327,12 @@ public void testExecuteInvokeFunctionWithAlias() { assertEquals("Hello World from PROD alias", result.getBody().toString()); }) .verifyComplete(); + + // Verify that the InvokeRequest was called with the correct qualifier + verify(mockLambda).invoke(requestCaptor.capture()); + InvokeRequest capturedRequest = requestCaptor.getValue(); + assertEquals("test-aws-lambda", capturedRequest.getFunctionName()); + assertEquals("PROD", capturedRequest.getQualifier()); } @Test @@ -334,6 +355,9 @@ public void testExecuteInvokeFunctionWithAliasTakesPrecedenceOverVersion() { mockResult.setPayload(ByteBuffer.wrap("Hello World from PROD alias (alias takes precedence)".getBytes())); when(mockLambda.invoke(any())).thenReturn(mockResult); + // Capture the InvokeRequest to verify the qualifier is set correctly + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(InvokeRequest.class); + Mono resultMono = pluginExecutor.execute(mockLambda, datasourceConfiguration, actionConfiguration); StepVerifier.create(resultMono) @@ -344,6 +368,51 @@ public void testExecuteInvokeFunctionWithAliasTakesPrecedenceOverVersion() { result.getBody().toString()); }) .verifyComplete(); + + // Verify that the InvokeRequest was called with the alias (not version) as qualifier + verify(mockLambda).invoke(requestCaptor.capture()); + InvokeRequest capturedRequest = requestCaptor.getValue(); + assertEquals("test-aws-lambda", capturedRequest.getFunctionName()); + assertEquals("PROD", capturedRequest.getQualifier()); // Should be alias, not version "2" + } + + @Test + public void testExecuteInvokeFunctionWithoutVersionOrAlias() { + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + + Map configMap = new HashMap<>(); + setDataValueSafelyInFormData(configMap, "command", "INVOKE_FUNCTION"); + setDataValueSafelyInFormData(configMap, "body", "{\"data\": \"\"}"); + setDataValueSafelyInFormData(configMap, "functionName", "test-aws-lambda"); + // No functionVersion or functionAlias specified + + ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setFormData(configMap); + + // Mock the Lambda connection + AWSLambda mockLambda = mock(AWSLambda.class); + InvokeResult mockResult = new InvokeResult(); + mockResult.setPayload(ByteBuffer.wrap("Hello World from $LATEST".getBytes())); + when(mockLambda.invoke(any())).thenReturn(mockResult); + + // Capture the InvokeRequest to verify no qualifier is set (defaults to $LATEST) + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(InvokeRequest.class); + + Mono resultMono = + pluginExecutor.execute(mockLambda, datasourceConfiguration, actionConfiguration); + StepVerifier.create(resultMono) + .assertNext(result -> { + assertTrue(result.getIsExecutionSuccess()); + assertEquals("Hello World from $LATEST", result.getBody().toString()); + }) + .verifyComplete(); + + // Verify that the InvokeRequest was called without a qualifier (defaults to $LATEST) + verify(mockLambda).invoke(requestCaptor.capture()); + InvokeRequest capturedRequest = requestCaptor.getValue(); + assertEquals("test-aws-lambda", capturedRequest.getFunctionName()); + // When no qualifier is set, it should be null (AWS defaults to $LATEST) + assertEquals(null, capturedRequest.getQualifier()); } @Test From 0148b540d74887bf64fd1eda1dff29cb73593c82 Mon Sep 17 00:00:00 2001 From: Rahul Barwal Date: Fri, 26 Sep 2025 16:29:00 +0530 Subject: [PATCH 7/7] fix: the invoke a function functionality for listing versions and aliases (#41267) ## Description - Enhanced the AwsLambdaPlugin to support both old and new parameter structures for retrieving function names in FUNCTION_VERSIONS and FUNCTION_ALIASES requests. - Updated the invoke.json to reflect the new parameter structure, ensuring compatibility with the updated logic. This change improves the robustness of the plugin by accommodating different parameter formats, preventing potential errors during function name retrieval. Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="" ### :mag: Cypress test results > [!CAUTION] > If you modify the content in this section, you are likely to disrupt the CI result for your PR. ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No --- .../com/external/plugins/AwsLambdaPlugin.java | 20 +++++++++++++++++-- .../src/main/resources/editor/invoke.json | 8 ++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java index 66235ef21452..e6e48c5bea45 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/java/com/external/plugins/AwsLambdaPlugin.java @@ -123,7 +123,15 @@ public Mono trigger( .collect(Collectors.toList()); } case "FUNCTION_VERSIONS" -> { - String functionName = (String) params.get("functionName"); + // Handle both old and new parameter structures + String functionName; + if (params.containsKey("parameters") && params.get("parameters") instanceof Map) { + Map parameters = (Map) params.get("parameters"); + functionName = (String) parameters.get("functionName"); + } else { + functionName = (String) params.get("functionName"); + } + if (!StringUtils.hasText(functionName)) { throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, @@ -138,7 +146,15 @@ public Mono trigger( .collect(Collectors.toList()); } case "FUNCTION_ALIASES" -> { - String functionName = (String) params.get("functionName"); + // Handle both old and new parameter structures + String functionName; + if (params.containsKey("parameters") && params.get("parameters") instanceof Map) { + Map parameters = (Map) params.get("parameters"); + functionName = (String) parameters.get("functionName"); + } else { + functionName = (String) params.get("functionName"); + } + if (!StringUtils.hasText(functionName)) { throw new AppsmithPluginException( AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, diff --git a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/invoke.json b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/invoke.json index ae54b3c89d46..23496934c9c3 100644 --- a/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/invoke.json +++ b/app/server/appsmith-plugins/awsLambdaPlugin/src/main/resources/editor/invoke.json @@ -58,7 +58,9 @@ "params": { "requestType": "FUNCTION_VERSIONS", "displayType": "DROP_DOWN", - "functionName": "{{actionConfiguration.formData.functionName.data}}" + "parameters": { + "functionName": "{{actionConfiguration.formData.functionName.data}}" + } } } } @@ -86,7 +88,9 @@ "params": { "requestType": "FUNCTION_ALIASES", "displayType": "DROP_DOWN", - "functionName": "{{actionConfiguration.formData.functionName.data}}" + "parameters": { + "functionName": "{{actionConfiguration.formData.functionName.data}}" + } } } }