From bb91ea5f8e373b18894e4fbe59ecfec067b860fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Duarte?= Date: Sun, 19 May 2024 10:54:10 +0000 Subject: [PATCH 01/50] Add Support for AWS Lambda Function SDK V2 --- aws-sdk-v2/build.gradle.kts | 2 + .../service/lambda/LambdaClientFactory.java | 94 ++++++++++++ .../sdk/v2/service/lambda/package-info.java | 28 ++++ function-client-aws-v2/build.gradle.kts | 17 +++ .../aws/AwsInvokeRequestDefinition.java | 46 ++++++ .../client/aws/AwsLambdaFunctionExecutor.java | 136 ++++++++++++++++++ .../function/client/aws/package-info.java | 23 +++ gradle/libs.versions.toml | 1 + 8 files changed, 347 insertions(+) create mode 100644 aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java create mode 100644 aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java create mode 100644 function-client-aws-v2/build.gradle.kts create mode 100644 function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java create mode 100644 function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java create mode 100644 function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java diff --git a/aws-sdk-v2/build.gradle.kts b/aws-sdk-v2/build.gradle.kts index 7ea6a13001..aacc958d98 100644 --- a/aws-sdk-v2/build.gradle.kts +++ b/aws-sdk-v2/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { compileOnly(libs.awssdk.secretsmanager) compileOnly(libs.awssdk.servicediscovery) compileOnly(libs.awssdk.cloudwatchlogs) + compileOnly(libs.awssdk.lambda) // Tests testAnnotationProcessor(mn.micronaut.inject.java) @@ -41,6 +42,7 @@ dependencies { testImplementation(libs.awssdk.sqs) testImplementation(libs.awssdk.ssm) testImplementation(libs.awssdk.rekognition) + testImplementation(libs.awssdk.lambda) testRuntimeOnly(libs.jcl.over.slf4j) testRuntimeOnly(mn.snakeyaml) diff --git a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java new file mode 100644 index 0000000000..58530d571d --- /dev/null +++ b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java @@ -0,0 +1,94 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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. + */ +/** + * Secrets Manager client factory. + * @author Luis Duarte + * @since 2.6.0 + */ +package io.micronaut.aws.sdk.v2.service.lambda; + +import io.micronaut.aws.sdk.v2.service.AWSServiceConfiguration; +import io.micronaut.aws.sdk.v2.service.AwsClientFactory; +import io.micronaut.aws.ua.UserAgentProvider; +import io.micronaut.context.annotation.Bean; +import io.micronaut.context.annotation.Requires; +import io.micronaut.core.annotation.Nullable; +import jakarta.inject.Named; +import jakarta.inject.Singleton; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.providers.AwsRegionProviderChain; +import software.amazon.awssdk.services.lambda.LambdaAsyncClient; +import software.amazon.awssdk.services.lambda.LambdaAsyncClientBuilder; +import software.amazon.awssdk.services.lambda.LambdaClient; +import software.amazon.awssdk.services.lambda.LambdaClientBuilder; + + +public class LambdaClientFactory extends AwsClientFactory { + /** + * Constructor. + * + * @param credentialsProvider The credentials provider + * @param regionProvider The region provider + * @param userAgentProvider User-Agent Provider + * @param awsServiceConfiguration AWS Service Configuration + */ + protected LambdaClientFactory(AwsCredentialsProviderChain credentialsProvider, + AwsRegionProviderChain regionProvider, + @Nullable UserAgentProvider userAgentProvider, + @Nullable @Named(LambdaClient.SERVICE_NAME) AWSServiceConfiguration awsServiceConfiguration) { + super(credentialsProvider, regionProvider, userAgentProvider, awsServiceConfiguration); + } + + @Override + protected LambdaClientBuilder createSyncBuilder() { + return LambdaClient.builder(); + } + + @Override + protected LambdaAsyncClientBuilder createAsyncBuilder() { + return LambdaAsyncClient.builder(); + } + + @Override + @Singleton + public LambdaClientBuilder syncBuilder(SdkHttpClient httpClient) { + return super.syncBuilder(httpClient); + } + + @Override + @Bean(preDestroy = "close") + @Singleton + public LambdaClient syncClient(LambdaClientBuilder builder) { + return super.syncClient(builder); + } + + @Override + @Singleton + @Requires(beans = SdkAsyncHttpClient.class) + public LambdaAsyncClientBuilder asyncBuilder(SdkAsyncHttpClient httpClient) { + return super.asyncBuilder(httpClient); + } + + @Override + @Bean(preDestroy = "close") + @Singleton + @Requires(beans = SdkAsyncHttpClient.class) + public LambdaAsyncClient asyncClient(LambdaAsyncClientBuilder builder) { + return super.asyncClient(builder); + } +} diff --git a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java new file mode 100644 index 0000000000..958a98bdd9 --- /dev/null +++ b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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. + */ +/** + * Secrets Manager client factory. + * @author Luis Duarte + * @since 2.6.0 + */ +@Requires(classes = {LambdaClient.class, LambdaAsyncClient.class}) +@Configuration +package io.micronaut.aws.sdk.v2.service.lambda; + +import io.micronaut.context.annotation.Configuration; +import io.micronaut.context.annotation.Requires; +import software.amazon.awssdk.services.lambda.LambdaAsyncClient; +import software.amazon.awssdk.services.lambda.LambdaClient; diff --git a/function-client-aws-v2/build.gradle.kts b/function-client-aws-v2/build.gradle.kts new file mode 100644 index 0000000000..073a111bc9 --- /dev/null +++ b/function-client-aws-v2/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id("io.micronaut.build.internal.aws-module") +} + +dependencies { + api(projects.micronautAwsSdkV2) + implementation(libs.awssdk.lambda) + implementation(mn.reactor) + api(mn.micronaut.function.client) + implementation(mn.micronaut.jackson.databind) + testAnnotationProcessor(mn.micronaut.inject.java) + testImplementation(mn.micronaut.inject.java) + testImplementation(mn.micronaut.http.server.netty) + testImplementation(mn.micronaut.function.web) + testImplementation(mnGroovy.micronaut.function.groovy) + testImplementation(mnGroovy.micronaut.runtime.groovy) +} diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java new file mode 100644 index 0000000000..01ac618aad --- /dev/null +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java @@ -0,0 +1,46 @@ +/* + * Copyright 2017-2020 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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.micronaut.function.client.aws; + +import io.micronaut.context.annotation.EachProperty; +import io.micronaut.context.annotation.Parameter; +import io.micronaut.function.client.FunctionDefinition; + +/** + * Builds an {@link InvokeRequest} for each definition under {@code aws.lambda.functions}. + * + * @author graemerocher + * @since 1.0 + */ +@EachProperty(AwsInvokeRequestDefinition.AWS_LAMBDA_FUNCTIONS) +public class AwsInvokeRequestDefinition implements FunctionDefinition { + public static final String AWS_LAMBDA_FUNCTIONS = "aws.lambda.functions"; + + private final String name; + + /** + * Constructor. + * @param name configured name from a property + */ + public AwsInvokeRequestDefinition(@Parameter String name) { + this.name = name; + } + + @Override + public String getName() { + return this.name; + } +} diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java new file mode 100644 index 0000000000..b8a6a0014f --- /dev/null +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java @@ -0,0 +1,136 @@ +/* + * Copyright 2017-2020 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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.micronaut.function.client.aws; + +import io.micronaut.context.annotation.Requires; +import io.micronaut.core.async.publisher.Publishers; +import io.micronaut.core.convert.ConversionService; +import io.micronaut.core.io.buffer.ByteBufferFactory; +import io.micronaut.core.type.Argument; +import io.micronaut.function.client.FunctionDefinition; +import io.micronaut.function.client.FunctionInvoker; +import io.micronaut.function.client.FunctionInvokerChooser; +import io.micronaut.function.client.exceptions.FunctionExecutionException; +import io.micronaut.jackson.codec.JsonMediaTypeCodec; +import io.micronaut.scheduling.TaskExecutors; +import jakarta.inject.Named; +import jakarta.inject.Singleton; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.lambda.LambdaAsyncClient; +import software.amazon.awssdk.services.lambda.LambdaClient; +import software.amazon.awssdk.services.lambda.model.InvokeRequest; +import software.amazon.awssdk.services.lambda.model.InvokeResponse; + +import java.nio.ByteBuffer; +import java.util.Optional; +import java.util.concurrent.ExecutorService; + +/** + * A {@link FunctionInvoker} for invoking functions on AWS. + * + * @param input type + * @param output type + * @author graemerocher + * @since 1.0 + */ +@Requires(beans = LambdaAsyncClient.class) +@Singleton +public class AwsLambdaFunctionExecutor implements FunctionInvoker, FunctionInvokerChooser { + + private static final int STATUS_CODE_ERROR = 300; + private final LambdaClient syncClient; + private final LambdaAsyncClient asyncClient; + private final ByteBufferFactory byteBufferFactory; + private final JsonMediaTypeCodec jsonMediaTypeCodec; + private final ExecutorService ioExecutor; + + /** + * Constructor. + * + * @param asyncClient asyncClient + * @param byteBufferFactory byteBufferFactory + * @param jsonMediaTypeCodec jsonMediaTypeCodec + * @param ioExecutor ioExecutor + */ + protected AwsLambdaFunctionExecutor( + LambdaAsyncClient asyncClient, + ByteBufferFactory byteBufferFactory, + JsonMediaTypeCodec jsonMediaTypeCodec, + @Named(TaskExecutors.IO) ExecutorService ioExecutor) { + + this.asyncClient = asyncClient; + this.byteBufferFactory = byteBufferFactory; + this.jsonMediaTypeCodec = jsonMediaTypeCodec; + this.ioExecutor = ioExecutor; + } + + @Override + public O invoke(FunctionDefinition definition, I input, Argument outputType) { + if (!(definition instanceof AwsInvokeRequestDefinition)) { + throw new IllegalArgumentException("Function definition must be a AWSInvokeRequestDefinition"); + } + + boolean isReactiveType = Publishers.isConvertibleToPublisher(outputType.getType()); + SdkBytes input = encodeInput(input); + if (isReactiveType) { + Mono invokeFlowable = Mono.fromFuture(asyncClient.invoke(InvokeRequest.builder() + .functionName(definition.getName()) + .payload(input) + .build())) + .map(invokeResult -> + decodeResult(definition, (Argument) outputType.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT), invokeResult)) + .onErrorResume(throwable -> Mono.error(new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + throwable.getMessage(), throwable))) + .subscribeOn(Schedulers.fromExecutor(ioExecutor)); + return ConversionService.SHARED.convert(invokeFlowable, outputType).orElseThrow(() -> new IllegalArgumentException("Unsupported Reactive type: " + outputType)); + } else { + InvokeResponse invokeResult = syncClient.invoke(invokeRequest); + try { + return (O) decodeResult(definition, outputType, invokeResult); + } catch (Exception e) { + throw new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + e.getMessage(), e); + } + } + } + + private Object decodeResult(FunctionDefinition definition, Argument outputType, InvokeResponse invokeResult) { + Integer statusCode = invokeResult.getStatusCode(); + if (statusCode >= STATUS_CODE_ERROR) { + throw new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + invokeResult.getFunctionError()); + } + io.micronaut.core.io.buffer.ByteBuffer byteBuffer = byteBufferFactory.copiedBuffer(invokeResult.getPayload().asByteArray()); + + return jsonMediaTypeCodec.decode(outputType, byteBuffer); + } + + private SdkBytes encodeInput(I input) { + if (input != null) { + ByteBuffer nioBuffer = jsonMediaTypeCodec.encode(input, byteBufferFactory).asNioBuffer(); + return SdkBytes.fromByteArray(nioBuffer); + } + return null; + } + + @SuppressWarnings("unchecked") + @Override + public Optional> choose(FunctionDefinition definition) { + if (definition instanceof AwsInvokeRequestDefinition) { + return Optional.of((FunctionInvoker) this); + } + return Optional.empty(); + } +} diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java new file mode 100644 index 0000000000..2a437be991 --- /dev/null +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java @@ -0,0 +1,23 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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. + */ +/** + * Function AWS lamda configuration. + * + * @author graemerocher + * @since 1.0 + */ +package io.micronaut.function.client.aws; + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 58c2ceebca..8f83afc2b5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -69,6 +69,7 @@ awssdk-apache-client = { module = 'software.amazon.awssdk:apache-client' } awssdk-apigatewaymanagementapi = { module = 'software.amazon.awssdk:apigatewaymanagementapi' } awssdk-cloudwatchlogs = { module = 'software.amazon.awssdk:cloudwatchlogs'} awssdk-dynamodb = { module = 'software.amazon.awssdk:dynamodb' } +awssdk-lambda = { module = 'software.amazon.awssdk:lambda' } awssdk-netty-nio-client = { module = 'software.amazon.awssdk:netty-nio-client' } awssdk-rekognition = { module = 'software.amazon.awssdk:rekognition' } awssdk-s3 = { module = 'software.amazon.awssdk:s3' } From ac22ee81792259501b2c504ae8d02975c3462ba8 Mon Sep 17 00:00:00 2001 From: Luis Duarte Date: Thu, 30 May 2024 17:22:24 +0100 Subject: [PATCH 02/50] Make Spotless happy --- .../aws/sdk/v2/service/lambda/LambdaClientFactory.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java index 58530d571d..6cb71d122c 100644 --- a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java +++ b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java @@ -13,11 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** - * Secrets Manager client factory. - * @author Luis Duarte - * @since 2.6.0 - */ package io.micronaut.aws.sdk.v2.service.lambda; import io.micronaut.aws.sdk.v2.service.AWSServiceConfiguration; From 51f58c1a677006e5f0aac78198525e78c26dca3e Mon Sep 17 00:00:00 2001 From: Luis Duarte Date: Sun, 9 Jun 2024 19:55:51 +0100 Subject: [PATCH 03/50] Fix compilation issues --- .../client/aws/AwsLambdaFunctionExecutor.java | 22 ++++++++++--------- settings.gradle.kts | 1 + 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java index b8a6a0014f..67d89be654 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java @@ -68,11 +68,12 @@ public class AwsLambdaFunctionExecutor implements FunctionInvoker, F * @param ioExecutor ioExecutor */ protected AwsLambdaFunctionExecutor( + LambdaClient syncClient, LambdaAsyncClient asyncClient, ByteBufferFactory byteBufferFactory, JsonMediaTypeCodec jsonMediaTypeCodec, @Named(TaskExecutors.IO) ExecutorService ioExecutor) { - + this.syncClient = syncClient; this.asyncClient = asyncClient; this.byteBufferFactory = byteBufferFactory; this.jsonMediaTypeCodec = jsonMediaTypeCodec; @@ -86,12 +87,13 @@ public O invoke(FunctionDefinition definition, I input, Argument outputType) } boolean isReactiveType = Publishers.isConvertibleToPublisher(outputType.getType()); - SdkBytes input = encodeInput(input); + SdkBytes sdkBytes = encodeInput(input); + InvokeRequest invokeRequest = InvokeRequest.builder() + .functionName(definition.getName()) + .payload(sdkBytes) + .build(); if (isReactiveType) { - Mono invokeFlowable = Mono.fromFuture(asyncClient.invoke(InvokeRequest.builder() - .functionName(definition.getName()) - .payload(input) - .build())) + Mono invokeFlowable = Mono.fromFuture(asyncClient.invoke(invokeRequest)) .map(invokeResult -> decodeResult(definition, (Argument) outputType.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT), invokeResult)) .onErrorResume(throwable -> Mono.error(new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + throwable.getMessage(), throwable))) @@ -108,11 +110,11 @@ public O invoke(FunctionDefinition definition, I input, Argument outputType) } private Object decodeResult(FunctionDefinition definition, Argument outputType, InvokeResponse invokeResult) { - Integer statusCode = invokeResult.getStatusCode(); + Integer statusCode = invokeResult.statusCode(); if (statusCode >= STATUS_CODE_ERROR) { - throw new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + invokeResult.getFunctionError()); + throw new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + invokeResult.functionError()); } - io.micronaut.core.io.buffer.ByteBuffer byteBuffer = byteBufferFactory.copiedBuffer(invokeResult.getPayload().asByteArray()); + io.micronaut.core.io.buffer.ByteBuffer byteBuffer = byteBufferFactory.copiedBuffer(invokeResult.payload().asByteArray()); return jsonMediaTypeCodec.decode(outputType, byteBuffer); } @@ -120,7 +122,7 @@ private Object decodeResult(FunctionDefinition definition, Argument outputTyp private SdkBytes encodeInput(I input) { if (input != null) { ByteBuffer nioBuffer = jsonMediaTypeCodec.encode(input, byteBufferFactory).asNioBuffer(); - return SdkBytes.fromByteArray(nioBuffer); + return SdkBytes.fromByteBuffer(nioBuffer); } return null; } diff --git a/settings.gradle.kts b/settings.gradle.kts index cbba64335e..02fce2a522 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,6 +37,7 @@ include("function-aws-api-proxy-test") include("function-aws-custom-runtime") include("function-aws-test") include("function-client-aws") +include("function-client-aws-v2") include("test-suite") include("test-suite-aws-sdk-v2") From 640f53c8710a912dbda6168e26934f22da9a94c7 Mon Sep 17 00:00:00 2001 From: Luis Duarte Date: Sun, 9 Jun 2024 19:58:51 +0100 Subject: [PATCH 04/50] Initial Commit for Tests --- function-client-aws-v2/build.gradle.kts | 7 +++ .../client/aws/IsbnValidationRequest.java | 32 ++++++++++++++ .../client/aws/IsbnValidationResponse.java | 40 +++++++++++++++++ .../client/aws/IsbnValidatorClient.java | 30 +++++++++++++ .../aws/IsbnValidatorFunctionSpec.groovy | 44 +++++++++++++++++++ gradle/libs.versions.toml | 9 ++++ 6 files changed, 162 insertions(+) create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationRequest.java create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationResponse.java create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorClient.java create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorFunctionSpec.groovy diff --git a/function-client-aws-v2/build.gradle.kts b/function-client-aws-v2/build.gradle.kts index 073a111bc9..494849e3bf 100644 --- a/function-client-aws-v2/build.gradle.kts +++ b/function-client-aws-v2/build.gradle.kts @@ -10,8 +10,15 @@ dependencies { implementation(mn.micronaut.jackson.databind) testAnnotationProcessor(mn.micronaut.inject.java) testImplementation(mn.micronaut.inject.java) + testImplementation(mn.micronaut.inject.java) testImplementation(mn.micronaut.http.server.netty) testImplementation(mn.micronaut.function.web) testImplementation(mnGroovy.micronaut.function.groovy) testImplementation(mnGroovy.micronaut.runtime.groovy) + // TODO: Switch to Test Resources, once Lambda Client is also included in Service Override + implementation(platform(libs.boms.testcontainers)) + implementation(libs.testcontainers) + implementation(libs.testcontainers.localstack) + implementation(libs.testcontainers.junit) + implementation(libs.testcontainers.spock) } diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationRequest.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationRequest.java new file mode 100644 index 0000000000..23f7e40250 --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationRequest.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017-2020 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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.micronaut.function.client.aws; + +public class IsbnValidationRequest { + private String isbn; + + public IsbnValidationRequest() { + + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } +} diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationResponse.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationResponse.java new file mode 100644 index 0000000000..f37d952f0d --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationResponse.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017-2020 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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.micronaut.function.client.aws; + +public class IsbnValidationResponse { + private String isbn; + private boolean valid; + + public IsbnValidationResponse() { + + } + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } + + public boolean isValid() { + return valid; + } + + public void setValid(boolean valid) { + this.valid = valid; + } +} diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorClient.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorClient.java new file mode 100644 index 0000000000..fcbceefc99 --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorClient.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017-2020 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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.micronaut.function.client.aws; + +//tag::imports[] +import io.micronaut.function.client.FunctionClient; +import io.micronaut.http.annotation.Body; +import jakarta.inject.Named; +//end::imports[] + +@FunctionClient +public interface IsbnValidatorClient { + + @Named("isbn-validator") + IsbnValidationResponse validate(@Body IsbnValidationRequest request); // <1> +} +//end::clazz[] diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorFunctionSpec.groovy new file mode 100644 index 0000000000..eb9bebedc8 --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorFunctionSpec.groovy @@ -0,0 +1,44 @@ +package io.micronaut.function.client.aws + +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import io.micronaut.test.support.TestPropertyProvider +import jakarta.inject.Inject +import org.testcontainers.containers.localstack.LocalStackContainer +import org.testcontainers.spock.Testcontainers +import org.testcontainers.utility.DockerImageName +import spock.lang.Shared +import spock.lang.Specification + +import static org.testcontainers.containers.localstack.LocalStackContainer.Service.LAMBDA + +@Testcontainers +@MicronautTest +class IsbnValidatorFunctionSpec extends Specification implements TestPropertyProvider { + + @Shared + private LocalStackContainer localStackContainer = new LocalStackContainer(DockerImageName + .parse("localstack/localstack:3.4.0")) + .withServices(LAMBDA); + + @Override + Map getProperties() { + return Map.of( + "aws.accessKeyId", localStackContainer.getAccessKey(), + "aws.secretKey", localStackContainer.getSecretKey(), + "aws.region", localStackContainer.getRegion(), + "aws.services.lambda.endpoint-override", localStackContainer.getEndpointOverride(LAMBDA) + ) + } + + @Inject + IsbnValidatorClient functionClient; + + def "foo"() { + given: + when: + functionClient.validate(new IsbnValidationRequest()) + then: + 1==1 + } + +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8f83afc2b5..ada06ac3e2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,6 +45,9 @@ kotlin = "1.9.23" # Micronaut micronaut-gradle-plugin = "4.3.6" +# Test Containers +testcontainers = "1.19.8" + [libraries] # Core @@ -85,6 +88,7 @@ kotlin-stdlib-jdk8 = { module = 'org.jetbrains.kotlin:kotlin-stdlib-jdk8', versi boms-aws-java-sdk-v1 = { module = 'com.amazonaws:aws-java-sdk-bom', version.ref = 'managed-aws-java-sdk-v1' } boms-aws-java-sdk-v2 = { module = 'software.amazon.awssdk:bom', version.ref = 'managed-aws-java-sdk-v2' } +boms-testcontainers = { module = 'org.testcontainers:testcontainers-bom', version.ref = 'testcontainers' } bouncycastle-provider = { module = 'org.bouncycastle:bcprov-jdk15on', version.ref = 'bouncycastle'} fileupload = { module = 'org.javadelight:delight-fileupload', version.ref = 'fileupload' } @@ -119,3 +123,8 @@ servlet-api = { module = 'javax.servlet:servlet-api', version.ref = 'servlet-api gradle-micronaut = { module = "io.micronaut.gradle:micronaut-gradle-plugin", version.ref = "micronaut-gradle-plugin" } gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } + +testcontainers = { module = "org.testcontainers:testcontainers", version.ref = "testcontainers" } +testcontainers-localstack = { module = "org.testcontainers:localstack", version.ref = "testcontainers" } +testcontainers-junit = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" } +testcontainers-spock = { module = "org.testcontainers:spock", version.ref = "testcontainers" } From 83fd2d29c6d6f3483c9a14f8c0779f8243974ae9 Mon Sep 17 00:00:00 2001 From: Luis Duarte Date: Fri, 14 Jun 2024 20:27:03 +0100 Subject: [PATCH 05/50] Add Lambda Code for Testing with LocalStack --- .../src/test/resources/lambda/index.js | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 function-client-aws-v2/src/test/resources/lambda/index.js diff --git a/function-client-aws-v2/src/test/resources/lambda/index.js b/function-client-aws-v2/src/test/resources/lambda/index.js new file mode 100644 index 0000000000..2c2b2a30b8 --- /dev/null +++ b/function-client-aws-v2/src/test/resources/lambda/index.js @@ -0,0 +1,37 @@ +/* +Contract: + +interface ComplexObject { + aNumber int + aString string +} + +interface Request { + aNumber int + aString string + aObject ComplexObject +} + +interface Response { + aNumber int + aString string + aObject ComplexObject + anArray []ComplexObject +} +*/ + +exports.handler = async function (event, context) { + if (!event.aNumber || !event.aString || !event.aObject || !event.aObject.aNumber || !event.aObject.aString) { + throw new Error('Invalid Input'); + } + + var arr = []; + arr.push(event.aObject); + + return { + aNumber: event.aNumber, + aString: event.aString, + aObject: event.aObject, + anArray: arr, + }; +}; From 7458176fcd3157ec1451f6999a4a49b2c6f2ddf4 Mon Sep 17 00:00:00 2001 From: Luis Duarte Date: Fri, 14 Jun 2024 20:31:25 +0100 Subject: [PATCH 06/50] Add Integration Tests for Function Client for AWS SDK V2 --- function-client-aws-v2/build.gradle.kts | 3 +- .../function/client/aws/ComplexType.java | 33 ++++++ .../client/aws/IsbnValidationRequest.java | 32 ----- .../client/aws/IsbnValidationResponse.java | 40 ------- .../aws/IsbnValidatorFunctionSpec.groovy | 44 ------- ...torClient.java => TestFunctionClient.java} | 6 +- .../client/aws/TestFunctionClientRequest.java | 58 +++++++++ .../aws/TestFunctionClientResponse.java | 64 ++++++++++ .../client/aws/TestFunctionSpec.groovy | 112 ++++++++++++++++++ gradle/libs.versions.toml | 4 + 10 files changed, 275 insertions(+), 121 deletions(-) create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/ComplexType.java delete mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationRequest.java delete mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationResponse.java delete mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorFunctionSpec.groovy rename function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/{IsbnValidatorClient.java => TestFunctionClient.java} (81%) create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientRequest.java create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientResponse.java create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy diff --git a/function-client-aws-v2/build.gradle.kts b/function-client-aws-v2/build.gradle.kts index 494849e3bf..d0c2290efd 100644 --- a/function-client-aws-v2/build.gradle.kts +++ b/function-client-aws-v2/build.gradle.kts @@ -10,11 +10,12 @@ dependencies { implementation(mn.micronaut.jackson.databind) testAnnotationProcessor(mn.micronaut.inject.java) testImplementation(mn.micronaut.inject.java) - testImplementation(mn.micronaut.inject.java) + testImplementation(mnSerde.micronaut.serde.api) testImplementation(mn.micronaut.http.server.netty) testImplementation(mn.micronaut.function.web) testImplementation(mnGroovy.micronaut.function.groovy) testImplementation(mnGroovy.micronaut.runtime.groovy) + testImplementation(libs.commons.compress) // TODO: Switch to Test Resources, once Lambda Client is also included in Service Override implementation(platform(libs.boms.testcontainers)) implementation(libs.testcontainers) diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/ComplexType.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/ComplexType.java new file mode 100644 index 0000000000..ad0fffd240 --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/ComplexType.java @@ -0,0 +1,33 @@ +package io.micronaut.function.client.aws; + +import io.micronaut.serde.annotation.Serdeable; + +@Serdeable +public class ComplexType { + private int aNumber; + private String aString; + + public ComplexType() { + } + + public ComplexType(int aNumber, String aString) { + this.aNumber = aNumber; + this.aString = aString; + } + + public int getaNumber() { + return aNumber; + } + + public void setaNumber(int aNumber) { + this.aNumber = aNumber; + } + + public String getaString() { + return aString; + } + + public void setaString(String aString) { + this.aString = aString; + } +} diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationRequest.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationRequest.java deleted file mode 100644 index 23f7e40250..0000000000 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationRequest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2017-2020 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://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.micronaut.function.client.aws; - -public class IsbnValidationRequest { - private String isbn; - - public IsbnValidationRequest() { - - } - - public String getIsbn() { - return isbn; - } - - public void setIsbn(String isbn) { - this.isbn = isbn; - } -} diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationResponse.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationResponse.java deleted file mode 100644 index f37d952f0d..0000000000 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidationResponse.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2017-2020 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://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.micronaut.function.client.aws; - -public class IsbnValidationResponse { - private String isbn; - private boolean valid; - - public IsbnValidationResponse() { - - } - public String getIsbn() { - return isbn; - } - - public void setIsbn(String isbn) { - this.isbn = isbn; - } - - public boolean isValid() { - return valid; - } - - public void setValid(boolean valid) { - this.valid = valid; - } -} diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorFunctionSpec.groovy deleted file mode 100644 index eb9bebedc8..0000000000 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorFunctionSpec.groovy +++ /dev/null @@ -1,44 +0,0 @@ -package io.micronaut.function.client.aws - -import io.micronaut.test.extensions.spock.annotation.MicronautTest -import io.micronaut.test.support.TestPropertyProvider -import jakarta.inject.Inject -import org.testcontainers.containers.localstack.LocalStackContainer -import org.testcontainers.spock.Testcontainers -import org.testcontainers.utility.DockerImageName -import spock.lang.Shared -import spock.lang.Specification - -import static org.testcontainers.containers.localstack.LocalStackContainer.Service.LAMBDA - -@Testcontainers -@MicronautTest -class IsbnValidatorFunctionSpec extends Specification implements TestPropertyProvider { - - @Shared - private LocalStackContainer localStackContainer = new LocalStackContainer(DockerImageName - .parse("localstack/localstack:3.4.0")) - .withServices(LAMBDA); - - @Override - Map getProperties() { - return Map.of( - "aws.accessKeyId", localStackContainer.getAccessKey(), - "aws.secretKey", localStackContainer.getSecretKey(), - "aws.region", localStackContainer.getRegion(), - "aws.services.lambda.endpoint-override", localStackContainer.getEndpointOverride(LAMBDA) - ) - } - - @Inject - IsbnValidatorClient functionClient; - - def "foo"() { - given: - when: - functionClient.validate(new IsbnValidationRequest()) - then: - 1==1 - } - -} diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorClient.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java similarity index 81% rename from function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorClient.java rename to function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java index fcbceefc99..c36a2d7274 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/IsbnValidatorClient.java +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java @@ -18,13 +18,11 @@ //tag::imports[] import io.micronaut.function.client.FunctionClient; import io.micronaut.http.annotation.Body; -import jakarta.inject.Named; //end::imports[] @FunctionClient -public interface IsbnValidatorClient { +public interface TestFunctionClient { - @Named("isbn-validator") - IsbnValidationResponse validate(@Body IsbnValidationRequest request); // <1> + TestFunctionClientResponse invokeFunction(@Body TestFunctionClientRequest request); // <1> } //end::clazz[] diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientRequest.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientRequest.java new file mode 100644 index 0000000000..ecfd51a899 --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientRequest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017-2020 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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.micronaut.function.client.aws; + +import io.micronaut.serde.annotation.Serdeable; + +@Serdeable +public class TestFunctionClientRequest { + private int aNumber; + private String aString; + private ComplexType aObject; + + public TestFunctionClientRequest() { + } + + public TestFunctionClientRequest(int aNumber, String aString, ComplexType aObject) { + this.aNumber = aNumber; + this.aString = aString; + this.aObject = aObject; + } + + public int getaNumber() { + return aNumber; + } + + public void setaNumber(int aNumber) { + this.aNumber = aNumber; + } + + public String getaString() { + return aString; + } + + public void setaString(String aString) { + this.aString = aString; + } + + public ComplexType getaObject() { + return aObject; + } + + public void setaObject(ComplexType aObject) { + this.aObject = aObject; + } +} diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientResponse.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientResponse.java new file mode 100644 index 0000000000..cd575f6a08 --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientResponse.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017-2020 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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.micronaut.function.client.aws; + +import io.micronaut.serde.annotation.Serdeable; + +import java.util.List; + +@Serdeable +public class TestFunctionClientResponse { + private int aNumber; + private String aString; + private ComplexType aObject; + private List anArray; + + public TestFunctionClientResponse() { + + } + + public int getaNumber() { + return aNumber; + } + + public void setaNumber(int aNumber) { + this.aNumber = aNumber; + } + + public String getaString() { + return aString; + } + + public void setaString(String aString) { + this.aString = aString; + } + + public ComplexType getaObject() { + return aObject; + } + + public void setaObject(ComplexType aObject) { + this.aObject = aObject; + } + + public List getAnArray() { + return anArray; + } + + public void setAnArray(List anArray) { + this.anArray = anArray; + } +} diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy new file mode 100644 index 0000000000..a2f60c20bd --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy @@ -0,0 +1,112 @@ +package io.micronaut.function.client.aws + +import io.micronaut.core.io.ResourceLoader +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import io.micronaut.test.support.TestPropertyProvider +import jakarta.inject.Inject +import org.apache.commons.compress.archivers.ArchiveOutputStream +import org.apache.commons.compress.archivers.ArchiveStreamFactory +import org.testcontainers.containers.localstack.LocalStackContainer +import org.testcontainers.spock.Testcontainers +import org.testcontainers.utility.DockerImageName +import software.amazon.awssdk.core.SdkBytes +import software.amazon.awssdk.services.lambda.LambdaClient +import software.amazon.awssdk.services.lambda.model.Architecture +import software.amazon.awssdk.services.lambda.model.CreateFunctionRequest +import software.amazon.awssdk.services.lambda.model.DeleteFunctionRequest +import software.amazon.awssdk.services.lambda.model.FunctionCode +import software.amazon.awssdk.services.lambda.model.Runtime +import spock.lang.Shared +import spock.lang.Specification + +import java.nio.file.Files + +import static org.testcontainers.containers.localstack.LocalStackContainer.Service.LAMBDA + +@Testcontainers +@MicronautTest +class TestFunctionSpec extends Specification implements TestPropertyProvider { + + private static final String FUNCTION_NAME = "FUNCTION_NAME"; + + @Shared + private LocalStackContainer localStackContainer = new LocalStackContainer(DockerImageName + .parse("localstack/localstack:3.4.0")) + .withServices(LAMBDA); + + @Inject + @Shared + LambdaClient lambdaClient + + @Inject + @Shared + ResourceLoader resourceLoader + + @Override + Map getProperties() { + return Map.of( + "aws.accessKeyId", localStackContainer.getAccessKey(), + "aws.secretKey", localStackContainer.getSecretKey(), + "aws.region", localStackContainer.getRegion(), + "aws.services.lambda.endpoint-override", localStackContainer.getEndpointOverride(LAMBDA) + ) + } + + @Inject + TestFunctionClient functionClient; + + def setupSpec() { + def resource = resourceLoader.getResource("classpath:lambda").orElseThrow() + def tempFile = File.createTempFile(UUID.randomUUID().toString(), UUID.randomUUID().toString()) + tempFile.deleteOnExit() + + def outputStream = new FileOutputStream(tempFile) + + ArchiveOutputStream archive = new ArchiveStreamFactory() + .createArchiveOutputStream(ArchiveStreamFactory.ZIP, outputStream); + + Arrays.stream(new File(resource.toURI()).listFiles()) + .forEach { file -> + archive.createArchiveEntry(file, file.getName()) + } + + archive.finish() + + lambdaClient.createFunction(CreateFunctionRequest.builder() + .functionName(FUNCTION_NAME) + .code(FunctionCode.builder() + .zipFile(SdkBytes.fromByteArray(Files.readAllBytes(tempFile.toPath()))) + .build()) + .runtime(Runtime.NODEJS20_X) + .architectures(Architecture.X86_64) + .handler("index.handler") + .build()) + } + + def cleanupSpec() { + lambdaClient.deleteFunction(DeleteFunctionRequest.builder() + .functionName(FUNCTION_NAME) + .build()) + } + + def "foo"() { + given: + def aNumber = 1 + def aString = "someString" + + when: + def result = functionClient + .invokeFunction(new TestFunctionClientRequest(aNumber, aNumber, new ComplexType(aNumber, aString))) + + then: + result.aNumber == aNumber + result.aString == aString + result.aObject + result.aObject.aNumber == aNumber + result.aObject.aString == aString + result.anArray.size() == 1 + result.anArray[0].aNumber == aNumber + result.anArray[0].aString == aString + } + +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ada06ac3e2..bb883efccb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -48,6 +48,8 @@ micronaut-gradle-plugin = "4.3.6" # Test Containers testcontainers = "1.19.8" +commons-compress = "1.26.2" + [libraries] # Core @@ -128,3 +130,5 @@ testcontainers = { module = "org.testcontainers:testcontainers", version.ref = " testcontainers-localstack = { module = "org.testcontainers:localstack", version.ref = "testcontainers" } testcontainers-junit = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" } testcontainers-spock = { module = "org.testcontainers:spock", version.ref = "testcontainers" } + +commons-compress = { module = "org.apache.commons:commons-compress", version.ref = "commons-compress" } From 054a4e612dce8711e77eca53f717366f02c44c6f Mon Sep 17 00:00:00 2001 From: Luis Duarte Date: Mon, 24 Jun 2024 19:42:51 +0100 Subject: [PATCH 07/50] Add missing Function Client Configuration --- .../io/micronaut/function/client/aws/TestFunctionClient.java | 2 ++ .../io/micronaut/function/client/aws/TestFunctionSpec.groovy | 2 +- .../src/test/resources/application-test.yaml | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 function-client-aws-v2/src/test/resources/application-test.yaml diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java index c36a2d7274..32272c5ae3 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java @@ -18,11 +18,13 @@ //tag::imports[] import io.micronaut.function.client.FunctionClient; import io.micronaut.http.annotation.Body; +import jakarta.inject.Named; //end::imports[] @FunctionClient public interface TestFunctionClient { + @Named("test-function") TestFunctionClientResponse invokeFunction(@Body TestFunctionClientRequest request); // <1> } //end::clazz[] diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy index a2f60c20bd..d94e96488f 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy @@ -27,7 +27,7 @@ import static org.testcontainers.containers.localstack.LocalStackContainer.Servi @MicronautTest class TestFunctionSpec extends Specification implements TestPropertyProvider { - private static final String FUNCTION_NAME = "FUNCTION_NAME"; + private static final String FUNCTION_NAME = "TEST_FUNCTION_NAME"; @Shared private LocalStackContainer localStackContainer = new LocalStackContainer(DockerImageName diff --git a/function-client-aws-v2/src/test/resources/application-test.yaml b/function-client-aws-v2/src/test/resources/application-test.yaml new file mode 100644 index 0000000000..d4e19ceff1 --- /dev/null +++ b/function-client-aws-v2/src/test/resources/application-test.yaml @@ -0,0 +1,5 @@ +aws: + lambda: + functions: + test-function: + function-name: 'TEST_FUNCTION_NAME' From 1755112d56fdd82b52603795d5184f7b3dd075f0 Mon Sep 17 00:00:00 2001 From: Luis Duarte Date: Mon, 24 Jun 2024 19:45:39 +0100 Subject: [PATCH 08/50] Update Javadoc --- .../io/micronaut/aws/sdk/v2/service/lambda/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java index 958a98bdd9..52833e7a4c 100644 --- a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java +++ b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Secrets Manager client factory. + * Lambda client factory. * @author Luis Duarte * @since 2.6.0 */ From 1149df3d2b21a916f41653ce9cdee6842af32a4b Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 10:22:01 +0200 Subject: [PATCH 09/50] add javadoc, test and @Factory --- .../service/lambda/LambdaClientFactory.java | 11 ++++++++-- .../sdk/v2/service/LambdaClientSpec.groovy | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 aws-sdk-v2/src/test/groovy/io/micronaut/aws/sdk/v2/service/LambdaClientSpec.groovy diff --git a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java index 6cb71d122c..90b04b62b9 100644 --- a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java +++ b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java @@ -19,7 +19,9 @@ import io.micronaut.aws.sdk.v2.service.AwsClientFactory; import io.micronaut.aws.ua.UserAgentProvider; import io.micronaut.context.annotation.Bean; +import io.micronaut.context.annotation.Factory; import io.micronaut.context.annotation.Requires; +import io.micronaut.core.annotation.Internal; import io.micronaut.core.annotation.Nullable; import jakarta.inject.Named; import jakarta.inject.Singleton; @@ -32,8 +34,13 @@ import software.amazon.awssdk.services.lambda.LambdaClient; import software.amazon.awssdk.services.lambda.LambdaClientBuilder; - -public class LambdaClientFactory extends AwsClientFactory { +/** + * Factory that creates {@link LambdaClient} and {@link LambdaAsyncClient}. + * @since 4.7.0 + */ +@Factory +@Internal +class LambdaClientFactory extends AwsClientFactory { /** * Constructor. * diff --git a/aws-sdk-v2/src/test/groovy/io/micronaut/aws/sdk/v2/service/LambdaClientSpec.groovy b/aws-sdk-v2/src/test/groovy/io/micronaut/aws/sdk/v2/service/LambdaClientSpec.groovy new file mode 100644 index 0000000000..7966a9c683 --- /dev/null +++ b/aws-sdk-v2/src/test/groovy/io/micronaut/aws/sdk/v2/service/LambdaClientSpec.groovy @@ -0,0 +1,20 @@ +package io.micronaut.aws.sdk.v2.service + +import software.amazon.awssdk.services.lambda.LambdaAsyncClient +import software.amazon.awssdk.services.lambda.LambdaClient + +class LambdaClientSpec extends ServiceClientSpec { + @Override + protected String serviceName() { + return LambdaClient.SERVICE_NAME + } + + @Override + protected LambdaClient getClient() { + applicationContext.getBean(LambdaClient) + } + + protected LambdaAsyncClient getAsyncClient() { + applicationContext.getBean(LambdaAsyncClient) + } +} From 361a8e32bda3caab85448c04fefb09878bc9f1f9 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 10:23:13 +0200 Subject: [PATCH 10/50] Update aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java --- .../io/micronaut/aws/sdk/v2/service/lambda/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java index 52833e7a4c..beafeb820f 100644 --- a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java +++ b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Lambda client factory. + * Lambda client factory. * @author Luis Duarte * @since 2.6.0 */ From c42b08619382961534cd3bf7773c14087345031f Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 10:23:20 +0200 Subject: [PATCH 11/50] Update aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java --- .../io/micronaut/aws/sdk/v2/service/lambda/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java index beafeb820f..5115d73a68 100644 --- a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java +++ b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/package-info.java @@ -16,7 +16,7 @@ /** * Lambda client factory. * @author Luis Duarte - * @since 2.6.0 + * @since 4.7.0 */ @Requires(classes = {LambdaClient.class, LambdaAsyncClient.class}) @Configuration From b6f463923eb5158c4ecf9c3765f442eda2c29a2f Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 10:28:03 +0200 Subject: [PATCH 12/50] Update function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java --- .../main/java/io/micronaut/function/client/aws/package-info.java | 1 - 1 file changed, 1 deletion(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java index 2a437be991..1df7bcd09c 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java @@ -16,7 +16,6 @@ /** * Function AWS lamda configuration. * - * @author graemerocher * @since 1.0 */ package io.micronaut.function.client.aws; From 592e3e6e2fc0a0aba18dc674a688b46f96ae2287 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 10:28:10 +0200 Subject: [PATCH 13/50] Update function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java --- .../java/io/micronaut/function/client/aws/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java index 1df7bcd09c..a7fc7acc37 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java @@ -16,7 +16,7 @@ /** * Function AWS lamda configuration. * - * @since 1.0 + * @since 4.7.0 */ package io.micronaut.function.client.aws; From 5f03912abffefde1660b09aa5c1d0cab7cbf1585 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 10:28:17 +0200 Subject: [PATCH 14/50] Update function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java --- .../function/client/aws/AwsInvokeRequestDefinition.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java index 01ac618aad..e55729a666 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java @@ -23,7 +23,7 @@ * Builds an {@link InvokeRequest} for each definition under {@code aws.lambda.functions}. * * @author graemerocher - * @since 1.0 + * @since 4.7.0 */ @EachProperty(AwsInvokeRequestDefinition.AWS_LAMBDA_FUNCTIONS) public class AwsInvokeRequestDefinition implements FunctionDefinition { From a79b20484d8515c12b3800c770829a316232ddac Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 10:28:23 +0200 Subject: [PATCH 15/50] Update function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java --- .../function/client/aws/AwsInvokeRequestDefinition.java | 1 - 1 file changed, 1 deletion(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java index e55729a666..88960ec47e 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java @@ -22,7 +22,6 @@ /** * Builds an {@link InvokeRequest} for each definition under {@code aws.lambda.functions}. * - * @author graemerocher * @since 4.7.0 */ @EachProperty(AwsInvokeRequestDefinition.AWS_LAMBDA_FUNCTIONS) From 9256c528608ed0fa3cad5c454e37218138177b3a Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 11:14:11 +0200 Subject: [PATCH 16/50] Use AwsInvokeRequestDefinition in javadoc --- .../function/client/aws/AwsInvokeRequestDefinition.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java index 88960ec47e..9bc9295096 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java @@ -20,7 +20,7 @@ import io.micronaut.function.client.FunctionDefinition; /** - * Builds an {@link InvokeRequest} for each definition under {@code aws.lambda.functions}. + * Builds an {@link AwsInvokeRequestDefinition} for each definition under {@code aws.lambda.functions}. * * @since 4.7.0 */ From 38d17d63afce7c04293c6dd74991c611dcb062c4 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 11:14:22 +0200 Subject: [PATCH 17/50] document Lambda Client --- src/main/docs/guide/sdkv2/lambdaClient.adoc | 15 +++++++++++++++ src/main/docs/guide/toc.yml | 1 + 2 files changed, 16 insertions(+) create mode 100644 src/main/docs/guide/sdkv2/lambdaClient.adoc diff --git a/src/main/docs/guide/sdkv2/lambdaClient.adoc b/src/main/docs/guide/sdkv2/lambdaClient.adoc new file mode 100644 index 0000000000..495de2782e --- /dev/null +++ b/src/main/docs/guide/sdkv2/lambdaClient.adoc @@ -0,0 +1,15 @@ +To use a Lambda client, add the following dependency: + +dependency:lambda[groupId="software.amazon.awssdk"] + +Then, the following beans will be created: + +* `software.amazon.awssdk.services.lambda.LambdaClientBuilder` +* `software.amazon.awssdk.services.lambda.LambdaClient`. + +And: + +* `software.amazon.awssdk.services.lambda.LambdaAsyncClientBuilder` +* `software.amazon.awssdk.services.lambda.LambdaAsyncClient`. + +The HTTP client, credentials and region will be configured as per described in the <>. diff --git a/src/main/docs/guide/toc.yml b/src/main/docs/guide/toc.yml index a9789fe4e4..f9edf387a0 100644 --- a/src/main/docs/guide/toc.yml +++ b/src/main/docs/guide/toc.yml @@ -28,6 +28,7 @@ sdkv2: s3: S3 dynamodb: Dynamo DB ses: SES + lambdaClient: Lambda Client sns: SNS sqs: SQS ssm: SSM From 3e446f5c2b06276eaf7a322fcb0c6c60893bd6c4 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 12:08:50 +0200 Subject: [PATCH 18/50] dependencies should be testImplementation --- function-client-aws-v2/build.gradle.kts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/function-client-aws-v2/build.gradle.kts b/function-client-aws-v2/build.gradle.kts index d0c2290efd..206618f954 100644 --- a/function-client-aws-v2/build.gradle.kts +++ b/function-client-aws-v2/build.gradle.kts @@ -16,10 +16,8 @@ dependencies { testImplementation(mnGroovy.micronaut.function.groovy) testImplementation(mnGroovy.micronaut.runtime.groovy) testImplementation(libs.commons.compress) - // TODO: Switch to Test Resources, once Lambda Client is also included in Service Override - implementation(platform(libs.boms.testcontainers)) - implementation(libs.testcontainers) - implementation(libs.testcontainers.localstack) - implementation(libs.testcontainers.junit) - implementation(libs.testcontainers.spock) + testImplementation(platform(mnTestResources.boms.testcontainers)) + testImplementation(libs.testcontainers) + testImplementation(libs.testcontainers.localstack) + testImplementation(libs.testcontainers.spock) } From 7d6c3cf755330eb5ecb7821e518cab8496eb899f Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 12:09:15 +0200 Subject: [PATCH 19/50] remove testContainers version --- gradle/libs.versions.toml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c0c4a3c020..e7fac07352 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,9 +45,6 @@ kotlin = "1.9.24" # Micronaut micronaut-gradle-plugin = "4.4.0" -# Test Containers -testcontainers = "1.19.8" - commons-compress = "1.26.2" [libraries] @@ -90,7 +87,6 @@ kotlin-stdlib-jdk8 = { module = 'org.jetbrains.kotlin:kotlin-stdlib-jdk8', versi boms-aws-java-sdk-v1 = { module = 'com.amazonaws:aws-java-sdk-bom', version.ref = 'managed-aws-java-sdk-v1' } boms-aws-java-sdk-v2 = { module = 'software.amazon.awssdk:bom', version.ref = 'managed-aws-java-sdk-v2' } -boms-testcontainers = { module = 'org.testcontainers:testcontainers-bom', version.ref = 'testcontainers' } bouncycastle-provider = { module = 'org.bouncycastle:bcprov-jdk15on', version.ref = 'bouncycastle'} fileupload = { module = 'org.javadelight:delight-fileupload', version.ref = 'fileupload' } @@ -126,9 +122,9 @@ servlet-api = { module = 'javax.servlet:servlet-api', version.ref = 'servlet-api gradle-micronaut = { module = "io.micronaut.gradle:micronaut-gradle-plugin", version.ref = "micronaut-gradle-plugin" } gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } -testcontainers = { module = "org.testcontainers:testcontainers", version.ref = "testcontainers" } -testcontainers-localstack = { module = "org.testcontainers:localstack", version.ref = "testcontainers" } -testcontainers-junit = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" } -testcontainers-spock = { module = "org.testcontainers:spock", version.ref = "testcontainers" } +testcontainers = { module = "org.testcontainers:testcontainers" } +testcontainers-localstack = { module = "org.testcontainers:localstack" } +testcontainers-junit = { module = "org.testcontainers:junit-jupiter" } +testcontainers-spock = { module = "org.testcontainers:spock" } commons-compress = { module = "org.apache.commons:commons-compress", version.ref = "commons-compress" } From 7545215d3b33e18474b794e7db8666699b3fb4b9 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 12:09:35 +0200 Subject: [PATCH 20/50] doc: how to use function-client-v2 --- src/main/docs/guide/lambda/lambdafunctionclient.adoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/docs/guide/lambda/lambdafunctionclient.adoc b/src/main/docs/guide/lambda/lambdafunctionclient.adoc index 3f4cf86828..3580b624a4 100644 --- a/src/main/docs/guide/lambda/lambdafunctionclient.adoc +++ b/src/main/docs/guide/lambda/lambdafunctionclient.adoc @@ -1,6 +1,10 @@ Micronaut AWS provides support for invoking AWS Lambda functions within a Micronaut application context. -To use the features described in this section, you will need to have the `micronaut-function-client-aws` dependency on your classpath. +To use the features described in this section, you will need to have the following dependency on your classpath: + +dependency:micronaut-function-client-aws-v2[groupId="io.micronaut.aws"] + +or for AWS SDK v1: dependency:micronaut-function-client-aws[groupId="io.micronaut.aws"] From 9d51b0f14f016fc1c7af1de7179ff506e1232d08 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 12:09:56 +0200 Subject: [PATCH 21/50] use micronautFunctionClientAwsV2 in test-suite --- test-suite-groovy/build.gradle.kts | 2 +- test-suite-kotlin/build.gradle.kts | 2 +- test-suite/build.gradle.kts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test-suite-groovy/build.gradle.kts b/test-suite-groovy/build.gradle.kts index 5d263f217b..5d496ab412 100644 --- a/test-suite-groovy/build.gradle.kts +++ b/test-suite-groovy/build.gradle.kts @@ -9,7 +9,7 @@ dependencies { testImplementation(mnTest.micronaut.test.spock) testImplementation(platform(mn.micronaut.core.bom)) testImplementation(projects.micronautFunctionAws) - testImplementation(projects.micronautFunctionClientAws) + testImplementation(projects.micronautFunctionClientAwsV2) testRuntimeOnly(mn.snakeyaml) } diff --git a/test-suite-kotlin/build.gradle.kts b/test-suite-kotlin/build.gradle.kts index c423ba56a2..175c4cbe43 100644 --- a/test-suite-kotlin/build.gradle.kts +++ b/test-suite-kotlin/build.gradle.kts @@ -14,7 +14,7 @@ dependencies { testRuntimeOnly(libs.junit.jupiter.engine) testImplementation(projects.micronautFunctionAws) testImplementation(libs.kotlin.stdlib.jdk8) - testImplementation(projects.micronautFunctionClientAws) + testImplementation(projects.micronautFunctionClientAwsV2) testRuntimeOnly(mn.snakeyaml) } diff --git a/test-suite/build.gradle.kts b/test-suite/build.gradle.kts index f6339f4ffa..98872291df 100644 --- a/test-suite/build.gradle.kts +++ b/test-suite/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } dependencies { testImplementation(projects.micronautFunctionAws) - testImplementation(projects.micronautFunctionClientAws) + testImplementation(projects.micronautFunctionClientAwsV2) } tasks { From a704fde6b0d5fac9b6be329e7ec083efb03f4038 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 12:19:04 +0200 Subject: [PATCH 22/50] add logback to src/test/resources --- .../src/test/resources/logback.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 function-client-aws-v2/src/test/resources/logback.xml diff --git a/function-client-aws-v2/src/test/resources/logback.xml b/function-client-aws-v2/src/test/resources/logback.xml new file mode 100644 index 0000000000..80dcc40c8d --- /dev/null +++ b/function-client-aws-v2/src/test/resources/logback.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file From b6de86096333a7e7f80402db6053fb25b1f01987 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 12:32:47 +0200 Subject: [PATCH 23/50] =?UTF-8?q?don=E2=80=99t=20use=20compress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- function-client-aws-v2/build.gradle.kts | 1 - .../client/aws/TestFunctionSpec.groovy | 100 ++++++++++-------- gradle/libs.versions.toml | 4 - 3 files changed, 57 insertions(+), 48 deletions(-) diff --git a/function-client-aws-v2/build.gradle.kts b/function-client-aws-v2/build.gradle.kts index 206618f954..d8d4b9b71f 100644 --- a/function-client-aws-v2/build.gradle.kts +++ b/function-client-aws-v2/build.gradle.kts @@ -15,7 +15,6 @@ dependencies { testImplementation(mn.micronaut.function.web) testImplementation(mnGroovy.micronaut.function.groovy) testImplementation(mnGroovy.micronaut.runtime.groovy) - testImplementation(libs.commons.compress) testImplementation(platform(mnTestResources.boms.testcontainers)) testImplementation(libs.testcontainers) testImplementation(libs.testcontainers.localstack) diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy index d94e96488f..9f1bfdb44e 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy @@ -4,8 +4,6 @@ import io.micronaut.core.io.ResourceLoader import io.micronaut.test.extensions.spock.annotation.MicronautTest import io.micronaut.test.support.TestPropertyProvider import jakarta.inject.Inject -import org.apache.commons.compress.archivers.ArchiveOutputStream -import org.apache.commons.compress.archivers.ArchiveStreamFactory import org.testcontainers.containers.localstack.LocalStackContainer import org.testcontainers.spock.Testcontainers import org.testcontainers.utility.DockerImageName @@ -15,11 +13,15 @@ import software.amazon.awssdk.services.lambda.model.Architecture import software.amazon.awssdk.services.lambda.model.CreateFunctionRequest import software.amazon.awssdk.services.lambda.model.DeleteFunctionRequest import software.amazon.awssdk.services.lambda.model.FunctionCode +import software.amazon.awssdk.services.lambda.model.LambdaRequest import software.amazon.awssdk.services.lambda.model.Runtime import spock.lang.Shared import spock.lang.Specification import java.nio.file.Files +import java.nio.file.Path +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream import static org.testcontainers.containers.localstack.LocalStackContainer.Service.LAMBDA @@ -27,12 +29,12 @@ import static org.testcontainers.containers.localstack.LocalStackContainer.Servi @MicronautTest class TestFunctionSpec extends Specification implements TestPropertyProvider { - private static final String FUNCTION_NAME = "TEST_FUNCTION_NAME"; + private static final String FUNCTION_NAME = "TEST_FUNCTION_NAME" @Shared private LocalStackContainer localStackContainer = new LocalStackContainer(DockerImageName .parse("localstack/localstack:3.4.0")) - .withServices(LAMBDA); + .withServices(LAMBDA) @Inject @Shared @@ -44,59 +46,40 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { @Override Map getProperties() { - return Map.of( - "aws.accessKeyId", localStackContainer.getAccessKey(), - "aws.secretKey", localStackContainer.getSecretKey(), + Map.of( + "aws.access-key-id", localStackContainer.getAccessKey(), + "aws.secret-key", localStackContainer.getSecretKey(), "aws.region", localStackContainer.getRegion(), - "aws.services.lambda.endpoint-override", localStackContainer.getEndpointOverride(LAMBDA) - ) + "aws.services.lambda.endpoint-override", localStackContainer.getEndpointOverride(LAMBDA).toString() + ) as Map } @Inject - TestFunctionClient functionClient; + TestFunctionClient functionClient def setupSpec() { - def resource = resourceLoader.getResource("classpath:lambda").orElseThrow() - def tempFile = File.createTempFile(UUID.randomUUID().toString(), UUID.randomUUID().toString()) - tempFile.deleteOnExit() - - def outputStream = new FileOutputStream(tempFile) - - ArchiveOutputStream archive = new ArchiveStreamFactory() - .createArchiveOutputStream(ArchiveStreamFactory.ZIP, outputStream); - - Arrays.stream(new File(resource.toURI()).listFiles()) - .forEach { file -> - archive.createArchiveEntry(file, file.getName()) - } - - archive.finish() - - lambdaClient.createFunction(CreateFunctionRequest.builder() - .functionName(FUNCTION_NAME) - .code(FunctionCode.builder() - .zipFile(SdkBytes.fromByteArray(Files.readAllBytes(tempFile.toPath()))) - .build()) - .runtime(Runtime.NODEJS20_X) - .architectures(Architecture.X86_64) - .handler("index.handler") - .build()) + byte[] bytes = lambdaBytes(resourceLoader) + LambdaRequest lambdaRequest = createFunctionRequest(bytes) + if (lambdaRequest instanceof CreateFunctionRequest) { + lambdaClient.createFunction((CreateFunctionRequest) lambdaRequest) + } } def cleanupSpec() { - lambdaClient.deleteFunction(DeleteFunctionRequest.builder() - .functionName(FUNCTION_NAME) - .build()) + LambdaRequest lambdaRequest = deleteFunctionRequest() + if (lambdaRequest instanceof DeleteFunctionRequest) { + lambdaClient.deleteFunction((DeleteFunctionRequest) lambdaRequest) + } } - def "foo"() { + def "can invoke a JS Lambda function with the an @FunctionClient"() { given: - def aNumber = 1 - def aString = "someString" + Integer aNumber = 1 + String aString = "someString" when: - def result = functionClient - .invokeFunction(new TestFunctionClientRequest(aNumber, aNumber, new ComplexType(aNumber, aString))) + TestFunctionClientResponse result = functionClient + .invokeFunction(new TestFunctionClientRequest(aNumber, aString, new ComplexType(aNumber, aString))) then: result.aNumber == aNumber @@ -109,4 +92,35 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { result.anArray[0].aString == aString } + private static byte[] lambdaBytes(ResourceLoader resourceLoader) { + try (InputStream inputStream = resourceLoader.getResourceAsStream("classpath:lambda/index.js.zip").orElseThrow()) { + byte[] fileBytes = inputStream.readAllBytes() + Path tempFile = Files.createTempFile(FUNCTION_NAME, ".zip"); + try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(tempFile))) { + ZipEntry zipEntry = new ZipEntry("index.js") + zos.putNextEntry(zipEntry) + zos.write(fileBytes) + zos.closeEntry() + } + return Files.readAllBytes(tempFile); + } + } + + private static LambdaRequest createFunctionRequest(byte[] arr) { + CreateFunctionRequest.builder() + .functionName(FUNCTION_NAME) + .code(FunctionCode.builder() + .zipFile(SdkBytes.fromByteArray(arr)) + .build()) + .runtime(Runtime.NODEJS20_X) + .architectures(Architecture.X86_64) + .handler("index.handler") + .build() + } + + private static LambdaRequest deleteFunctionRequest() { + DeleteFunctionRequest.builder() + .functionName(FUNCTION_NAME) + .build() + } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e7fac07352..9396ff56da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,8 +45,6 @@ kotlin = "1.9.24" # Micronaut micronaut-gradle-plugin = "4.4.0" -commons-compress = "1.26.2" - [libraries] # Core @@ -126,5 +124,3 @@ testcontainers = { module = "org.testcontainers:testcontainers" } testcontainers-localstack = { module = "org.testcontainers:localstack" } testcontainers-junit = { module = "org.testcontainers:junit-jupiter" } testcontainers-spock = { module = "org.testcontainers:spock" } - -commons-compress = { module = "org.apache.commons:commons-compress", version.ref = "commons-compress" } From 91c9b78486c20a3ffddad883188cc6b37dfb26cb Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Mon, 1 Jul 2024 12:33:53 +0200 Subject: [PATCH 24/50] remove zip --- .../io/micronaut/function/client/aws/TestFunctionSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy index 9f1bfdb44e..b249d4cdc1 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy @@ -93,7 +93,7 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { } private static byte[] lambdaBytes(ResourceLoader resourceLoader) { - try (InputStream inputStream = resourceLoader.getResourceAsStream("classpath:lambda/index.js.zip").orElseThrow()) { + try (InputStream inputStream = resourceLoader.getResourceAsStream("classpath:lambda/index.js").orElseThrow()) { byte[] fileBytes = inputStream.readAllBytes() Path tempFile = Files.createTempFile(FUNCTION_NAME, ".zip"); try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(tempFile))) { From 6fb0c0e0d0a524c51690473f47665cbc8a924e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Duarte?= Date: Wed, 3 Jul 2024 16:14:09 +0000 Subject: [PATCH 25/50] Fix lambda code --- .../src/test/resources/lambda/index.js | 38 +++++-------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/function-client-aws-v2/src/test/resources/lambda/index.js b/function-client-aws-v2/src/test/resources/lambda/index.js index 2c2b2a30b8..a9c8b20423 100644 --- a/function-client-aws-v2/src/test/resources/lambda/index.js +++ b/function-client-aws-v2/src/test/resources/lambda/index.js @@ -1,37 +1,17 @@ -/* -Contract: - -interface ComplexObject { - aNumber int - aString string -} - -interface Request { - aNumber int - aString string - aObject ComplexObject -} - -interface Response { - aNumber int - aString string - aObject ComplexObject - anArray []ComplexObject -} -*/ - -exports.handler = async function (event, context) { +exports.handler = async (event, context) => { if (!event.aNumber || !event.aString || !event.aObject || !event.aObject.aNumber || !event.aObject.aString) { throw new Error('Invalid Input'); } - var arr = []; + const arr = []; arr.push(event.aObject); - return { - aNumber: event.aNumber, - aString: event.aString, - aObject: event.aObject, - anArray: arr, + const response = { + aNumber: event.aNumber, + aString: event.aString, + aObject: event.aObject, + anArray: arr, }; + + return response }; From 1b6d77097a7cac600eed5fe5ae908094258fbaf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Duarte?= Date: Wed, 3 Jul 2024 16:14:35 +0000 Subject: [PATCH 26/50] Add AWS SDK IAM to Tests --- function-client-aws-v2/build.gradle.kts | 2 ++ gradle/libs.versions.toml | 1 + 2 files changed, 3 insertions(+) diff --git a/function-client-aws-v2/build.gradle.kts b/function-client-aws-v2/build.gradle.kts index d8d4b9b71f..20b20b3610 100644 --- a/function-client-aws-v2/build.gradle.kts +++ b/function-client-aws-v2/build.gradle.kts @@ -19,4 +19,6 @@ dependencies { testImplementation(libs.testcontainers) testImplementation(libs.testcontainers.localstack) testImplementation(libs.testcontainers.spock) + testImplementation(libs.awssdk.iam) + testRuntimeOnly(mn.snakeyaml) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9396ff56da..a004243603 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -79,6 +79,7 @@ awssdk-ses = { module = 'software.amazon.awssdk:ses' } awssdk-sns = { module = 'software.amazon.awssdk:sns' } awssdk-sqs = { module = 'software.amazon.awssdk:sqs' } awssdk-ssm = { module = 'software.amazon.awssdk:ssm' } +awssdk-iam = { module = 'software.amazon.awssdk:iam' } awssdk-url-connection-client = { module = 'software.amazon.awssdk:url-connection-client' } kotlin-stdlib-jdk8 = { module = 'org.jetbrains.kotlin:kotlin-stdlib-jdk8', version.ref = 'kotlin' } From bec81a318261a26c2478ad1d21091686b852d036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Duarte?= Date: Wed, 3 Jul 2024 16:14:54 +0000 Subject: [PATCH 27/50] Remove @Internal from Lambda Factory --- .../aws/sdk/v2/service/lambda/LambdaClientFactory.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java index 90b04b62b9..864ccce541 100644 --- a/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java +++ b/aws-sdk-v2/src/main/java/io/micronaut/aws/sdk/v2/service/lambda/LambdaClientFactory.java @@ -21,7 +21,6 @@ import io.micronaut.context.annotation.Bean; import io.micronaut.context.annotation.Factory; import io.micronaut.context.annotation.Requires; -import io.micronaut.core.annotation.Internal; import io.micronaut.core.annotation.Nullable; import jakarta.inject.Named; import jakarta.inject.Singleton; @@ -39,7 +38,6 @@ * @since 4.7.0 */ @Factory -@Internal class LambdaClientFactory extends AwsClientFactory { /** * Constructor. From 1b353024236a2055afb66431f5d4111ba50d26dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Duarte?= Date: Wed, 3 Jul 2024 16:15:36 +0000 Subject: [PATCH 28/50] Properly Map Lambda Function Name and extra attributes --- .../aws/AwsInvokeRequestDefinition.java | 33 +++++ .../client/aws/AwsLambdaFunctionExecutor.java | 9 +- .../client/aws/TestFunctionSpec.groovy | 125 +++++++++++++++--- 3 files changed, 146 insertions(+), 21 deletions(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java index 9bc9295096..1cecaedb2a 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java @@ -17,6 +17,7 @@ import io.micronaut.context.annotation.EachProperty; import io.micronaut.context.annotation.Parameter; +import io.micronaut.core.annotation.Introspected; import io.micronaut.function.client.FunctionDefinition; /** @@ -24,14 +25,22 @@ * * @since 4.7.0 */ +@Introspected @EachProperty(AwsInvokeRequestDefinition.AWS_LAMBDA_FUNCTIONS) public class AwsInvokeRequestDefinition implements FunctionDefinition { public static final String AWS_LAMBDA_FUNCTIONS = "aws.lambda.functions"; private final String name; + private String functionName; + + private String qualifier; + + private String clientContext; + /** * Constructor. + * * @param name configured name from a property */ public AwsInvokeRequestDefinition(@Parameter String name) { @@ -42,4 +51,28 @@ public AwsInvokeRequestDefinition(@Parameter String name) { public String getName() { return this.name; } + + public String getFunctionName() { + return functionName; + } + + public String getQualifier() { + return qualifier; + } + + public String getClientContext() { + return clientContext; + } + + public void setFunctionName(String functionName) { + this.functionName = functionName; + } + + public void setQualifier(String qualifier) { + this.qualifier = qualifier; + } + + public void setClientContext(String clientContext) { + this.clientContext = clientContext; + } } diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java index 67d89be654..81a09ce124 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java @@ -88,10 +88,17 @@ public O invoke(FunctionDefinition definition, I input, Argument outputType) boolean isReactiveType = Publishers.isConvertibleToPublisher(outputType.getType()); SdkBytes sdkBytes = encodeInput(input); + + AwsInvokeRequestDefinition awsInvokeRequestDefinition = + (AwsInvokeRequestDefinition) definition; + InvokeRequest invokeRequest = InvokeRequest.builder() - .functionName(definition.getName()) + .functionName(awsInvokeRequestDefinition.getFunctionName()) + .qualifier(awsInvokeRequestDefinition.getQualifier()) + .clientContext(awsInvokeRequestDefinition.getClientContext()) .payload(sdkBytes) .build(); + if (isReactiveType) { Mono invokeFlowable = Mono.fromFuture(asyncClient.invoke(invokeRequest)) .map(invokeResult -> diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy index b249d4cdc1..375f54da4b 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy @@ -7,14 +7,17 @@ import jakarta.inject.Inject import org.testcontainers.containers.localstack.LocalStackContainer import org.testcontainers.spock.Testcontainers import org.testcontainers.utility.DockerImageName +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials +import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain import software.amazon.awssdk.core.SdkBytes +import software.amazon.awssdk.regions.Region +import software.amazon.awssdk.services.iam.IamClient +import software.amazon.awssdk.services.iam.model.CreatePolicyRequest +import software.amazon.awssdk.services.iam.model.Role +import software.amazon.awssdk.services.iam.waiters.IamWaiter import software.amazon.awssdk.services.lambda.LambdaClient -import software.amazon.awssdk.services.lambda.model.Architecture import software.amazon.awssdk.services.lambda.model.CreateFunctionRequest -import software.amazon.awssdk.services.lambda.model.DeleteFunctionRequest -import software.amazon.awssdk.services.lambda.model.FunctionCode import software.amazon.awssdk.services.lambda.model.LambdaRequest -import software.amazon.awssdk.services.lambda.model.Runtime import spock.lang.Shared import spock.lang.Specification @@ -23,6 +26,7 @@ import java.nio.file.Path import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream +import static org.testcontainers.containers.localstack.LocalStackContainer.Service.IAM import static org.testcontainers.containers.localstack.LocalStackContainer.Service.LAMBDA @Testcontainers @@ -34,7 +38,7 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { @Shared private LocalStackContainer localStackContainer = new LocalStackContainer(DockerImageName .parse("localstack/localstack:3.4.0")) - .withServices(LAMBDA) + .withServices(IAM, LAMBDA) @Inject @Shared @@ -58,17 +62,23 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { TestFunctionClient functionClient def setupSpec() { - byte[] bytes = lambdaBytes(resourceLoader) - LambdaRequest lambdaRequest = createFunctionRequest(bytes) - if (lambdaRequest instanceof CreateFunctionRequest) { - lambdaClient.createFunction((CreateFunctionRequest) lambdaRequest) - } - } - - def cleanupSpec() { - LambdaRequest lambdaRequest = deleteFunctionRequest() - if (lambdaRequest instanceof DeleteFunctionRequest) { - lambdaClient.deleteFunction((DeleteFunctionRequest) lambdaRequest) + try { + lambdaClient.getFunction(GetFunctionRequest.builder() + .functionName(FUNCTION_NAME) + .build()) + } catch(Exception e) { + // Create if not exists + byte[] bytes = lambdaBytes(resourceLoader) + LambdaRequest lambdaRequest = createFunctionRequest(bytes) + if (lambdaRequest instanceof CreateFunctionRequest) { + def waiter = lambdaClient.waiter() + + def function = lambdaClient.createFunction((CreateFunctionRequest) lambdaRequest) + + waiter.waitUntilFunctionExists(GetFunctionRequest.builder() + .functionName(function.functionName()) + .build()) + } } } @@ -92,7 +102,7 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { result.anArray[0].aString == aString } - private static byte[] lambdaBytes(ResourceLoader resourceLoader) { + private byte[] lambdaBytes(ResourceLoader resourceLoader) { try (InputStream inputStream = resourceLoader.getResourceAsStream("classpath:lambda/index.js").orElseThrow()) { byte[] fileBytes = inputStream.readAllBytes() Path tempFile = Files.createTempFile(FUNCTION_NAME, ".zip"); @@ -106,19 +116,94 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { } } - private static LambdaRequest createFunctionRequest(byte[] arr) { + private Role getLambdaRole() { + def iamClient = IamClient.builder() + .region(Region.of(localStackContainer.getRegion())) + .credentialsProvider(AwsCredentialsProviderChain.of( + () -> AwsBasicCredentials.create(localStackContainer.getAccessKey(), localStackContainer.getSecretKey()) + )) + .endpointOverride(localStackContainer.getEndpointOverride(IAM)) + .build() + def roleName = "lambda-role"; + try { + return iamClient.getRole(GetRoleRequest.builder() + .roleName(roleName) + .build()).role(); + } catch (final Exception e) { + // Create if not exists + IamWaiter iamWaiter = iamClient.waiter(); + + CreatePolicyRequest request = CreatePolicyRequest.builder() + .policyName("lambda-invoke-policy") + .policyDocument(""" + { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "LambdaInvoke", + "Effect": "Allow", + "Action": [ + "lambda:InvokeFunction" + ], + "Resource": "*" + } + ] + } + """.stripIndent()) + .build(); + + def policy = iamClient.createPolicy(request) + iamWaiter.waitUntilPolicyExists(GetPolicyRequest.builder() + .policyArn(policy.policy().arn()) + .build()); + + def role = iamClient.createRole(CreateRoleRequest.builder() + .roleName(roleName) + .path("/") + .assumeRolePolicyDocument(""" + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + } + """.stripIndent()) + .build()) + + iamWaiter.waitUntilRoleExists(GetRoleRequest.builder() + .roleName(role.role().roleName()) + .build()) + + iamClient.attachRolePolicy(AttachRolePolicyRequest.builder() + .roleName(role.role().roleName()) + .policyArn(policy.policy().arn()) + .build()) + + return role.role(); + } + } + + private LambdaRequest createFunctionRequest(byte[] arr) { + def role = getLambdaRole() CreateFunctionRequest.builder() .functionName(FUNCTION_NAME) + .role(role.arn()) .code(FunctionCode.builder() .zipFile(SdkBytes.fromByteArray(arr)) .build()) - .runtime(Runtime.NODEJS20_X) + .runtime(Runtime.NODEJS18_X) .architectures(Architecture.X86_64) .handler("index.handler") .build() } - private static LambdaRequest deleteFunctionRequest() { + private LambdaRequest deleteFunctionRequest() { DeleteFunctionRequest.builder() .functionName(FUNCTION_NAME) .build() From e51547aca8ab8e862a21d8ccd7b886f579a75814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Duarte?= Date: Wed, 3 Jul 2024 16:16:03 +0000 Subject: [PATCH 29/50] Fix failing tests --- test-suite/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-suite/build.gradle.kts b/test-suite/build.gradle.kts index 98872291df..f6339f4ffa 100644 --- a/test-suite/build.gradle.kts +++ b/test-suite/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } dependencies { testImplementation(projects.micronautFunctionAws) - testImplementation(projects.micronautFunctionClientAwsV2) + testImplementation(projects.micronautFunctionClientAws) } tasks { From 1af4c149cd8ce78ccfea8aa837f0057aada3d87b Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:04:23 +0200 Subject: [PATCH 30/50] change javadoc --- .../java/io/micronaut/function/client/aws/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java index a7fc7acc37..7785166e37 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * Function AWS lamda configuration. + * AWS Lambda Function Client related classes. * * @since 4.7.0 */ From fd01b8200aa62de2938371ebf8ffdd9ae18995aa Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 12:38:21 +0200 Subject: [PATCH 31/50] revert v2 dependency --- test-suite-groovy/build.gradle.kts | 2 +- test-suite-kotlin/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test-suite-groovy/build.gradle.kts b/test-suite-groovy/build.gradle.kts index 5d496ab412..5d263f217b 100644 --- a/test-suite-groovy/build.gradle.kts +++ b/test-suite-groovy/build.gradle.kts @@ -9,7 +9,7 @@ dependencies { testImplementation(mnTest.micronaut.test.spock) testImplementation(platform(mn.micronaut.core.bom)) testImplementation(projects.micronautFunctionAws) - testImplementation(projects.micronautFunctionClientAwsV2) + testImplementation(projects.micronautFunctionClientAws) testRuntimeOnly(mn.snakeyaml) } diff --git a/test-suite-kotlin/build.gradle.kts b/test-suite-kotlin/build.gradle.kts index 175c4cbe43..c423ba56a2 100644 --- a/test-suite-kotlin/build.gradle.kts +++ b/test-suite-kotlin/build.gradle.kts @@ -14,7 +14,7 @@ dependencies { testRuntimeOnly(libs.junit.jupiter.engine) testImplementation(projects.micronautFunctionAws) testImplementation(libs.kotlin.stdlib.jdk8) - testImplementation(projects.micronautFunctionClientAwsV2) + testImplementation(projects.micronautFunctionClientAws) testRuntimeOnly(mn.snakeyaml) } From cd944236f6b03c3d77176951469fc9e8a02c394b Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 12:47:35 +0200 Subject: [PATCH 32/50] set AwsLambdaFunctionExecutor as @Internal --- .../function/client/aws/AwsLambdaFunctionExecutor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java index 81a09ce124..29331a7ec7 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java @@ -16,6 +16,7 @@ package io.micronaut.function.client.aws; import io.micronaut.context.annotation.Requires; +import io.micronaut.core.annotation.Internal; import io.micronaut.core.async.publisher.Publishers; import io.micronaut.core.convert.ConversionService; import io.micronaut.core.io.buffer.ByteBufferFactory; @@ -50,6 +51,7 @@ */ @Requires(beans = LambdaAsyncClient.class) @Singleton +@Internal public class AwsLambdaFunctionExecutor implements FunctionInvoker, FunctionInvokerChooser { private static final int STATUS_CODE_ERROR = 300; From 3be9d9cc81187c532d68c20b64bb487c22c45030 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 12:54:04 +0200 Subject: [PATCH 33/50] dont add jackson.databind use JsonMediaTypeCodec --- function-client-aws-v2/build.gradle.kts | 1 - .../client/aws/AwsLambdaFunctionExecutor.java | 14 +++++++------- .../function/client/aws/TestFunctionSpec.groovy | 15 ++++++++++++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/function-client-aws-v2/build.gradle.kts b/function-client-aws-v2/build.gradle.kts index 20b20b3610..692de96bfa 100644 --- a/function-client-aws-v2/build.gradle.kts +++ b/function-client-aws-v2/build.gradle.kts @@ -7,7 +7,6 @@ dependencies { implementation(libs.awssdk.lambda) implementation(mn.reactor) api(mn.micronaut.function.client) - implementation(mn.micronaut.jackson.databind) testAnnotationProcessor(mn.micronaut.inject.java) testImplementation(mn.micronaut.inject.java) testImplementation(mnSerde.micronaut.serde.api) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java index 29331a7ec7..6b2cf57342 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java @@ -25,7 +25,7 @@ import io.micronaut.function.client.FunctionInvoker; import io.micronaut.function.client.FunctionInvokerChooser; import io.micronaut.function.client.exceptions.FunctionExecutionException; -import io.micronaut.jackson.codec.JsonMediaTypeCodec; +import io.micronaut.json.codec.JsonMediaTypeCodec; import io.micronaut.scheduling.TaskExecutors; import jakarta.inject.Named; import jakarta.inject.Singleton; @@ -58,7 +58,7 @@ public class AwsLambdaFunctionExecutor implements FunctionInvoker, F private final LambdaClient syncClient; private final LambdaAsyncClient asyncClient; private final ByteBufferFactory byteBufferFactory; - private final JsonMediaTypeCodec jsonMediaTypeCodec; + private final JsonMediaTypeCodec mediaTypeCodec; private final ExecutorService ioExecutor; /** @@ -66,19 +66,19 @@ public class AwsLambdaFunctionExecutor implements FunctionInvoker, F * * @param asyncClient asyncClient * @param byteBufferFactory byteBufferFactory - * @param jsonMediaTypeCodec jsonMediaTypeCodec + * @param mediaTypeCodec JsonMediaTypeCodec * @param ioExecutor ioExecutor */ protected AwsLambdaFunctionExecutor( LambdaClient syncClient, LambdaAsyncClient asyncClient, ByteBufferFactory byteBufferFactory, - JsonMediaTypeCodec jsonMediaTypeCodec, + JsonMediaTypeCodec mediaTypeCodec, @Named(TaskExecutors.IO) ExecutorService ioExecutor) { this.syncClient = syncClient; this.asyncClient = asyncClient; this.byteBufferFactory = byteBufferFactory; - this.jsonMediaTypeCodec = jsonMediaTypeCodec; + this.mediaTypeCodec = mediaTypeCodec; this.ioExecutor = ioExecutor; } @@ -125,12 +125,12 @@ private Object decodeResult(FunctionDefinition definition, Argument outputTyp } io.micronaut.core.io.buffer.ByteBuffer byteBuffer = byteBufferFactory.copiedBuffer(invokeResult.payload().asByteArray()); - return jsonMediaTypeCodec.decode(outputType, byteBuffer); + return mediaTypeCodec.decode(outputType, byteBuffer); } private SdkBytes encodeInput(I input) { if (input != null) { - ByteBuffer nioBuffer = jsonMediaTypeCodec.encode(input, byteBufferFactory).asNioBuffer(); + ByteBuffer nioBuffer = mediaTypeCodec.encode(input, byteBufferFactory).asNioBuffer(); return SdkBytes.fromByteBuffer(nioBuffer); } return null; diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy index 375f54da4b..d0b637832f 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy @@ -12,11 +12,22 @@ import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain import software.amazon.awssdk.core.SdkBytes import software.amazon.awssdk.regions.Region import software.amazon.awssdk.services.iam.IamClient +import software.amazon.awssdk.services.iam.model.AttachRolePolicyRequest import software.amazon.awssdk.services.iam.model.CreatePolicyRequest +import software.amazon.awssdk.services.iam.model.CreateRoleRequest +import software.amazon.awssdk.services.iam.model.GetPolicyRequest +import software.amazon.awssdk.services.iam.model.GetRoleRequest import software.amazon.awssdk.services.iam.model.Role import software.amazon.awssdk.services.iam.waiters.IamWaiter import software.amazon.awssdk.services.lambda.LambdaClient +import software.amazon.awssdk.services.lambda.model.Architecture import software.amazon.awssdk.services.lambda.model.CreateFunctionRequest +import software.amazon.awssdk.services.lambda.model.DeleteFunctionRequest +import software.amazon.awssdk.services.lambda.model.FunctionCode +import software.amazon.awssdk.services.lambda.model.GetFunctionConcurrencyRequest +import software.amazon.awssdk.services.lambda.model.GetFunctionConfigurationRequest +import software.amazon.awssdk.services.lambda.model.Runtime +import software.amazon.awssdk.services.lambda.model.GetFunctionRequest import software.amazon.awssdk.services.lambda.model.LambdaRequest import spock.lang.Shared import spock.lang.Specification @@ -74,10 +85,12 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { def waiter = lambdaClient.waiter() def function = lambdaClient.createFunction((CreateFunctionRequest) lambdaRequest) - waiter.waitUntilFunctionExists(GetFunctionRequest.builder() .functionName(function.functionName()) .build()) + GetFunctionConfigurationRequest getFunctionConfigurationRequest = + GetFunctionConfigurationRequest.builder().functionName(function.functionName()).build() + waiter.waitUntilFunctionActive(getFunctionConfigurationRequest) } } } From b8d9c5157267f82e83f14097891d1b27af10ea15 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:01:40 +0200 Subject: [PATCH 34/50] move to package v2 --- .../client/aws/{ => v2}/AwsInvokeRequestDefinition.java | 2 +- .../client/aws/{ => v2}/AwsLambdaFunctionExecutor.java | 2 +- .../function/client/aws/{ => v2}/package-info.java | 6 +++++- .../micronaut/function/client/aws/{ => v2}/ComplexType.java | 2 +- .../function/client/aws/{ => v2}/TestFunctionClient.java | 2 +- .../client/aws/{ => v2}/TestFunctionClientRequest.java | 2 +- .../client/aws/{ => v2}/TestFunctionClientResponse.java | 2 +- .../function/client/aws/{ => v2}/TestFunctionSpec.groovy | 3 +-- 8 files changed, 12 insertions(+), 9 deletions(-) rename function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/{ => v2}/AwsInvokeRequestDefinition.java (97%) rename function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/{ => v2}/AwsLambdaFunctionExecutor.java (99%) rename function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/{ => v2}/package-info.java (67%) rename function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/{ => v2}/ComplexType.java (92%) rename function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/{ => v2}/TestFunctionClient.java (95%) rename function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/{ => v2}/TestFunctionClientRequest.java (97%) rename function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/{ => v2}/TestFunctionClientResponse.java (97%) rename function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/{ => v2}/TestFunctionSpec.groovy (98%) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java similarity index 97% rename from function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java rename to function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java index 1cecaedb2a..8f208c6b94 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsInvokeRequestDefinition.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.function.client.aws; +package io.micronaut.function.client.aws.v2; import io.micronaut.context.annotation.EachProperty; import io.micronaut.context.annotation.Parameter; diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java similarity index 99% rename from function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java rename to function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java index 6b2cf57342..0670be891b 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.function.client.aws; +package io.micronaut.function.client.aws.v2; import io.micronaut.context.annotation.Requires; import io.micronaut.core.annotation.Internal; diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/package-info.java similarity index 67% rename from function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java rename to function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/package-info.java index 7785166e37..5c9f8da942 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/package-info.java @@ -14,9 +14,13 @@ * limitations under the License. */ /** +<<<<<<< HEAD:function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java * AWS Lambda Function Client related classes. +======= + * AWS Lambda Function Client related classes. +>>>>>>> f00002268 (move to package v2):function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/package-info.java * * @since 4.7.0 */ -package io.micronaut.function.client.aws; +package io.micronaut.function.client.aws.v2; diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/ComplexType.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/ComplexType.java similarity index 92% rename from function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/ComplexType.java rename to function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/ComplexType.java index ad0fffd240..27b8f5dc1f 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/ComplexType.java +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/ComplexType.java @@ -1,4 +1,4 @@ -package io.micronaut.function.client.aws; +package io.micronaut.function.client.aws.v2; import io.micronaut.serde.annotation.Serdeable; diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClient.java similarity index 95% rename from function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java rename to function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClient.java index 32272c5ae3..eae81ddf68 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClient.java +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClient.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.function.client.aws; +package io.micronaut.function.client.aws.v2; //tag::imports[] import io.micronaut.function.client.FunctionClient; diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientRequest.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientRequest.java similarity index 97% rename from function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientRequest.java rename to function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientRequest.java index ecfd51a899..6cada5e77a 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientRequest.java +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientRequest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.function.client.aws; +package io.micronaut.function.client.aws.v2; import io.micronaut.serde.annotation.Serdeable; diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientResponse.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientResponse.java similarity index 97% rename from function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientResponse.java rename to function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientResponse.java index cd575f6a08..4482ae3e97 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionClientResponse.java +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientResponse.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micronaut.function.client.aws; +package io.micronaut.function.client.aws.v2; import io.micronaut.serde.annotation.Serdeable; diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionSpec.groovy similarity index 98% rename from function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy rename to function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionSpec.groovy index d0b637832f..49d16613b6 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/TestFunctionSpec.groovy +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionSpec.groovy @@ -1,4 +1,4 @@ -package io.micronaut.function.client.aws +package io.micronaut.function.client.aws.v2 import io.micronaut.core.io.ResourceLoader import io.micronaut.test.extensions.spock.annotation.MicronautTest @@ -24,7 +24,6 @@ import software.amazon.awssdk.services.lambda.model.Architecture import software.amazon.awssdk.services.lambda.model.CreateFunctionRequest import software.amazon.awssdk.services.lambda.model.DeleteFunctionRequest import software.amazon.awssdk.services.lambda.model.FunctionCode -import software.amazon.awssdk.services.lambda.model.GetFunctionConcurrencyRequest import software.amazon.awssdk.services.lambda.model.GetFunctionConfigurationRequest import software.amazon.awssdk.services.lambda.model.Runtime import software.amazon.awssdk.services.lambda.model.GetFunctionRequest From 651614b61b96bb1b185d434ab1b40ecee38f0f0b Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:06:04 +0200 Subject: [PATCH 35/50] change javadoc --- .../io/micronaut/function/client/aws/v2/package-info.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/package-info.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/package-info.java index 5c9f8da942..25270c3b6e 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/package-info.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/package-info.java @@ -14,11 +14,7 @@ * limitations under the License. */ /** -<<<<<<< HEAD:function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/package-info.java * AWS Lambda Function Client related classes. -======= - * AWS Lambda Function Client related classes. ->>>>>>> f00002268 (move to package v2):function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/package-info.java * * @since 4.7.0 */ From 421ae9d5dc65b541eca2214b5f3589c7c75dcc6c Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:12:36 +0200 Subject: [PATCH 36/50] add test --- .../v2/AwsInvokeRequestDefinitionSpec.groovy | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinitionSpec.groovy diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinitionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinitionSpec.groovy new file mode 100644 index 0000000000..463cc03a70 --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinitionSpec.groovy @@ -0,0 +1,32 @@ +package io.micronaut.function.client.aws.v2 + +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification + +@Property(name = "aws.lambda.functions.foo.function-name", value = "x-function-name") +@Property(name = "aws.lambda.functions.foo.qualifier", value = "x-qualifier") +@Property(name = "aws.lambda.functions.foo.client-context", value = "x-client-context") +@Property(name = "aws.lambda.functions.bar.function-name", value = "z-function-name") +@Property(name = "aws.lambda.functions.bar.qualifier", value = "z-qualifier") +@Property(name = "aws.lambda.functions.bar.client-context", value = "z-client-context") +@MicronautTest +class AwsInvokeRequestDefinitionSpec extends Specification { + + @Inject + List awsInvokeRequestDefinitions + + void "test aws invoke request"() { + expect: + awsInvokeRequestDefinitions.find { it.name == 'foo' }.name == 'foo' + awsInvokeRequestDefinitions.find { it.name == 'foo' }.functionName == "x-function-name" + awsInvokeRequestDefinitions.find { it.name == 'foo' }.qualifier == "x-qualifier" + awsInvokeRequestDefinitions.find { it.name == 'foo' }.clientContext == "x-client-context" + + awsInvokeRequestDefinitions.find { it.name == 'bar' }.name == 'bar' + awsInvokeRequestDefinitions.find { it.name == 'bar' }.functionName == "z-function-name" + awsInvokeRequestDefinitions.find { it.name == 'bar' }.qualifier == "z-qualifier" + awsInvokeRequestDefinitions.find { it.name == 'bar' }.clientContext == "z-client-context" + } +} From 764bd31752d4e269ee316281424d6e251dc85f8c Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:13:25 +0200 Subject: [PATCH 37/50] remove @Introspected annotation --- .../function/client/aws/v2/AwsInvokeRequestDefinition.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java index 8f208c6b94..634fe6fea1 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java @@ -17,7 +17,6 @@ import io.micronaut.context.annotation.EachProperty; import io.micronaut.context.annotation.Parameter; -import io.micronaut.core.annotation.Introspected; import io.micronaut.function.client.FunctionDefinition; /** @@ -25,7 +24,6 @@ * * @since 4.7.0 */ -@Introspected @EachProperty(AwsInvokeRequestDefinition.AWS_LAMBDA_FUNCTIONS) public class AwsInvokeRequestDefinition implements FunctionDefinition { public static final String AWS_LAMBDA_FUNCTIONS = "aws.lambda.functions"; From 497a8e814e7cf7c860cf203ac6e046311b6f198e Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:14:03 +0200 Subject: [PATCH 38/50] remove raw use of parameterized --- .../function/client/aws/v2/AwsLambdaFunctionExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java index 0670be891b..babd3beded 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java @@ -123,7 +123,7 @@ private Object decodeResult(FunctionDefinition definition, Argument outputTyp if (statusCode >= STATUS_CODE_ERROR) { throw new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + invokeResult.functionError()); } - io.micronaut.core.io.buffer.ByteBuffer byteBuffer = byteBufferFactory.copiedBuffer(invokeResult.payload().asByteArray()); + io.micronaut.core.io.buffer.ByteBuffer byteBuffer = byteBufferFactory.copiedBuffer(invokeResult.payload().asByteArray()); return mediaTypeCodec.decode(outputType, byteBuffer); } From 022ef661cc84c22448ceef02df6ce222fbd53bcb Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:15:23 +0200 Subject: [PATCH 39/50] use BLOCKING instead of IO --- .../function/client/aws/v2/AwsLambdaFunctionExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java index babd3beded..f450fd2446 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java @@ -74,7 +74,7 @@ protected AwsLambdaFunctionExecutor( LambdaAsyncClient asyncClient, ByteBufferFactory byteBufferFactory, JsonMediaTypeCodec mediaTypeCodec, - @Named(TaskExecutors.IO) ExecutorService ioExecutor) { + @Named(TaskExecutors.BLOCKING) ExecutorService ioExecutor) { this.syncClient = syncClient; this.asyncClient = asyncClient; this.byteBufferFactory = byteBufferFactory; From 560e00d87541e93111e7bfb23ed2cbe72d1863c0 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:15:39 +0200 Subject: [PATCH 40/50] remove raw use parameterized --- .../function/client/aws/v2/AwsLambdaFunctionExecutor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java index f450fd2446..5945421418 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java @@ -57,7 +57,7 @@ public class AwsLambdaFunctionExecutor implements FunctionInvoker, F private static final int STATUS_CODE_ERROR = 300; private final LambdaClient syncClient; private final LambdaAsyncClient asyncClient; - private final ByteBufferFactory byteBufferFactory; + private final ByteBufferFactory byteBufferFactory; private final JsonMediaTypeCodec mediaTypeCodec; private final ExecutorService ioExecutor; @@ -72,7 +72,7 @@ public class AwsLambdaFunctionExecutor implements FunctionInvoker, F protected AwsLambdaFunctionExecutor( LambdaClient syncClient, LambdaAsyncClient asyncClient, - ByteBufferFactory byteBufferFactory, + ByteBufferFactory byteBufferFactory, JsonMediaTypeCodec mediaTypeCodec, @Named(TaskExecutors.BLOCKING) ExecutorService ioExecutor) { this.syncClient = syncClient; From 5b00e50c8912b0c22ed5256ce9c71c764f1989c4 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:18:03 +0200 Subject: [PATCH 41/50] use conversionService --- .../client/aws/v2/AwsLambdaFunctionExecutor.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java index 5945421418..1c2029b7e4 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java @@ -60,6 +60,7 @@ public class AwsLambdaFunctionExecutor implements FunctionInvoker, F private final ByteBufferFactory byteBufferFactory; private final JsonMediaTypeCodec mediaTypeCodec; private final ExecutorService ioExecutor; + private final ConversionService conversionService; /** * Constructor. @@ -70,16 +71,18 @@ public class AwsLambdaFunctionExecutor implements FunctionInvoker, F * @param ioExecutor ioExecutor */ protected AwsLambdaFunctionExecutor( - LambdaClient syncClient, - LambdaAsyncClient asyncClient, - ByteBufferFactory byteBufferFactory, - JsonMediaTypeCodec mediaTypeCodec, - @Named(TaskExecutors.BLOCKING) ExecutorService ioExecutor) { + LambdaClient syncClient, + LambdaAsyncClient asyncClient, + ByteBufferFactory byteBufferFactory, + JsonMediaTypeCodec mediaTypeCodec, + @Named(TaskExecutors.BLOCKING) ExecutorService ioExecutor, + ConversionService conversionService) { this.syncClient = syncClient; this.asyncClient = asyncClient; this.byteBufferFactory = byteBufferFactory; this.mediaTypeCodec = mediaTypeCodec; this.ioExecutor = ioExecutor; + this.conversionService = conversionService; } @Override @@ -107,7 +110,7 @@ public O invoke(FunctionDefinition definition, I input, Argument outputType) decodeResult(definition, (Argument) outputType.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT), invokeResult)) .onErrorResume(throwable -> Mono.error(new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + throwable.getMessage(), throwable))) .subscribeOn(Schedulers.fromExecutor(ioExecutor)); - return ConversionService.SHARED.convert(invokeFlowable, outputType).orElseThrow(() -> new IllegalArgumentException("Unsupported Reactive type: " + outputType)); + return conversionService.convert(invokeFlowable, outputType).orElseThrow(() -> new IllegalArgumentException("Unsupported Reactive type: " + outputType)); } else { InvokeResponse invokeResult = syncClient.invoke(invokeRequest); try { From c54ed503c9866cb3062df3a0d77eaebf9552f609 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:37:30 +0200 Subject: [PATCH 42/50] add reactive test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit don’t use yaml configuration --- function-client-aws-v2/build.gradle.kts | 1 - .../aws/v2/AwsLambdaFunctionExecutor.java | 23 +++++++++++-------- .../client/aws/v2/TestFunctionClient.java | 20 +--------------- .../aws/v2/TestFunctionClientRequest.java | 15 ------------ .../aws/v2/TestFunctionClientResponse.java | 15 ------------ .../aws/v2/TestFunctionReactiveClient.java | 12 ++++++++++ .../client/aws/v2/TestFunctionSpec.groovy | 22 ++++++++++++++++++ .../resources/application-test.properties | 2 ++ .../src/test/resources/application-test.yaml | 5 ---- .../client/aws/AwsLambdaInvokeSpec.groovy | 6 ++--- 10 files changed, 53 insertions(+), 68 deletions(-) create mode 100644 function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionReactiveClient.java create mode 100644 function-client-aws-v2/src/test/resources/application-test.properties delete mode 100644 function-client-aws-v2/src/test/resources/application-test.yaml diff --git a/function-client-aws-v2/build.gradle.kts b/function-client-aws-v2/build.gradle.kts index 692de96bfa..8e66e26b46 100644 --- a/function-client-aws-v2/build.gradle.kts +++ b/function-client-aws-v2/build.gradle.kts @@ -19,5 +19,4 @@ dependencies { testImplementation(libs.testcontainers.localstack) testImplementation(libs.testcontainers.spock) testImplementation(libs.awssdk.iam) - testRuntimeOnly(mn.snakeyaml) } diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java index 1c2029b7e4..a7ea9732a6 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java @@ -93,16 +93,8 @@ public O invoke(FunctionDefinition definition, I input, Argument outputType) boolean isReactiveType = Publishers.isConvertibleToPublisher(outputType.getType()); SdkBytes sdkBytes = encodeInput(input); - - AwsInvokeRequestDefinition awsInvokeRequestDefinition = - (AwsInvokeRequestDefinition) definition; - - InvokeRequest invokeRequest = InvokeRequest.builder() - .functionName(awsInvokeRequestDefinition.getFunctionName()) - .qualifier(awsInvokeRequestDefinition.getQualifier()) - .clientContext(awsInvokeRequestDefinition.getClientContext()) - .payload(sdkBytes) - .build(); + AwsInvokeRequestDefinition awsInvokeRequestDefinition = (AwsInvokeRequestDefinition) definition; + InvokeRequest invokeRequest = createInvokeRequest(awsInvokeRequestDefinition, sdkBytes); if (isReactiveType) { Mono invokeFlowable = Mono.fromFuture(asyncClient.invoke(invokeRequest)) @@ -111,6 +103,7 @@ public O invoke(FunctionDefinition definition, I input, Argument outputType) .onErrorResume(throwable -> Mono.error(new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + throwable.getMessage(), throwable))) .subscribeOn(Schedulers.fromExecutor(ioExecutor)); return conversionService.convert(invokeFlowable, outputType).orElseThrow(() -> new IllegalArgumentException("Unsupported Reactive type: " + outputType)); + } else { InvokeResponse invokeResult = syncClient.invoke(invokeRequest); try { @@ -121,6 +114,16 @@ public O invoke(FunctionDefinition definition, I input, Argument outputType) } } + private InvokeRequest createInvokeRequest(AwsInvokeRequestDefinition awsInvokeRequestDefinition, + SdkBytes sdkBytes) { + return InvokeRequest.builder() + .functionName(awsInvokeRequestDefinition.getFunctionName()) + .qualifier(awsInvokeRequestDefinition.getQualifier()) + .clientContext(awsInvokeRequestDefinition.getClientContext()) + .payload(sdkBytes) + .build(); + } + private Object decodeResult(FunctionDefinition definition, Argument outputType, InvokeResponse invokeResult) { Integer statusCode = invokeResult.statusCode(); if (statusCode >= STATUS_CODE_ERROR) { diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClient.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClient.java index eae81ddf68..a2e5bde7a9 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClient.java +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClient.java @@ -1,30 +1,12 @@ -/* - * Copyright 2017-2020 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://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.micronaut.function.client.aws.v2; -//tag::imports[] import io.micronaut.function.client.FunctionClient; import io.micronaut.http.annotation.Body; import jakarta.inject.Named; -//end::imports[] @FunctionClient public interface TestFunctionClient { @Named("test-function") - TestFunctionClientResponse invokeFunction(@Body TestFunctionClientRequest request); // <1> + TestFunctionClientResponse invokeFunction(@Body TestFunctionClientRequest request); } -//end::clazz[] diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientRequest.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientRequest.java index 6cada5e77a..0e8fc403f4 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientRequest.java +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientRequest.java @@ -1,18 +1,3 @@ -/* - * Copyright 2017-2020 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://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.micronaut.function.client.aws.v2; import io.micronaut.serde.annotation.Serdeable; diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientResponse.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientResponse.java index 4482ae3e97..2319714358 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientResponse.java +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionClientResponse.java @@ -1,18 +1,3 @@ -/* - * Copyright 2017-2020 original authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://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.micronaut.function.client.aws.v2; import io.micronaut.serde.annotation.Serdeable; diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionReactiveClient.java b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionReactiveClient.java new file mode 100644 index 0000000000..d61afb647b --- /dev/null +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionReactiveClient.java @@ -0,0 +1,12 @@ +package io.micronaut.function.client.aws.v2; + +import io.micronaut.function.client.FunctionClient; +import io.micronaut.http.annotation.Body; +import jakarta.inject.Named; +import org.reactivestreams.Publisher; + +@FunctionClient +public interface TestFunctionReactiveClient { + @Named("test-function-reactive") + Publisher invokeFunctionReactive(@Body TestFunctionClientRequest request); +} diff --git a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionSpec.groovy b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionSpec.groovy index 49d16613b6..03f8a4465d 100644 --- a/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionSpec.groovy +++ b/function-client-aws-v2/src/test/groovy/io/micronaut/function/client/aws/v2/TestFunctionSpec.groovy @@ -7,6 +7,7 @@ import jakarta.inject.Inject import org.testcontainers.containers.localstack.LocalStackContainer import org.testcontainers.spock.Testcontainers import org.testcontainers.utility.DockerImageName +import reactor.core.publisher.Mono import software.amazon.awssdk.auth.credentials.AwsBasicCredentials import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain import software.amazon.awssdk.core.SdkBytes @@ -71,6 +72,9 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { @Inject TestFunctionClient functionClient + @Inject + TestFunctionReactiveClient testFunctionReactiveClient + def setupSpec() { try { lambdaClient.getFunction(GetFunctionRequest.builder() @@ -114,6 +118,24 @@ class TestFunctionSpec extends Specification implements TestPropertyProvider { result.anArray[0].aString == aString } + def "can invoke a JS Lambda function with the an @FunctionClient wtih reactive types"() { + given: + Integer aNumber = 1 + String aString = "someString" + when: + TestFunctionClientResponse result = Mono.from(testFunctionReactiveClient.invokeFunctionReactive(new TestFunctionClientRequest(aNumber, aString, new ComplexType(aNumber, aString)))).block() + + then: + result.aNumber == aNumber + result.aString == aString + result.aObject + result.aObject.aNumber == aNumber + result.aObject.aString == aString + result.anArray.size() == 1 + result.anArray[0].aNumber == aNumber + result.anArray[0].aString == aString + } + private byte[] lambdaBytes(ResourceLoader resourceLoader) { try (InputStream inputStream = resourceLoader.getResourceAsStream("classpath:lambda/index.js").orElseThrow()) { byte[] fileBytes = inputStream.readAllBytes() diff --git a/function-client-aws-v2/src/test/resources/application-test.properties b/function-client-aws-v2/src/test/resources/application-test.properties new file mode 100644 index 0000000000..cdaf3278ec --- /dev/null +++ b/function-client-aws-v2/src/test/resources/application-test.properties @@ -0,0 +1,2 @@ +aws.lambda.functions.test-function.function-name=TEST_FUNCTION_NAME +aws.lambda.functions.test-function-reactive.function-name=TEST_FUNCTION_NAME diff --git a/function-client-aws-v2/src/test/resources/application-test.yaml b/function-client-aws-v2/src/test/resources/application-test.yaml deleted file mode 100644 index d4e19ceff1..0000000000 --- a/function-client-aws-v2/src/test/resources/application-test.yaml +++ /dev/null @@ -1,5 +0,0 @@ -aws: - lambda: - functions: - test-function: - function-name: 'TEST_FUNCTION_NAME' diff --git a/function-client-aws/src/test/groovy/io/micronaut/function/client/aws/AwsLambdaInvokeSpec.groovy b/function-client-aws/src/test/groovy/io/micronaut/function/client/aws/AwsLambdaInvokeSpec.groovy index f3c7112f6c..3e4ad30705 100644 --- a/function-client-aws/src/test/groovy/io/micronaut/function/client/aws/AwsLambdaInvokeSpec.groovy +++ b/function-client-aws/src/test/groovy/io/micronaut/function/client/aws/AwsLambdaInvokeSpec.groovy @@ -73,7 +73,7 @@ class AwsLambdaInvokeSpec extends Specification { void "test setup lambda config"() { given: ApplicationContext applicationContext = ApplicationContext.run( - 'aws.lambda.functions.test.functionName':'micronaut-function', + 'aws.lambda.functions.test.function-name':'micronaut-function', 'aws.lambda.functions.test.qualifier':'something', 'aws.lambda.region':'us-east-1' ) @@ -94,7 +94,7 @@ class AwsLambdaInvokeSpec extends Specification { void "test invoke function"() { given: ApplicationContext applicationContext = ApplicationContext.run( - 'aws.lambda.functions.test.functionName':'micronaut-function', + 'aws.lambda.functions.test.function-name':'micronaut-function', 'aws.lambda.region':'us-east-1' ) @@ -123,7 +123,7 @@ class AwsLambdaInvokeSpec extends Specification { void "test invoke client with @FunctionClient"() { given: ApplicationContext applicationContext = ApplicationContext.run( - 'aws.lambda.functions.test.functionName':'micronaut-function', + 'aws.lambda.functions.test.function-name':'micronaut-function', 'aws.lambda.region':'us-east-1' ) From a78e20bd73f48fcaf5f2f73f3d2feb3303158e9b Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 13:59:35 +0200 Subject: [PATCH 43/50] fix: run Junit4 test into Junit5 test This PR moves a Java test which was not being run as it was a JUnit 4 test to `src/test/java` and transforms it into a JUnit5 test. It updates to latest Micronaut core as it was failing locally for me without this upgrade. --- function-client-aws/build.gradle.kts | 2 + .../aws/LocalFunctionInvokeJavaSpec.java | 85 ------------------- .../aws/LocalFunctionInvokeJavaTest.java | 42 +++++++++ .../function/client/aws/MathClient.java | 14 +++ .../client/aws/ReactiveMathClient.java | 15 ++++ .../micronaut/function/client/aws/Suma.java | 27 ++++++ gradle/libs.versions.toml | 2 +- 7 files changed, 101 insertions(+), 86 deletions(-) delete mode 100644 function-client-aws/src/test/groovy/io/micronaut/function/client/aws/LocalFunctionInvokeJavaSpec.java create mode 100644 function-client-aws/src/test/java/io/micronaut/function/client/aws/LocalFunctionInvokeJavaTest.java create mode 100644 function-client-aws/src/test/java/io/micronaut/function/client/aws/MathClient.java create mode 100644 function-client-aws/src/test/java/io/micronaut/function/client/aws/ReactiveMathClient.java create mode 100644 function-client-aws/src/test/java/io/micronaut/function/client/aws/Suma.java diff --git a/function-client-aws/build.gradle.kts b/function-client-aws/build.gradle.kts index 244c91d7e2..8f332dc738 100644 --- a/function-client-aws/build.gradle.kts +++ b/function-client-aws/build.gradle.kts @@ -14,4 +14,6 @@ dependencies { testImplementation(mn.micronaut.function.web) testImplementation(mnGroovy.micronaut.function.groovy) testImplementation(mnGroovy.micronaut.runtime.groovy) + testImplementation(mnTest.micronaut.test.junit5) + testRuntimeOnly(libs.junit.jupiter.engine) } diff --git a/function-client-aws/src/test/groovy/io/micronaut/function/client/aws/LocalFunctionInvokeJavaSpec.java b/function-client-aws/src/test/groovy/io/micronaut/function/client/aws/LocalFunctionInvokeJavaSpec.java deleted file mode 100644 index 7e3dbb7bcc..0000000000 --- a/function-client-aws/src/test/groovy/io/micronaut/function/client/aws/LocalFunctionInvokeJavaSpec.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.micronaut.function.client.aws; - -//tag::import[] -import io.micronaut.context.ApplicationContext; -import io.micronaut.function.client.FunctionClient; -import jakarta.inject.Named; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -//end::rxImport[] -//end::import[] - -import io.micronaut.runtime.server.EmbeddedServer; -import org.reactivestreams.Publisher; -import reactor.core.publisher.Mono; -//tag::rxImport[] - -public class LocalFunctionInvokeJavaSpec { - - //tag::invokeLocalFunction[] - @Test - public void testInvokingALocalFunction() { - Sum sum = new Sum(); - sum.setA(5); - sum.setB(10); - - EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class); - MathClient mathClient = server.getApplicationContext().getBean(MathClient.class); - - assertEquals(Long.valueOf(Integer.MAX_VALUE), mathClient.max()); - assertEquals(2, mathClient.rnd(1.6f)); - assertEquals(15, mathClient.sum(sum)); - - } - //end::invokeLocalFunction[] - - //tag::invokeRxLocalFunction[] - @Test - public void testInvokingALocalFunctionRX() { - Sum sum = new Sum(); - sum.setA(5); - sum.setB(10); - - EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class); - ReactiveMathClient mathClient = server.getApplicationContext().getBean(ReactiveMathClient.class); - - assertEquals(Long.valueOf(Integer.MAX_VALUE), mathClient.max().block()); - assertEquals(2, mathClient.rnd(1.6f).block().longValue()); - assertEquals(15, mathClient.sum(sum).block().longValue()); - - } - //end::invokeRxLocalFunction[] - - //tag::beginFunctionClient[] - @FunctionClient - interface MathClient { - //end::beginFunctionClient[] - - //tag::functionMax[] - Long max(); //<1> - //end::functionMax[] - - //tag::functionRnd[] - @Named("round") - int rnd(float value); - //end::functionRnd[] - - long sum(Sum sum); - //tag::endFunctionClient[] - } - //end::endFunctionClient[] - - - //tag::rxFunctionClient[] - @FunctionClient - interface ReactiveMathClient { - Mono max(); - - @Named("round") - Mono rnd(float value); - - Mono sum(Sum sum); - } - //end::rxFunctionClient[] -} diff --git a/function-client-aws/src/test/java/io/micronaut/function/client/aws/LocalFunctionInvokeJavaTest.java b/function-client-aws/src/test/java/io/micronaut/function/client/aws/LocalFunctionInvokeJavaTest.java new file mode 100644 index 0000000000..0543bf367f --- /dev/null +++ b/function-client-aws/src/test/java/io/micronaut/function/client/aws/LocalFunctionInvokeJavaTest.java @@ -0,0 +1,42 @@ +package io.micronaut.function.client.aws; + +import io.micronaut.context.ApplicationContext; +import static org.junit.Assert.assertEquals; +import io.micronaut.runtime.server.EmbeddedServer; +import org.junit.jupiter.api.Test; +import reactor.core.publisher.Mono; + +class LocalFunctionInvokeJavaTest { + + @Test + void testInvokingALocalFunction() { + Suma sum = new Suma(); + sum.setA(5); + sum.setB(10); + + EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class); + MathClient mathClient = server.getApplicationContext().getBean(MathClient.class); + + assertEquals(Long.valueOf(Integer.MAX_VALUE), mathClient.max()); + assertEquals(2, mathClient.rnd(1.6f)); + assertEquals(15, mathClient.sum(sum)); + + server.close(); + } + + @Test + void testInvokingALocalFunctionRX() { + Suma sum = new Suma(); + sum.setA(5); + sum.setB(10); + + EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class); + ReactiveMathClient mathClient = server.getApplicationContext().getBean(ReactiveMathClient.class); + + assertEquals(Long.valueOf(Integer.MAX_VALUE), Mono.from(mathClient.max()).block()); + assertEquals(2, Mono.from(mathClient.rnd(1.6f)).block().longValue()); + assertEquals(15, Mono.from(mathClient.sum(sum)).block().longValue()); + + server.close(); + } +} diff --git a/function-client-aws/src/test/java/io/micronaut/function/client/aws/MathClient.java b/function-client-aws/src/test/java/io/micronaut/function/client/aws/MathClient.java new file mode 100644 index 0000000000..5a29aca59c --- /dev/null +++ b/function-client-aws/src/test/java/io/micronaut/function/client/aws/MathClient.java @@ -0,0 +1,14 @@ +package io.micronaut.function.client.aws; + +import io.micronaut.function.client.FunctionClient; +import jakarta.inject.Named; + +@FunctionClient +interface MathClient { + Long max(); + + @Named("round") + int rnd(float value); + + long sum(Suma sum); +} diff --git a/function-client-aws/src/test/java/io/micronaut/function/client/aws/ReactiveMathClient.java b/function-client-aws/src/test/java/io/micronaut/function/client/aws/ReactiveMathClient.java new file mode 100644 index 0000000000..890b3260e7 --- /dev/null +++ b/function-client-aws/src/test/java/io/micronaut/function/client/aws/ReactiveMathClient.java @@ -0,0 +1,15 @@ +package io.micronaut.function.client.aws; + +import io.micronaut.function.client.FunctionClient; +import jakarta.inject.Named; +import org.reactivestreams.Publisher; + +@FunctionClient +interface ReactiveMathClient { + Publisher max(); + + @Named("round") + Publisher rnd(float value); + + Publisher sum(Suma sum); +} diff --git a/function-client-aws/src/test/java/io/micronaut/function/client/aws/Suma.java b/function-client-aws/src/test/java/io/micronaut/function/client/aws/Suma.java new file mode 100644 index 0000000000..d8cb82cac2 --- /dev/null +++ b/function-client-aws/src/test/java/io/micronaut/function/client/aws/Suma.java @@ -0,0 +1,27 @@ +package io.micronaut.function.client.aws; + +/** + * @author graemerocher + * @since 1.0 + */ +public class Suma { + + private int a; + private Integer b; + + public int getA() { + return a; + } + + public void setA(int a) { + this.a = a; + } + + public Integer getB() { + return b; + } + + public void setB(Integer b) { + this.b = b; + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a004243603..2f1fa377b8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -micronaut = "4.5.0" +micronaut = "4.5.3" micronaut-docs = "2.0.0" micronaut-test = "4.2.0" groovy = "4.0.15" From 47990246194b7201c1ebc269d2e94dac7b87684c Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 14:20:57 +0200 Subject: [PATCH 44/50] test-suite for function-client-aws v1 and v2 --- settings.gradle.kts | 3 ++ .../build.gradle.kts | 23 +++++++++++++ .../client/aws/AnalyticsClientSpec.groovy | 30 +++++++++++++++++ .../client/aws/atnamed/AnalyticsClient.groovy | 9 ++++++ .../aws/methodnamed/AnalyticsClient.groovy | 8 +++++ .../src/test/resources/application.properties | 1 + .../src/test/resources/logback.xml | 15 +++++++++ .../build.gradle.kts | 32 +++++++++++++++++++ .../docs/function/aws/AnalyticsClientTest.kt | 25 +++++++++++++++ .../client/aws/atnamed/AnalyticsClient.kt | 10 ++++++ .../client/aws/methodnamed/AnalyticsClient.kt | 8 +++++ .../src/test/resources/application.properties | 1 + .../src/test/resources/logback.xml | 15 +++++++++ .../build.gradle.kts | 9 ++++++ .../function/aws/AnalyticsClientTest.java | 32 +++++++++++++++++++ .../client/aws/atnamed/AnalyticsClient.java | 10 ++++++ .../aws/methodnamed/AnalyticsClient.java | 8 +++++ .../src/test/resources/application.yml | 8 +++++ .../src/test/resources/logback.xml | 15 +++++++++ test-suite-groovy/build.gradle.kts | 2 +- .../client/aws/AnalyticsClientSpec.groovy | 7 ++-- test-suite-kotlin/build.gradle.kts | 2 +- .../docs/function/aws/AnalyticsClientTest.kt | 6 ++-- test-suite/build.gradle.kts | 2 +- .../function/aws/AnalyticsClientTest.java | 6 ++-- 25 files changed, 274 insertions(+), 13 deletions(-) create mode 100644 test-suite-function-client-aws-groovy/build.gradle.kts create mode 100644 test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/AnalyticsClientSpec.groovy create mode 100644 test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.groovy create mode 100644 test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.groovy create mode 100644 test-suite-function-client-aws-groovy/src/test/resources/application.properties create mode 100644 test-suite-function-client-aws-groovy/src/test/resources/logback.xml create mode 100644 test-suite-function-client-aws-kotlin/build.gradle.kts create mode 100644 test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/aws/AnalyticsClientTest.kt create mode 100644 test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.kt create mode 100644 test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.kt create mode 100644 test-suite-function-client-aws-kotlin/src/test/resources/application.properties create mode 100644 test-suite-function-client-aws-kotlin/src/test/resources/logback.xml create mode 100644 test-suite-function-client-aws/build.gradle.kts create mode 100644 test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/aws/AnalyticsClientTest.java create mode 100644 test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.java create mode 100644 test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.java create mode 100644 test-suite-function-client-aws/src/test/resources/application.yml create mode 100644 test-suite-function-client-aws/src/test/resources/logback.xml diff --git a/settings.gradle.kts b/settings.gradle.kts index 5dcef21fd0..005f56fc4a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,16 +39,19 @@ include("function-aws-test") include("function-client-aws") include("function-client-aws-v2") +include("test-suite-function-client-aws") include("test-suite") include("test-suite-aws-sdk-v2") include("test-suite-graal") include("test-suite-graal-logging") include("test-suite-groovy") +include("test-suite-function-client-aws-groovy") include("test-suite-http-server-tck-function-aws-api-gateway-proxy-alb") include("test-suite-http-server-tck-function-aws-api-gateway-proxy-payloadv1") include("test-suite-http-server-tck-function-aws-api-gateway-proxy-payloadv2") include("test-suite-http-server-tck-function-aws-api-proxy-test") include("test-suite-kotlin") +include("test-suite-function-client-aws-kotlin") include("test-suite-s3") configure { diff --git a/test-suite-function-client-aws-groovy/build.gradle.kts b/test-suite-function-client-aws-groovy/build.gradle.kts new file mode 100644 index 0000000000..ef95a4b33e --- /dev/null +++ b/test-suite-function-client-aws-groovy/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + id("groovy") + id("java-library") + id("io.micronaut.build.internal.aws-tests") +} + +dependencies { + testCompileOnly(mn.micronaut.inject.groovy) + testImplementation(mnTest.micronaut.test.spock) + testImplementation(platform(mn.micronaut.core.bom)) + testImplementation(projects.micronautFunctionClientAws) +} + +tasks { + named("test", Test::class) { + useJUnitPlatform() + } +} + +java { + sourceCompatibility = JavaVersion.toVersion("17") + targetCompatibility = JavaVersion.toVersion("17") +} diff --git a/test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/AnalyticsClientSpec.groovy b/test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/AnalyticsClientSpec.groovy new file mode 100644 index 0000000000..00770b9725 --- /dev/null +++ b/test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/AnalyticsClientSpec.groovy @@ -0,0 +1,30 @@ +package io.micronaut.docs.function.client.aws + +import io.micronaut.context.ApplicationContext +import io.micronaut.function.client.FunctionDefinition +import io.micronaut.function.client.aws.AWSInvokeRequestDefinition +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import spock.lang.Specification +import jakarta.inject.Inject + +@MicronautTest(startApplication = false) +class AnalyticsClientSpec extends Specification { + @Inject + ApplicationContext applicationContext + + void "test setup function definitions"() { + given: + Collection definitions = applicationContext.getBeansOfType(FunctionDefinition) + + expect: + definitions.size() == 1 + definitions.first() instanceof AWSInvokeRequestDefinition + + when: + AWSInvokeRequestDefinition invokeRequestDefinition = (AWSInvokeRequestDefinition) definitions.first() + + then: + invokeRequestDefinition.name == 'analytics' + invokeRequestDefinition.invokeRequest.functionName == 'AwsLambdaFunctionName' + } +} diff --git a/test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.groovy b/test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.groovy new file mode 100644 index 0000000000..f49d482ab8 --- /dev/null +++ b/test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.groovy @@ -0,0 +1,9 @@ +package io.micronaut.docs.function.client.aws.atnamed + +import io.micronaut.function.client.FunctionClient +import jakarta.inject.Named +@FunctionClient +interface AnalyticsClient { + @Named('analytics') + String visit(String productId); +} diff --git a/test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.groovy b/test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.groovy new file mode 100644 index 0000000000..6dfdf74d6c --- /dev/null +++ b/test-suite-function-client-aws-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.groovy @@ -0,0 +1,8 @@ +package io.micronaut.docs.function.client.aws.methodnamed + +import io.micronaut.function.client.FunctionClient + +@FunctionClient +interface AnalyticsClient { + String analytics(String productId) +} diff --git a/test-suite-function-client-aws-groovy/src/test/resources/application.properties b/test-suite-function-client-aws-groovy/src/test/resources/application.properties new file mode 100644 index 0000000000..73c92aa9d4 --- /dev/null +++ b/test-suite-function-client-aws-groovy/src/test/resources/application.properties @@ -0,0 +1 @@ +aws.lambda.functions.analytics.function-name=AwsLambdaFunctionName \ No newline at end of file diff --git a/test-suite-function-client-aws-groovy/src/test/resources/logback.xml b/test-suite-function-client-aws-groovy/src/test/resources/logback.xml new file mode 100644 index 0000000000..80dcc40c8d --- /dev/null +++ b/test-suite-function-client-aws-groovy/src/test/resources/logback.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/test-suite-function-client-aws-kotlin/build.gradle.kts b/test-suite-function-client-aws-kotlin/build.gradle.kts new file mode 100644 index 0000000000..c423ba56a2 --- /dev/null +++ b/test-suite-function-client-aws-kotlin/build.gradle.kts @@ -0,0 +1,32 @@ +plugins { + id("org.jetbrains.kotlin.jvm") + id("org.jetbrains.kotlin.kapt") + id("io.micronaut.build.internal.aws-tests") +} + +val micronautVersion: String by project + +dependencies { + kaptTest(mn.micronaut.inject.java) + testAnnotationProcessor(platform(mn.micronaut.core.bom)) + testImplementation(libs.junit.jupiter.api) + testImplementation(mnTest.micronaut.test.junit5) + testRuntimeOnly(libs.junit.jupiter.engine) + testImplementation(projects.micronautFunctionAws) + testImplementation(libs.kotlin.stdlib.jdk8) + testImplementation(projects.micronautFunctionClientAws) + testRuntimeOnly(mn.snakeyaml) +} + +tasks { + named("test", Test::class) { + useJUnitPlatform() + } +} + +kotlin { + jvmToolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } + +} diff --git a/test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/aws/AnalyticsClientTest.kt b/test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/aws/AnalyticsClientTest.kt new file mode 100644 index 0000000000..1539ed0c88 --- /dev/null +++ b/test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/aws/AnalyticsClientTest.kt @@ -0,0 +1,25 @@ +package io.micronaut.docs.function.aws + +import io.micronaut.context.ApplicationContext +import io.micronaut.function.client.FunctionDefinition +import io.micronaut.function.client.aws.AWSInvokeRequestDefinition +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import jakarta.inject.Inject +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test + +@MicronautTest(startApplication = false) +internal class AnalyticsClientTest { + @Inject + lateinit var applicationContext: ApplicationContext + @Test + fun testSetupFunctionDefinitions() { + val definitions = applicationContext.getBeansOfType(FunctionDefinition::class.java) + Assertions.assertEquals(1, definitions.size) + Assertions.assertTrue(definitions.stream().findFirst().isPresent) + Assertions.assertTrue(definitions.stream().findFirst().get() is AWSInvokeRequestDefinition) + val invokeRequestDefinition = definitions.stream().findFirst().get() as AWSInvokeRequestDefinition + Assertions.assertEquals("analytics", invokeRequestDefinition.name) + //Assertions.assertEquals("AwsLambdaFunctionName", invokeRequestDefinition.invokeRequest.functionName) + } +} \ No newline at end of file diff --git a/test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.kt b/test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.kt new file mode 100644 index 0000000000..f4ad54bfb1 --- /dev/null +++ b/test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.kt @@ -0,0 +1,10 @@ +package io.micronaut.docs.function.client.aws.atnamed + +import io.micronaut.function.client.FunctionClient +import jakarta.inject.Named + +@FunctionClient +internal interface AnalyticsClient { + @Named("analytics") + fun visit(productId: String): String +} diff --git a/test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.kt b/test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.kt new file mode 100644 index 0000000000..27efa775e2 --- /dev/null +++ b/test-suite-function-client-aws-kotlin/src/test/kotlin/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.kt @@ -0,0 +1,8 @@ +package io.micronaut.docs.function.client.aws.methodnamed + +import io.micronaut.function.client.FunctionClient + +@FunctionClient +internal interface AnalyticsClient { + fun analytics(productId: String): String +} diff --git a/test-suite-function-client-aws-kotlin/src/test/resources/application.properties b/test-suite-function-client-aws-kotlin/src/test/resources/application.properties new file mode 100644 index 0000000000..73c92aa9d4 --- /dev/null +++ b/test-suite-function-client-aws-kotlin/src/test/resources/application.properties @@ -0,0 +1 @@ +aws.lambda.functions.analytics.function-name=AwsLambdaFunctionName \ No newline at end of file diff --git a/test-suite-function-client-aws-kotlin/src/test/resources/logback.xml b/test-suite-function-client-aws-kotlin/src/test/resources/logback.xml new file mode 100644 index 0000000000..80dcc40c8d --- /dev/null +++ b/test-suite-function-client-aws-kotlin/src/test/resources/logback.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/test-suite-function-client-aws/build.gradle.kts b/test-suite-function-client-aws/build.gradle.kts new file mode 100644 index 0000000000..49070ce16b --- /dev/null +++ b/test-suite-function-client-aws/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("java-library") + id("io.micronaut.build.internal.aws-tests-java") + id("io.micronaut.build.internal.common") +} +dependencies { + testImplementation(projects.micronautFunctionClientAws) +} + diff --git a/test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/aws/AnalyticsClientTest.java b/test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/aws/AnalyticsClientTest.java new file mode 100644 index 0000000000..60be703853 --- /dev/null +++ b/test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/aws/AnalyticsClientTest.java @@ -0,0 +1,32 @@ +package io.micronaut.docs.function.aws; + +import io.micronaut.context.ApplicationContext; +import io.micronaut.function.client.FunctionDefinition; +import io.micronaut.function.client.aws.AWSInvokeRequestDefinition; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; + +import java.util.Collection; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@MicronautTest(startApplication = false) +class AnalyticsClientTest { + @Inject + ApplicationContext applicationContext; + + @Test + void testSetupFunctionDefinitions() { + Collection definitions = applicationContext.getBeansOfType(FunctionDefinition.class); + + assertEquals(1, definitions.size()); + assertTrue(definitions.stream().findFirst().isPresent()); + assertTrue(definitions.stream().findFirst().get() instanceof AWSInvokeRequestDefinition); + + AWSInvokeRequestDefinition invokeRequestDefinition = (AWSInvokeRequestDefinition) definitions.stream().findFirst().get(); + + assertEquals("analytics", invokeRequestDefinition.getName()); + } +} diff --git a/test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.java b/test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.java new file mode 100644 index 0000000000..0547f2dc2d --- /dev/null +++ b/test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/client/aws/atnamed/AnalyticsClient.java @@ -0,0 +1,10 @@ +package io.micronaut.docs.function.client.aws.atnamed; + +import io.micronaut.function.client.FunctionClient; +import jakarta.inject.Named; +@FunctionClient +public interface AnalyticsClient { + + @Named("analytics") // <1> + String visit(String productId); +} diff --git a/test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.java b/test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.java new file mode 100644 index 0000000000..613d1c6e8a --- /dev/null +++ b/test-suite-function-client-aws/src/test/java/io/micronaut/docs/function/client/aws/methodnamed/AnalyticsClient.java @@ -0,0 +1,8 @@ +package io.micronaut.docs.function.client.aws.methodnamed; + +import io.micronaut.function.client.FunctionClient; + +@FunctionClient +public interface AnalyticsClient { + String analytics(String productId); +} diff --git a/test-suite-function-client-aws/src/test/resources/application.yml b/test-suite-function-client-aws/src/test/resources/application.yml new file mode 100644 index 0000000000..85c4f2e020 --- /dev/null +++ b/test-suite-function-client-aws/src/test/resources/application.yml @@ -0,0 +1,8 @@ +#tag::config[] +--- +aws: + lambda: + functions: + analytics: + function-name: 'AwsLambdaFunctionName' +#end::config[] \ No newline at end of file diff --git a/test-suite-function-client-aws/src/test/resources/logback.xml b/test-suite-function-client-aws/src/test/resources/logback.xml new file mode 100644 index 0000000000..80dcc40c8d --- /dev/null +++ b/test-suite-function-client-aws/src/test/resources/logback.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/test-suite-groovy/build.gradle.kts b/test-suite-groovy/build.gradle.kts index 5d263f217b..5d496ab412 100644 --- a/test-suite-groovy/build.gradle.kts +++ b/test-suite-groovy/build.gradle.kts @@ -9,7 +9,7 @@ dependencies { testImplementation(mnTest.micronaut.test.spock) testImplementation(platform(mn.micronaut.core.bom)) testImplementation(projects.micronautFunctionAws) - testImplementation(projects.micronautFunctionClientAws) + testImplementation(projects.micronautFunctionClientAwsV2) testRuntimeOnly(mn.snakeyaml) } diff --git a/test-suite-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/AnalyticsClientSpec.groovy b/test-suite-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/AnalyticsClientSpec.groovy index 00770b9725..efedeaa7cd 100644 --- a/test-suite-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/AnalyticsClientSpec.groovy +++ b/test-suite-groovy/src/test/groovy/io/micronaut/docs/function/client/aws/AnalyticsClientSpec.groovy @@ -2,7 +2,7 @@ package io.micronaut.docs.function.client.aws import io.micronaut.context.ApplicationContext import io.micronaut.function.client.FunctionDefinition -import io.micronaut.function.client.aws.AWSInvokeRequestDefinition +import io.micronaut.function.client.aws.v2.AwsInvokeRequestDefinition import io.micronaut.test.extensions.spock.annotation.MicronautTest import spock.lang.Specification import jakarta.inject.Inject @@ -18,13 +18,12 @@ class AnalyticsClientSpec extends Specification { expect: definitions.size() == 1 - definitions.first() instanceof AWSInvokeRequestDefinition + definitions.first() instanceof AwsInvokeRequestDefinition when: - AWSInvokeRequestDefinition invokeRequestDefinition = (AWSInvokeRequestDefinition) definitions.first() + AwsInvokeRequestDefinition invokeRequestDefinition = (AwsInvokeRequestDefinition) definitions.first() then: invokeRequestDefinition.name == 'analytics' - invokeRequestDefinition.invokeRequest.functionName == 'AwsLambdaFunctionName' } } diff --git a/test-suite-kotlin/build.gradle.kts b/test-suite-kotlin/build.gradle.kts index c423ba56a2..175c4cbe43 100644 --- a/test-suite-kotlin/build.gradle.kts +++ b/test-suite-kotlin/build.gradle.kts @@ -14,7 +14,7 @@ dependencies { testRuntimeOnly(libs.junit.jupiter.engine) testImplementation(projects.micronautFunctionAws) testImplementation(libs.kotlin.stdlib.jdk8) - testImplementation(projects.micronautFunctionClientAws) + testImplementation(projects.micronautFunctionClientAwsV2) testRuntimeOnly(mn.snakeyaml) } diff --git a/test-suite-kotlin/src/test/kotlin/io/micronaut/docs/function/aws/AnalyticsClientTest.kt b/test-suite-kotlin/src/test/kotlin/io/micronaut/docs/function/aws/AnalyticsClientTest.kt index 1539ed0c88..5418a00b27 100644 --- a/test-suite-kotlin/src/test/kotlin/io/micronaut/docs/function/aws/AnalyticsClientTest.kt +++ b/test-suite-kotlin/src/test/kotlin/io/micronaut/docs/function/aws/AnalyticsClientTest.kt @@ -2,7 +2,7 @@ package io.micronaut.docs.function.aws import io.micronaut.context.ApplicationContext import io.micronaut.function.client.FunctionDefinition -import io.micronaut.function.client.aws.AWSInvokeRequestDefinition +import io.micronaut.function.client.aws.v2.AwsInvokeRequestDefinition import io.micronaut.test.extensions.junit5.annotation.MicronautTest import jakarta.inject.Inject import org.junit.jupiter.api.Assertions @@ -17,8 +17,8 @@ internal class AnalyticsClientTest { val definitions = applicationContext.getBeansOfType(FunctionDefinition::class.java) Assertions.assertEquals(1, definitions.size) Assertions.assertTrue(definitions.stream().findFirst().isPresent) - Assertions.assertTrue(definitions.stream().findFirst().get() is AWSInvokeRequestDefinition) - val invokeRequestDefinition = definitions.stream().findFirst().get() as AWSInvokeRequestDefinition + Assertions.assertTrue(definitions.stream().findFirst().get() is AwsInvokeRequestDefinition) + val invokeRequestDefinition = definitions.stream().findFirst().get() as AwsInvokeRequestDefinition Assertions.assertEquals("analytics", invokeRequestDefinition.name) //Assertions.assertEquals("AwsLambdaFunctionName", invokeRequestDefinition.invokeRequest.functionName) } diff --git a/test-suite/build.gradle.kts b/test-suite/build.gradle.kts index f6339f4ffa..98872291df 100644 --- a/test-suite/build.gradle.kts +++ b/test-suite/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } dependencies { testImplementation(projects.micronautFunctionAws) - testImplementation(projects.micronautFunctionClientAws) + testImplementation(projects.micronautFunctionClientAwsV2) } tasks { diff --git a/test-suite/src/test/java/io/micronaut/docs/function/aws/AnalyticsClientTest.java b/test-suite/src/test/java/io/micronaut/docs/function/aws/AnalyticsClientTest.java index dec6690f8c..8f35476cd4 100644 --- a/test-suite/src/test/java/io/micronaut/docs/function/aws/AnalyticsClientTest.java +++ b/test-suite/src/test/java/io/micronaut/docs/function/aws/AnalyticsClientTest.java @@ -2,7 +2,7 @@ import io.micronaut.context.ApplicationContext; import io.micronaut.function.client.FunctionDefinition; -import io.micronaut.function.client.aws.AWSInvokeRequestDefinition; +import io.micronaut.function.client.aws.v2.AwsInvokeRequestDefinition; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import jakarta.inject.Inject; import org.junit.jupiter.api.Test; @@ -23,9 +23,9 @@ void testSetupFunctionDefinitions() { assertEquals(1, definitions.size()); assertTrue(definitions.stream().findFirst().isPresent()); - assertTrue(definitions.stream().findFirst().get() instanceof AWSInvokeRequestDefinition); + assertTrue(definitions.stream().findFirst().get() instanceof AwsInvokeRequestDefinition); - AWSInvokeRequestDefinition invokeRequestDefinition = (AWSInvokeRequestDefinition) definitions.stream().findFirst().get(); + AwsInvokeRequestDefinition invokeRequestDefinition = (AwsInvokeRequestDefinition) definitions.stream().findFirst().get(); assertEquals("analytics", invokeRequestDefinition.getName()); //assertEquals("AwsLambdaFunctionName", invokeRequestDefinition.getInvokeRequest().getFunctionName()); From 95b58d809c51c9ce9fe035a559814e751a0f5309 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 14:22:53 +0200 Subject: [PATCH 45/50] disable binary compatibility --- function-client-aws-v2/build.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/function-client-aws-v2/build.gradle.kts b/function-client-aws-v2/build.gradle.kts index 8e66e26b46..def348e4c6 100644 --- a/function-client-aws-v2/build.gradle.kts +++ b/function-client-aws-v2/build.gradle.kts @@ -20,3 +20,9 @@ dependencies { testImplementation(libs.testcontainers.spock) testImplementation(libs.awssdk.iam) } +micronautBuild { + // new module, so no binary check + binaryCompatibility { + enabled.set(false) + } +} From 615d2bc64d58addc0cf13bcb6d19649f40df19f1 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 14:34:57 +0200 Subject: [PATCH 46/50] improve docs --- .../guide/lambda/lambdafunctionclient.adoc | 24 +++++++++++++++---- .../src/test/resources/application.properties | 1 + 2 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 test-suite/src/test/resources/application.properties diff --git a/src/main/docs/guide/lambda/lambdafunctionclient.adoc b/src/main/docs/guide/lambda/lambdafunctionclient.adoc index 3580b624a4..65b63f0af5 100644 --- a/src/main/docs/guide/lambda/lambdafunctionclient.adoc +++ b/src/main/docs/guide/lambda/lambdafunctionclient.adoc @@ -1,15 +1,19 @@ Micronaut AWS provides support for invoking AWS Lambda functions within a Micronaut application context. + +=== AWS SDK V2 + To use the features described in this section, you will need to have the following dependency on your classpath: dependency:micronaut-function-client-aws-v2[groupId="io.micronaut.aws"] -or for AWS SDK v1: - -dependency:micronaut-function-client-aws[groupId="io.micronaut.aws"] +NOTE: To invoke a function Micronaut configures a `LambdaAsyncClient` and `LambdaClient`. You can configure them by registering a https://docs.micronaut.io/latest/api/io/micronaut/context/event/BeanCreatedEventListener.html[BeanCreatedEventListener] for `software.amazon.awssdk.services.lambda.LambdaAsyncClient` or `software.amazon.awssdk.services.lambda.LambdaAsyncClientBuilder` You can define multiple named functions under the `aws.lambda.functions` configuration. -Each is configured by `AWSInvokeRequestDefinition` that allows setting any property on the underlying `com.amazonaws.services.lambda.model.InvokeRequest`. +Each is configured by `AwsInvokeRequestDefinition` that allows setting any property on the underlying `software.amazon.awssdk.services.lambda.model.InvokeRequest`. + + +=== Example For example, you invoke a function named `AwsLambdaFunctionName`, in the AWS Lambda console, with the following configuration: @@ -28,6 +32,16 @@ Alternatively, you can remove the `@Named` annotation and match the method name snippet::io.micronaut.docs.function.client.aws.methodnamed.AnalyticsClient[tags="clazz"] -To configure credentials for invoking the function you can either define a `~/.aws/credentials` file or use the application configuration file. Micronaut registers a api:configurations.aws.EnvironmentAWSCredentialsProvider[] that resolves AWS credentials from the Micronaut Environment. + +=== AWS SDK V1 + +To use AWS SDK v1 add the following dependency instead: + +dependency:micronaut-function-client-aws[groupId="io.micronaut.aws"] NOTE: To invoke a function Micronaut configures a `AWSLambdaAsyncClient` using api:function.client.aws.AWSLambdaConfiguration[] that allows configuring any of the properties of the `AWSLambdaAsyncClientBuilder` class. + +You can define multiple named functions under the `aws.lambda.functions` configuration. +Each is configured by `AWSInvokeRequestDefinition` that allows setting any property on the underlying `com.amazonaws.services.lambda.model.InvokeRequest`. + +To configure credentials for invoking the function you can either define a `~/.aws/credentials` file or use the application configuration file. Micronaut registers a api:configurations.aws.EnvironmentAWSCredentialsProvider[] that resolves AWS credentials from the Micronaut Environment. diff --git a/test-suite/src/test/resources/application.properties b/test-suite/src/test/resources/application.properties new file mode 100644 index 0000000000..73c92aa9d4 --- /dev/null +++ b/test-suite/src/test/resources/application.properties @@ -0,0 +1 @@ +aws.lambda.functions.analytics.function-name=AwsLambdaFunctionName \ No newline at end of file From 94729881984afeefdd36524ddf703e367127c2ad Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 15:14:16 +0200 Subject: [PATCH 47/50] add javadoc --- .../aws/v2/AwsInvokeRequestDefinition.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java index 634fe6fea1..7490fc5a2c 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java @@ -50,26 +50,50 @@ public String getName() { return this.name; } + /** + * + * @return The name or ARN of the Lambda function, version, or alias. + */ public String getFunctionName() { return functionName; } + /** + * + * @param functionName The name or ARN of the Lambda function, version, or alias. + */ + public void setFunctionName(String functionName) { + this.functionName = functionName; + } + + /** + * + * @return Specify a version or alias to invoke a published version of the function. + */ public String getQualifier() { return qualifier; } + /** + * {@see software.amazon.awssdk.services.lambda.model.InvokeRequest#clientContext} + * @return Up to 3,583 bytes of base64-encoded data about the invoking client to pass to the function in the context object. + */ public String getClientContext() { return clientContext; } - public void setFunctionName(String functionName) { - this.functionName = functionName; - } - + /** + * {@see software.amazon.awssdk.services.lambda.model.InvokeRequest#qualifier} + * @param qualifier Specify a version or alias to invoke a published version of the function. + */ public void setQualifier(String qualifier) { this.qualifier = qualifier; } + /** + * + * @param clientContext Up to 3,583 bytes of base64-encoded data about the invoking client to pass to the function in the context object. + */ public void setClientContext(String clientContext) { this.clientContext = clientContext; } From cf924e3e1327db6ec7ae1b5560a3a94a7164dc42 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 15:16:45 +0200 Subject: [PATCH 48/50] fix checkstyle --- .../client/aws/v2/AwsInvokeRequestDefinition.java | 4 ++-- .../client/aws/v2/AwsLambdaFunctionExecutor.java | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java index 7490fc5a2c..927628043a 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java @@ -75,7 +75,7 @@ public String getQualifier() { } /** - * {@see software.amazon.awssdk.services.lambda.model.InvokeRequest#clientContext} + * {@see software.amazon.awssdk.services.lambda.model.InvokeRequest#clientContext}. * @return Up to 3,583 bytes of base64-encoded data about the invoking client to pass to the function in the context object. */ public String getClientContext() { @@ -83,7 +83,7 @@ public String getClientContext() { } /** - * {@see software.amazon.awssdk.services.lambda.model.InvokeRequest#qualifier} + * {@see software.amazon.awssdk.services.lambda.model.InvokeRequest#qualifier}. * @param qualifier Specify a version or alias to invoke a published version of the function. */ public void setQualifier(String qualifier) { diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java index a7ea9732a6..2a9dcfdcd5 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java @@ -59,29 +59,30 @@ public class AwsLambdaFunctionExecutor implements FunctionInvoker, F private final LambdaAsyncClient asyncClient; private final ByteBufferFactory byteBufferFactory; private final JsonMediaTypeCodec mediaTypeCodec; - private final ExecutorService ioExecutor; + private final ExecutorService executor; private final ConversionService conversionService; /** * Constructor. * - * @param asyncClient asyncClient + * @param syncClient Lambda Sync Client + * @param asyncClient Lambda Async Client * @param byteBufferFactory byteBufferFactory * @param mediaTypeCodec JsonMediaTypeCodec - * @param ioExecutor ioExecutor + * @param executor blocking executor */ protected AwsLambdaFunctionExecutor( LambdaClient syncClient, LambdaAsyncClient asyncClient, ByteBufferFactory byteBufferFactory, JsonMediaTypeCodec mediaTypeCodec, - @Named(TaskExecutors.BLOCKING) ExecutorService ioExecutor, + @Named(TaskExecutors.BLOCKING) ExecutorService executor, ConversionService conversionService) { this.syncClient = syncClient; this.asyncClient = asyncClient; this.byteBufferFactory = byteBufferFactory; this.mediaTypeCodec = mediaTypeCodec; - this.ioExecutor = ioExecutor; + this.executor = executor; this.conversionService = conversionService; } @@ -101,7 +102,7 @@ public O invoke(FunctionDefinition definition, I input, Argument outputType) .map(invokeResult -> decodeResult(definition, (Argument) outputType.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT), invokeResult)) .onErrorResume(throwable -> Mono.error(new FunctionExecutionException("Error executing AWS Lambda [" + definition.getName() + "]: " + throwable.getMessage(), throwable))) - .subscribeOn(Schedulers.fromExecutor(ioExecutor)); + .subscribeOn(Schedulers.fromExecutor(executor)); return conversionService.convert(invokeFlowable, outputType).orElseThrow(() -> new IllegalArgumentException("Unsupported Reactive type: " + outputType)); } else { From 3446aee2430dbdf6cfcc10abcb3e89207cee3383 Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Thu, 4 Jul 2024 15:28:26 +0200 Subject: [PATCH 49/50] add javadoc --- .../function/client/aws/v2/AwsInvokeRequestDefinition.java | 3 +++ .../function/client/aws/v2/AwsLambdaFunctionExecutor.java | 1 + 2 files changed, 4 insertions(+) diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java index 927628043a..82b70fceb1 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsInvokeRequestDefinition.java @@ -26,6 +26,9 @@ */ @EachProperty(AwsInvokeRequestDefinition.AWS_LAMBDA_FUNCTIONS) public class AwsInvokeRequestDefinition implements FunctionDefinition { + /** + * Configuration prefix. + */ public static final String AWS_LAMBDA_FUNCTIONS = "aws.lambda.functions"; private final String name; diff --git a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java index 2a9dcfdcd5..9c3ce5b247 100644 --- a/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java +++ b/function-client-aws-v2/src/main/java/io/micronaut/function/client/aws/v2/AwsLambdaFunctionExecutor.java @@ -70,6 +70,7 @@ public class AwsLambdaFunctionExecutor implements FunctionInvoker, F * @param byteBufferFactory byteBufferFactory * @param mediaTypeCodec JsonMediaTypeCodec * @param executor blocking executor + * @param conversionService ConversionService */ protected AwsLambdaFunctionExecutor( LambdaClient syncClient, From 9c814af29243d630d591b9dda086c4e7569e4dfd Mon Sep 17 00:00:00 2001 From: Sergio del Amo Date: Tue, 20 Aug 2024 14:31:39 +0200 Subject: [PATCH 50/50] disabled tests --- .../function/client/aws/LocalFunctionInvokeJavaTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/function-client-aws/src/test/java/io/micronaut/function/client/aws/LocalFunctionInvokeJavaTest.java b/function-client-aws/src/test/java/io/micronaut/function/client/aws/LocalFunctionInvokeJavaTest.java index 0543bf367f..6d927c824a 100644 --- a/function-client-aws/src/test/java/io/micronaut/function/client/aws/LocalFunctionInvokeJavaTest.java +++ b/function-client-aws/src/test/java/io/micronaut/function/client/aws/LocalFunctionInvokeJavaTest.java @@ -3,11 +3,14 @@ import io.micronaut.context.ApplicationContext; import static org.junit.Assert.assertEquals; import io.micronaut.runtime.server.EmbeddedServer; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; +import spock.lang.Ignore; class LocalFunctionInvokeJavaTest { + @Disabled("it is flaky https://ge.micronaut.io/scans/tests?tests.container=io.micronaut.function.client.aws.LocalFunctionInvokeSpec") @Test void testInvokingALocalFunction() { Suma sum = new Suma(); @@ -24,6 +27,7 @@ void testInvokingALocalFunction() { server.close(); } + @Disabled("it is flaky https://ge.micronaut.io/scans/tests?tests.container=io.micronaut.function.client.aws.LocalFunctionInvokeSpec") @Test void testInvokingALocalFunctionRX() { Suma sum = new Suma();