Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ swagger-models = { module = "io.swagger.core.v3:swagger-models", version.ref = "
swagger-annotations = { module = "io.swagger.core.v3:swagger-annotations", version.ref = "swagger" }

s3client-minio = { module = "io.minio:minio", version = "8.5.17" }
s3client-aws = { module = "software.amazon.awssdk:s3", version = "2.29.52" }
s3client-aws = { module = "software.amazon.awssdk:s3", version = "2.42.35" }

camunda7-engine = { module = "org.camunda.bpm:camunda-engine", version.ref = "camunda7" }
camunda7-rest-jakarta = { module = "org.camunda.bpm:camunda-engine-rest-jakarta", version.ref = "camunda7" }
Expand Down
16 changes: 16 additions & 0 deletions s3/s3-client-aws/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
dependencies {
annotationProcessor project(":config:config-annotation-processor")

api project(":telemetry:telemetry-common")
api project(":http:http-client-common")
api project(":config:config-common")
api project(":common")

api(libs.s3client.aws) {
exclude group: "software.amazon.awssdk", module: "apache-client"
exclude group: "software.amazon.awssdk", module: "netty-nio-client"
}

testImplementation project(":internal:test-logging")
testImplementation libs.testcontainers.core
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.koraframework.s3.client.aws;

import software.amazon.awssdk.services.s3.S3Client;

public interface AwsS3ClientFactory {

S3Client create(AwsS3Config config);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package io.koraframework.s3.client.aws;

import io.koraframework.application.graph.All;
import io.koraframework.common.DefaultComponent;
import io.koraframework.common.Tag;
import io.koraframework.config.common.Config;
import io.koraframework.config.common.extractor.ConfigValueExtractor;
import io.koraframework.http.client.common.HttpClient;
import io.koraframework.s3.client.aws.telemetry.AwsS3ClientTelemetryFactory;
import io.koraframework.s3.client.aws.telemetry.DefaultAwsS3ClientTelemetryFactory;
import io.micrometer.core.instrument.MeterRegistry;
import io.opentelemetry.api.trace.Tracer;
import org.jspecify.annotations.Nullable;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.awscore.AwsClient;
import software.amazon.awssdk.core.checksums.RequestChecksumCalculation;
import software.amazon.awssdk.core.checksums.ResponseChecksumValidation;
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration;

import java.net.URI;

public interface AwsS3ClientModule {

default AwsS3Config awsS3Config(Config config, ConfigValueExtractor<AwsS3Config> extractor) {
var value = config.get("s3client.aws");
return extractor.extract(value);
}

@Tag(AwsClient.class)
@DefaultComponent
default HttpClient awsS3httpClient(HttpClient client) {
return client;
}

@DefaultComponent
default KoraAwsSdkHttpClient awsS3koraSdkHttpClient(@Tag(AwsClient.class) HttpClient client,
AwsS3Config clientConfig) {
return new KoraAwsSdkHttpClient(client, clientConfig);
}

@DefaultComponent
default S3Configuration awsS3Configuration(AwsS3Config config) {
return S3Configuration.builder()
.chunkedEncodingEnabled(config.chunkedEncodingEnabled())
.pathStyleAccessEnabled(config.addressStyle() == AwsS3Config.AddressStyle.PATH)
.build();
}

@DefaultComponent
default AwsCredentialsProvider awsS3credentialsProvider(AwsS3Config config) {
return () -> AwsBasicCredentials.create(config.credentials().accessKey(), config.credentials().secretKey());
}

default AwsS3ClientTelemetryFactory awsS3ClientTelemetryFactory(@Nullable Tracer tracer,
@Nullable MeterRegistry meterRegistry) {
return new DefaultAwsS3ClientTelemetryFactory(tracer, meterRegistry);
}

default AwsS3ClientFactory awsS3ClientFactory(SdkHttpClient httpClient,
AwsCredentialsProvider credentialsProvider,
S3Configuration s3Configuration,
AwsS3ClientTelemetryFactory telemetryFactory,
All<ExecutionInterceptor> interceptors) {
return (config) -> {
var configuration = s3Configuration.toBuilder()
.chunkedEncodingEnabled(config.chunkedEncodingEnabled())
.pathStyleAccessEnabled(config.addressStyle() == AwsS3Config.AddressStyle.PATH)
.build();

return S3Client.builder()
.credentialsProvider(credentialsProvider)
.httpClient(httpClient)
.endpointOverride(URI.create(config.url()))
.serviceConfiguration(configuration)
.region(Region.of(config.region()))
.requestChecksumCalculation(RequestChecksumCalculation.fromValue(config.checksumCalculationRequest().name()))
.responseChecksumValidation(ResponseChecksumValidation.fromValue(config.checksumValidationResponse().name()))
.overrideConfiguration(b -> b.addExecutionInterceptor(new AwsS3ClientTelemetryInterceptor(telemetryFactory.get(config.telemetry()))))
.overrideConfiguration(b -> interceptors.forEach(b::addExecutionInterceptor))
.build();
};
}

default S3Client awsS3Client(AwsS3Config config, AwsS3ClientFactory factory) {
return factory.create(config);
}
}
Loading
Loading