mirror of
https://github.com/tadfisher/gradle2nix.git
synced 2026-01-11 15:30:38 -05:00
plugin: Support S3 repositories
This commit is contained in:
24
ivy/build.gradle.kts
Normal file
24
ivy/build.gradle.kts
Normal file
@@ -0,0 +1,24 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("org.apache.ivy:ivy:latest.release")
|
||||
api("com.amazonaws:aws-java-sdk-s3:latest.release")
|
||||
|
||||
testImplementation("com.adobe.testing:s3mock-junit5:latest.release")
|
||||
testImplementation("io.strikt:strikt-core:latest.release")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:latest.release")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-params:latest.release")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:latest.release")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher:latest.release")
|
||||
}
|
||||
|
||||
tasks {
|
||||
test {
|
||||
useJUnitPlatform {
|
||||
includeEngines("junit-jupiter")
|
||||
}
|
||||
systemProperty("fixtures", "$rootDir/fixtures")
|
||||
}
|
||||
}
|
||||
123
ivy/gradle.lockfile
Normal file
123
ivy/gradle.lockfile
Normal file
@@ -0,0 +1,123 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
ch.qos.logback:logback-classic:1.2.3=testCompileClasspath,testRuntimeClasspath
|
||||
ch.qos.logback:logback-core:1.2.3=testCompileClasspath,testRuntimeClasspath
|
||||
com.adobe.testing:s3mock-junit5:2.1.28=testCompileClasspath,testRuntimeClasspath
|
||||
com.adobe.testing:s3mock-testsupport-common:2.1.28=testCompileClasspath,testRuntimeClasspath
|
||||
com.adobe.testing:s3mock:2.1.28=testCompileClasspath,testRuntimeClasspath
|
||||
com.amazonaws:aws-java-sdk-core:1.11.946=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.amazonaws:aws-java-sdk-kms:1.11.946=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.amazonaws:aws-java-sdk-s3:1.11.946=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.amazonaws:jmespath-java:1.11.946=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.christophsturm:filepeek:0.1.2=testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.6.0=compileClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-annotations:2.9.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.6.7=compileClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-core:2.9.9=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.6.7.4=compileClasspath,runtimeClasspath
|
||||
com.fasterxml.jackson.core:jackson-databind:2.9.9.3=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.6.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.9=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.9=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.9=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.9.9=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.9=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml.woodstox:woodstox-core:5.1.0=testCompileClasspath,testRuntimeClasspath
|
||||
com.fasterxml:classmate:1.3.4=testCompileClasspath,testRuntimeClasspath
|
||||
com.typesafe.netty:netty-reactive-streams-http:2.0.0=testRuntimeClasspath
|
||||
com.typesafe.netty:netty-reactive-streams:2.0.0=testRuntimeClasspath
|
||||
commons-codec:commons-codec:1.11=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
commons-io:commons-io:2.6=testCompileClasspath,testRuntimeClasspath
|
||||
commons-logging:commons-logging:1.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
io.netty:netty-buffer:4.1.33.Final=testRuntimeClasspath
|
||||
io.netty:netty-codec-http2:4.1.33.Final=testRuntimeClasspath
|
||||
io.netty:netty-codec-http:4.1.33.Final=testRuntimeClasspath
|
||||
io.netty:netty-codec:4.1.33.Final=testRuntimeClasspath
|
||||
io.netty:netty-common:4.1.33.Final=testRuntimeClasspath
|
||||
io.netty:netty-handler:4.1.33.Final=testRuntimeClasspath
|
||||
io.netty:netty-resolver:4.1.33.Final=testRuntimeClasspath
|
||||
io.netty:netty-transport-native-epoll:4.1.33.Final=testRuntimeClasspath
|
||||
io.netty:netty-transport-native-unix-common:4.1.33.Final=testRuntimeClasspath
|
||||
io.netty:netty-transport:4.1.33.Final=testRuntimeClasspath
|
||||
io.strikt:strikt-core:0.28.2=testCompileClasspath,testRuntimeClasspath
|
||||
javax.annotation:javax.annotation-api:1.3.2=testCompileClasspath,testRuntimeClasspath
|
||||
javax.servlet:javax.servlet-api:3.1.0=testCompileClasspath,testRuntimeClasspath
|
||||
javax.validation:validation-api:2.0.1.Final=testCompileClasspath,testRuntimeClasspath
|
||||
joda-time:joda-time:2.8.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.commons:commons-lang3:3.8.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpclient:4.5.13=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.httpcomponents:httpcore:4.4.13=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.ivy:ivy:2.5.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.logging.log4j:log4j-api:2.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.apache.logging.log4j:log4j-to-slf4j:2.11.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.apiguardian:apiguardian-api:1.1.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.codehaus.woodstox:stax2-api:4.1=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-continuation:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-http:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-io:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-security:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-server:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-servlet:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-servlets:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-util:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-webapp:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.eclipse.jetty:jetty-xml:9.4.19.v20190610=testCompileClasspath,testRuntimeClasspath
|
||||
org.hibernate.validator:hibernate-validator:6.0.17.Final=testCompileClasspath,testRuntimeClasspath
|
||||
org.jboss.logging:jboss-logging:3.3.2.Final=testCompileClasspath,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.4.21-2=testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20=compileClasspath,runtimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.4.21-2=testCompileClasspath,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.21-2=testCompileClasspath,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.21-2=testCompileClasspath,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.4.20=compileClasspath,runtimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.4.21-2=testCompileClasspath,testRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.2=testRuntimeClasspath
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2=testRuntimeClasspath
|
||||
org.jetbrains:annotations:13.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.7.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-engine:5.7.0=testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-params:5.7.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.7.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-engine:1.7.0=testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-launcher:1.7.0=testRuntimeClasspath
|
||||
org.junit:junit-bom:5.7.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.mortbay.jasper:apache-el:8.5.40=testCompileClasspath,testRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.2.0=testCompileClasspath,testRuntimeClasspath
|
||||
org.reactivestreams:reactive-streams:1.0.2=testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:jul-to-slf4j:1.7.28=testCompileClasspath,testRuntimeClasspath
|
||||
org.slf4j:slf4j-api:1.7.28=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework.boot:spring-boot-autoconfigure:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework.boot:spring-boot-starter-jetty:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework.boot:spring-boot-starter-json:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework.boot:spring-boot-starter-logging:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework.boot:spring-boot-starter-web:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework.boot:spring-boot-starter:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework.boot:spring-boot:2.1.9.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-aop:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-beans:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-context:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-core:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-expression:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-jcl:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-web:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.springframework:spring-webmvc:5.1.10.RELEASE=testCompileClasspath,testRuntimeClasspath
|
||||
org.yaml:snakeyaml:1.23=testRuntimeClasspath
|
||||
software.amazon.awssdk:annotations:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:apache-client:2.7.19=testRuntimeClasspath
|
||||
software.amazon.awssdk:auth:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:aws-core:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:aws-query-protocol:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:aws-xml-protocol:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:http-client-spi:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:netty-nio-client:2.7.19=testRuntimeClasspath
|
||||
software.amazon.awssdk:profiles:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:protocol-core:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:regions:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:s3:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:sdk-core:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:url-connection-client:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.awssdk:utils:2.7.19=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.eventstream:eventstream:1.0.1=testCompileClasspath,testRuntimeClasspath
|
||||
software.amazon.ion:ion-java:1.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
|
||||
empty=
|
||||
294
ivy/src/main/kotlin/org/nixos/gradle2nix/S3.kt
Normal file
294
ivy/src/main/kotlin/org/nixos/gradle2nix/S3.kt
Normal file
@@ -0,0 +1,294 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.amazonaws.AmazonServiceException
|
||||
import com.amazonaws.ClientConfiguration
|
||||
import com.amazonaws.auth.AWSCredentials
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider
|
||||
import com.amazonaws.client.builder.AwsClientBuilder
|
||||
import com.amazonaws.regions.Region
|
||||
import com.amazonaws.regions.RegionUtils
|
||||
import com.amazonaws.regions.Regions
|
||||
import com.amazonaws.services.s3.AmazonS3
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder
|
||||
import com.amazonaws.services.s3.model.GetObjectRequest
|
||||
import com.amazonaws.services.s3.model.ListObjectsRequest
|
||||
import com.amazonaws.services.s3.model.ObjectMetadata
|
||||
import com.amazonaws.services.s3.model.S3Object
|
||||
import com.amazonaws.services.s3.model.S3ObjectInputStream
|
||||
import com.amazonaws.util.AwsHostNameUtils
|
||||
import org.apache.http.conn.ssl.NoopHostnameVerifier
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory
|
||||
import org.apache.ivy.core.settings.TimeoutConstraint
|
||||
import org.apache.ivy.plugins.repository.AbstractRepository
|
||||
import org.apache.ivy.plugins.repository.RepositoryCopyProgressListener
|
||||
import org.apache.ivy.plugins.repository.Resource
|
||||
import org.apache.ivy.plugins.repository.TransferEvent
|
||||
import org.apache.ivy.util.FileUtil
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.net.Socket
|
||||
import java.net.URI
|
||||
import java.security.KeyManagementException
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.security.SecureRandom
|
||||
import java.security.cert.X509Certificate
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.SSLEngine
|
||||
import javax.net.ssl.TrustManager
|
||||
import javax.net.ssl.X509ExtendedTrustManager
|
||||
|
||||
|
||||
class S3Repository(
|
||||
private val client: AmazonS3,
|
||||
timeoutConstraint: TimeoutConstraint? = null
|
||||
) : AbstractRepository(timeoutConstraint) {
|
||||
|
||||
constructor(
|
||||
credentials: AWSCredentials?,
|
||||
endpoint: URI?,
|
||||
timeoutConstraint: TimeoutConstraint?
|
||||
) : this(
|
||||
AmazonS3ClientBuilder.standard().apply {
|
||||
credentials?.let { setCredentials(AWSStaticCredentialsProvider(it)) }
|
||||
|
||||
if (endpoint != null) {
|
||||
setEndpointConfiguration(
|
||||
AwsClientBuilder.EndpointConfiguration(
|
||||
endpoint.toString(),
|
||||
AwsHostNameUtils.parseRegion(endpoint.host, null) ?: Regions.US_EAST_1.name
|
||||
)
|
||||
)
|
||||
isChunkedEncodingDisabled = true
|
||||
isPathStyleAccessEnabled = true
|
||||
} else {
|
||||
region = Regions.US_EAST_1.name
|
||||
}
|
||||
|
||||
if (System.getProperty("org.nixos.gradle2nix.s3test") != null) {
|
||||
clientConfiguration = ClientConfiguration().apply {
|
||||
apacheHttpClientConfig.sslSocketFactory = SSLConnectionSocketFactory(
|
||||
createBlindlyTrustingSslContext(),
|
||||
NoopHostnameVerifier.INSTANCE
|
||||
)
|
||||
}
|
||||
}
|
||||
}.build(),
|
||||
timeoutConstraint
|
||||
)
|
||||
|
||||
private val cache = mutableMapOf<String, S3Resource>()
|
||||
|
||||
private val progress = RepositoryCopyProgressListener(this)
|
||||
|
||||
override fun getResource(source: String): Resource =
|
||||
cache.getOrPut(source) { S3Resource(this, URI(source)) }
|
||||
|
||||
override fun get(source: String, destination: File) {
|
||||
fireTransferInitiated(getResource(source), TransferEvent.REQUEST_GET)
|
||||
try {
|
||||
val res = getResource(source)
|
||||
val totalLength = res.contentLength
|
||||
if (totalLength > 0) {
|
||||
progress.totalLength = totalLength
|
||||
}
|
||||
destination.parentFile?.mkdirs()
|
||||
FileUtil.copy(
|
||||
res.openStream(),
|
||||
FileOutputStream(destination),
|
||||
progress,
|
||||
true
|
||||
)
|
||||
fireTransferCompleted(res.contentLength)
|
||||
} catch (e: Exception) {
|
||||
fireTransferError(e)
|
||||
throw e
|
||||
} finally {
|
||||
progress.totalLength = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun list(parent: String): List<String> =
|
||||
S3Resource(this, URI(parent))
|
||||
.let { resource ->
|
||||
generateSequence({
|
||||
try {
|
||||
withClient(resource) {
|
||||
listObjects(
|
||||
ListObjectsRequest()
|
||||
.withBucketName(resource.bucket)
|
||||
.withPrefix(resource.key)
|
||||
.withDelimiter("/")
|
||||
)
|
||||
}
|
||||
} catch (e: AmazonServiceException) {
|
||||
throw S3RepositoryException(e)
|
||||
}
|
||||
}) { prev ->
|
||||
if (!prev.isTruncated) {
|
||||
null
|
||||
} else {
|
||||
try {
|
||||
withClient(resource) {
|
||||
listNextBatchOfObjects(prev)
|
||||
}
|
||||
} catch (e: AmazonServiceException) {
|
||||
throw S3RepositoryException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.flatMap { listing ->
|
||||
listing.commonPrefixes.asSequence() +
|
||||
listing.objectSummaries.asSequence().map { it.key }
|
||||
}
|
||||
.toList()
|
||||
|
||||
internal fun <T> withClient(
|
||||
resource: S3Resource,
|
||||
block: AmazonS3.() -> T
|
||||
): T = client.apply {
|
||||
resource.region?.let { setRegion(it) }
|
||||
}.block()
|
||||
}
|
||||
|
||||
class S3Resource(
|
||||
private val repository: S3Repository,
|
||||
private val url: URI
|
||||
) : Resource {
|
||||
|
||||
private val source: Source by lazy {
|
||||
REGIONAL_ENDPOINT_PATTERN.find(url.normalize().toString())
|
||||
?.let {
|
||||
val (bucket, region, _, key) = it.destructured
|
||||
Source(
|
||||
bucket = bucket,
|
||||
key = key,
|
||||
region = when (region) {
|
||||
"external-1" -> Region.getRegion(Regions.US_EAST_1)
|
||||
else -> RegionUtils.getRegion(region)
|
||||
}
|
||||
)
|
||||
}
|
||||
?: Source(
|
||||
bucket = url.bucket(),
|
||||
key = url.key(),
|
||||
region = null
|
||||
)
|
||||
}
|
||||
|
||||
private val metadata: Metadata by lazy {
|
||||
try {
|
||||
getMetadata()
|
||||
} catch (e: AmazonServiceException) {
|
||||
null
|
||||
}?.let { meta ->
|
||||
Metadata(
|
||||
exists = true,
|
||||
contentLength = meta.contentLength,
|
||||
lastModified = meta.lastModified.time
|
||||
)
|
||||
} ?: Metadata(
|
||||
exists = false,
|
||||
contentLength = 0,
|
||||
lastModified = 0
|
||||
)
|
||||
}
|
||||
|
||||
val bucket: String get() = source.bucket
|
||||
|
||||
val key: String get() = source.key
|
||||
|
||||
val region: Region? get() = source.region
|
||||
|
||||
override fun getName(): String = url.toString()
|
||||
|
||||
override fun getLastModified(): Long = metadata.lastModified
|
||||
|
||||
override fun getContentLength(): Long = metadata.contentLength
|
||||
|
||||
override fun exists(): Boolean = metadata.exists
|
||||
|
||||
override fun isLocal(): Boolean = false
|
||||
|
||||
override fun clone(cloneName: String): Resource = S3Resource(repository, URI(cloneName))
|
||||
|
||||
override fun openStream(): InputStream =
|
||||
try { getContent() }
|
||||
catch (e: AmazonServiceException) { throw S3RepositoryException(e) }
|
||||
?: throw S3RepositoryException()
|
||||
|
||||
private fun getMetadata(): ObjectMetadata? =
|
||||
getObject(withContent = false)?.objectMetadata
|
||||
|
||||
private fun getContent(): S3ObjectInputStream? =
|
||||
getObject(withContent = true)?.objectContent
|
||||
|
||||
private fun getObject(withContent: Boolean = true): S3Object? {
|
||||
val request = GetObjectRequest(bucket, key)
|
||||
if (!withContent) {
|
||||
request.setRange(0, 0)
|
||||
}
|
||||
|
||||
return try {
|
||||
repository.withClient(this) { getObject(request) }
|
||||
} catch (e: AmazonServiceException) {
|
||||
val errorCode = e.errorCode
|
||||
if (errorCode != null && "NoSuchKey".compareTo(errorCode, ignoreCase = true) == 0) {
|
||||
null
|
||||
} else {
|
||||
e.printStackTrace()
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private data class Source(
|
||||
val bucket: String,
|
||||
val key: String,
|
||||
val region: Region?
|
||||
)
|
||||
|
||||
private data class Metadata(
|
||||
val exists: Boolean,
|
||||
val contentLength: Long,
|
||||
val lastModified: Long
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val REGIONAL_ENDPOINT_PATTERN =
|
||||
Regex("""^s3://(.+)?\.s3[.-]([a-z0-9-]+)\.amazonaws\.com(\.[a-z]+)?/(.+)""")
|
||||
}
|
||||
}
|
||||
|
||||
class S3RepositoryException : RuntimeException {
|
||||
constructor() : super()
|
||||
|
||||
constructor(throwable: Throwable) : super(throwable)
|
||||
}
|
||||
|
||||
private fun URI.bucket(): String = normalize().host
|
||||
|
||||
private fun URI.key(): String = normalize().path.removePrefix("/")
|
||||
|
||||
// Used for testing.
|
||||
private fun createBlindlyTrustingSslContext(): SSLContext? {
|
||||
return try {
|
||||
SSLContext.getInstance("TLS").apply {
|
||||
init(null, arrayOf<TrustManager>(object : X509ExtendedTrustManager() {
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate>? = null
|
||||
override fun checkClientTrusted(arg0: Array<X509Certificate?>?, arg1: String?, arg2: Socket?) {}
|
||||
override fun checkClientTrusted(arg0: Array<X509Certificate?>?, arg1: String?, arg2: SSLEngine?) {}
|
||||
override fun checkClientTrusted(certs: Array<X509Certificate?>?, authType: String?) {}
|
||||
override fun checkServerTrusted(certs: Array<X509Certificate?>?, authType: String?) {}
|
||||
override fun checkServerTrusted(arg0: Array<X509Certificate?>?, arg1: String?, arg2: Socket?) {}
|
||||
override fun checkServerTrusted(arg0: Array<X509Certificate?>?, arg1: String?, arg2: SSLEngine?) {}
|
||||
}), SecureRandom())
|
||||
}
|
||||
} catch (e: NoSuchAlgorithmException) {
|
||||
throw RuntimeException("Unexpected exception", e)
|
||||
} catch (e: KeyManagementException) {
|
||||
throw RuntimeException("Unexpected exception", e)
|
||||
}
|
||||
}
|
||||
113
ivy/src/test/kotlin/org/nixos/gradle2nix/S3Test.kt
Normal file
113
ivy/src/test/kotlin/org/nixos/gradle2nix/S3Test.kt
Normal file
@@ -0,0 +1,113 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.adobe.testing.s3mock.junit5.S3MockExtension
|
||||
import com.amazonaws.services.s3.AmazonS3
|
||||
import org.apache.ivy.ant.IvyDependencyArtifact
|
||||
import org.apache.ivy.core.module.descriptor.Artifact
|
||||
import org.apache.ivy.core.module.descriptor.DefaultArtifact
|
||||
import org.apache.ivy.core.module.id.ArtifactRevisionId
|
||||
import org.apache.ivy.core.module.id.ModuleRevisionId
|
||||
import org.apache.ivy.core.settings.IvySettings
|
||||
import org.apache.ivy.plugins.repository.Resource
|
||||
import org.apache.ivy.plugins.resolver.IBiblioResolver
|
||||
import org.apache.ivy.plugins.resolver.URLResolver
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.extension.RegisterExtension
|
||||
import strikt.api.expectThat
|
||||
import strikt.assertions.containsExactly
|
||||
import strikt.assertions.isEmpty
|
||||
import strikt.assertions.isEqualTo
|
||||
import strikt.assertions.isFalse
|
||||
import strikt.assertions.isNotEqualTo
|
||||
import strikt.assertions.isNotNull
|
||||
import strikt.assertions.isTrue
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import kotlin.io.path.ExperimentalPathApi
|
||||
import kotlin.io.path.createTempDirectory
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class S3Test {
|
||||
companion object {
|
||||
const val bucket = "repositories"
|
||||
|
||||
val fixtureRoot = File(System.getProperty("fixtures")).resolve(bucket)
|
||||
|
||||
@JvmField
|
||||
@RegisterExtension
|
||||
val s3mock: S3MockExtension = S3MockExtension.builder().withInitialBuckets(bucket).build()
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
fun populateBucket(client: AmazonS3) {
|
||||
fixtureRoot.walkTopDown()
|
||||
.filter { it.isFile }
|
||||
.forEach { file ->
|
||||
val key = file.toRelativeString(fixtureRoot)
|
||||
client.putObject(bucket, key, file)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun listsContents(client: AmazonS3) {
|
||||
val repository = S3Repository(client)
|
||||
expectThat(repository.list("s3://repositories/m2/org/apache/test/1.0.0/")).containsExactly(
|
||||
"m2/org/apache/test/1.0.0/test-1.0.0.jar",
|
||||
"m2/org/apache/test/1.0.0/test-1.0.0.pom",
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun findsResourceMetadata(client: AmazonS3) {
|
||||
val repository = S3Repository(client)
|
||||
val resource: Resource = S3Resource(repository, URI("s3://repositories/m2/org/apache/test/1.0.0/test-1.0.0.pom"))
|
||||
expectThat(resource).and {
|
||||
get { exists() }.isTrue()
|
||||
get { contentLength }.isNotEqualTo(-1L)
|
||||
get { lastModified }.isNotEqualTo(-1L)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun downloadsResource(client: AmazonS3) {
|
||||
val repository = S3Repository(client)
|
||||
val resource: Resource = S3Resource(repository, URI("s3://repositories/m2/org/apache/test/1.0.0/test-1.0.0.pom"))
|
||||
val source = fixtureRoot.resolve("m2/org/apache/test/1.0.0/test-1.0.0.pom").readText()
|
||||
|
||||
expectThat(resource.openStream().bufferedReader().readText()).isEqualTo(source)
|
||||
}
|
||||
|
||||
@ExperimentalPathApi
|
||||
@Test
|
||||
fun locatesArtifact(client: AmazonS3) {
|
||||
val resolver = IBiblioResolver().apply {
|
||||
name = "s3"
|
||||
root = "s3://repositories/m2/"
|
||||
isM2compatible = true
|
||||
settings = IvySettings().apply {
|
||||
defaultInit()
|
||||
setDefaultRepositoryCacheBasedir(createTempDirectory().toString())
|
||||
}
|
||||
repository = S3Repository(client)
|
||||
}
|
||||
val origin = resolver.locate(DefaultArtifact(
|
||||
ArtifactRevisionId.newInstance(
|
||||
ModuleRevisionId.newInstance("org.apache", "test", "1.0.0"),
|
||||
"test",
|
||||
"jar",
|
||||
"jar"
|
||||
),
|
||||
null,
|
||||
null,
|
||||
false
|
||||
))
|
||||
|
||||
expectThat(origin).isNotNull().and {
|
||||
get { isExists }.isTrue()
|
||||
get { isLocal }.isFalse()
|
||||
get { location }.isEqualTo("s3://repositories/m2/org/apache/test/1.0.0/test-1.0.0.jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user