feat: add object storage production capability

This commit is contained in:
donghyeon-ka
2026-07-31 23:50:03 +09:00
parent b3add0162d
commit f0a6d1c8c8
427 changed files with 39930 additions and 699 deletions
@@ -1,8 +1,6 @@
// Driven adapter: object storage behind application-core's ObjectStoragePort. Two backends — local
// filesystem (default, no external service) and S3/MinIO via the AWS SDK v2 S3 client (endpoint
// override makes the same code work against real AWS S3 and MinIO). Opt-in via
// @ConditionalOnProperty (ca-skeleton.objectstorage.backend); filesystem is the matchIfMissing
// default.
// Driven adapter: provider-neutral semantic object-storage ports plus a bounded local-development
// provider. Canonical app.object-storage activation is disabled by default. The old whole-byte[]
// filesystem/S3 adapters remain isolated, explicit legacy compatibility only.
//
// software.amazon.awssdk:* versions are NOT managed by the Spring Boot BOM, and this repo has no
// version catalog, so the AWS SDK v2 BOM platform is imported HERE (module scope) using the root
@@ -10,6 +8,36 @@
// root dependencyManagement block stays awssdk-free), mirroring the grpc module's grpc-bom import.
description = 'Outbound adapter: object storage (S3/MinIO + local filesystem)'
sourceSets {
objectStorageMinioContractTest {
java.srcDir 'src/objectStorageMinioContractTest/java'
resources.srcDir 'src/objectStorageMinioContractTest/resources'
compileClasspath += sourceSets.main.output + sourceSets.test.output
runtimeClasspath += output + compileClasspath
}
objectStorageMinioFaultTest {
java.srcDir 'src/objectStorageMinioFaultTest/java'
resources.srcDir 'src/objectStorageMinioFaultTest/resources'
compileClasspath += sourceSets.main.output + sourceSets.test.output
runtimeClasspath += output + compileClasspath
}
objectStorageAwsQualificationTest {
java.srcDir 'src/objectStorageAwsQualificationTest/java'
resources.srcDir 'src/objectStorageAwsQualificationTest/resources'
compileClasspath += sourceSets.main.output + sourceSets.test.output
runtimeClasspath += output + compileClasspath
}
}
configurations {
objectStorageMinioContractTestImplementation.extendsFrom testImplementation
objectStorageMinioContractTestRuntimeOnly.extendsFrom testRuntimeOnly
objectStorageMinioFaultTestImplementation.extendsFrom testImplementation
objectStorageMinioFaultTestRuntimeOnly.extendsFrom testRuntimeOnly
objectStorageAwsQualificationTestImplementation.extendsFrom testImplementation
objectStorageAwsQualificationTestRuntimeOnly.extendsFrom testRuntimeOnly
}
dependencyManagement {
imports {
mavenBom "software.amazon.awssdk:bom:${awsSdkVersion}"
@@ -23,6 +51,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-autoconfigure'
implementation 'org.slf4j:slf4j-api'
implementation 'software.amazon.awssdk:s3'
implementation 'software.amazon.awssdk:netty-nio-client'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
@@ -31,4 +60,32 @@ dependencies {
// Docker is available and is skipped (disabledWithoutDocker) otherwise.
testImplementation 'org.testcontainers:testcontainers'
testImplementation 'org.testcontainers:testcontainers-junit-jupiter'
testImplementation 'org.testcontainers:testcontainers-toxiproxy'
testImplementation 'net.jqwik:jqwik:1.9.1'
}
tasks.register('objectStorageMinioContractTest', Test) {
description = 'Runs the non-skipping exact-release MinIO managed object contract.'
group = 'verification'
testClassesDirs = sourceSets.objectStorageMinioContractTest.output.classesDirs
classpath = sourceSets.objectStorageMinioContractTest.runtimeClasspath
useJUnitPlatform()
shouldRunAfter tasks.named('test')
}
tasks.register('objectStorageMinioFaultTest', Test) {
description = 'Runs the non-skipping digest-pinned MinIO/Toxiproxy fault contract.'
group = 'verification'
testClassesDirs = sourceSets.objectStorageMinioFaultTest.output.classesDirs
classpath = sourceSets.objectStorageMinioFaultTest.runtimeClasspath
useJUnitPlatform()
shouldRunAfter tasks.named('objectStorageMinioContractTest')
}
tasks.register('objectStorageAwsQualificationTest', Test) {
description = 'Runs only with explicit protected AWS sandbox authority and exact inputs.'
group = 'verification'
testClassesDirs = sourceSets.objectStorageAwsQualificationTest.output.classesDirs
classpath = sourceSets.objectStorageAwsQualificationTest.runtimeClasspath
useJUnitPlatform()
}