diff --git a/build.gradle.kts b/build.gradle.kts index f8070da..e2c7f25 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,9 @@ import org.gradle.api.tasks.wrapper.Wrapper.DistributionType +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { `maven-publish` - id("java-gradle-plugin") + `kotlin-dsl` id("com.gradle.plugin-publish") version "0.9.7" id("org.shipkit.java") version "2.3.4" id("org.shipkit.gradle-plugin") version "2.3.4" @@ -19,6 +20,16 @@ java { targetCompatibility = JavaVersion.VERSION_1_7 } +tasks.configureEach { + kotlinOptions { + jvmTarget = "1.6" + } +} + +kotlinDslPluginOptions { + experimentalWarning.set(false) +} + dependencies { implementation("com.amazonaws:aws-java-sdk-s3:1.11.751") diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..df77b96 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,5 @@ +org.gradle.parallel=true +# See https://github.com/gradle/gradle/pull/11358 , https://issues.apache.org/jira/browse/INFRA-14923 +# repository.apache.org does not yet support .sha256 and .sha512 checksums +systemProp.org.gradle.internal.publish.checksums.insecure=true +kotlin.parallel.tasks.in.project=true diff --git a/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java b/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java deleted file mode 100644 index f8b3e12..0000000 --- a/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2017 the original author or 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 - * - * http://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 ch.myniva.gradle.caching.s3; - -import java.util.HashMap; -import java.util.Map; -import org.gradle.caching.configuration.AbstractBuildCache; - -public class AwsS3BuildCache extends AbstractBuildCache { - private String region; - private String bucket; - private String path; - private boolean reducedRedundancy = true; - private String endpoint; - private Map headers; - private String awsAccessKeyId; - private String awsSecretKey; - private String sessionToken; - - public String getRegion() { - return region; - } - - public void setRegion(String region) { - this.region = region; - } - - public String getBucket() { - return bucket; - } - - public void setBucket(String bucket) { - this.bucket = bucket; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public boolean isReducedRedundancy() { - return reducedRedundancy; - } - - public void setReducedRedundancy(boolean reducedRedundancy) { - this.reducedRedundancy = reducedRedundancy; - } - - public String getEndpoint() { - return endpoint; - } - - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } - - public Map getHeaders() { - return headers; - } - - public void setHeaders(final Map headers) { - this.headers = headers != null ? new HashMap<>(headers) : null; - } - - public String getAwsAccessKeyId() { - return awsAccessKeyId; - } - - public void setAwsAccessKeyId(String awsAccessKeyId) { - this.awsAccessKeyId = awsAccessKeyId; - } - - public String getAwsSecretKey() { - return awsSecretKey; - } - - public void setAwsSecretKey(String awsSecretKey) { - this.awsSecretKey = awsSecretKey; - } - - public String getSessionToken() { - return sessionToken; - } - - public void setSessionToken(String sessionToken) { - this.sessionToken = sessionToken; - } -} diff --git a/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheService.java b/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheService.java deleted file mode 100644 index bd6312c..0000000 --- a/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheService.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2017 the original author or 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 - * - * http://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 ch.myniva.gradle.caching.s3.internal; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.amazonaws.services.s3.model.S3Object; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import com.amazonaws.services.s3.model.StorageClass; -import org.gradle.caching.BuildCacheEntryReader; -import org.gradle.caching.BuildCacheEntryWriter; -import org.gradle.caching.BuildCacheException; -import org.gradle.caching.BuildCacheKey; -import org.gradle.caching.BuildCacheService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AwsS3BuildCacheService implements BuildCacheService { - - private static final String BUILD_CACHE_CONTENT_TYPE = "application/vnd.gradle.build-cache-artifact"; - private static final Logger logger = LoggerFactory.getLogger(AwsS3BuildCacheService.class); - - private final AmazonS3 s3; - private final String bucketName; - private final String path; - private final boolean reducedRedundancy; - - AwsS3BuildCacheService(AmazonS3 s3, String bucketName, String path, boolean reducedRedundancy) { - this.s3 = s3; - this.bucketName = bucketName; - this.path = path; - this.reducedRedundancy = reducedRedundancy; - } - - private String getBucketPath(BuildCacheKey key) { - if (path == null || path.length() == 0) { - return key.getHashCode(); - } - return (path+"/"+key.getHashCode()).replaceAll("[/]+", "/"); - } - - @Override - public boolean load(BuildCacheKey key, BuildCacheEntryReader reader) { - final String bucketPath = getBucketPath(key); - if (s3.doesObjectExist(bucketName, bucketPath)) { - logger.info("Found cache item '{}' in S3 bucket", bucketPath); - S3Object object = s3.getObject(bucketName, bucketPath); - try (InputStream is = object.getObjectContent()) { - reader.readFrom(is); - return true; - } catch (IOException e) { - throw new BuildCacheException("Error while reading cache object from S3 bucket", e); - } - } else { - logger.info("Did not find cache item '{}' in S3 bucket", bucketPath); - return false; - } - } - - @Override - public void store(BuildCacheKey key, BuildCacheEntryWriter writer) { - final String bucketPath = getBucketPath(key); - logger.info("Start storing cache entry '{}' in S3 bucket", bucketPath); - ObjectMetadata meta = new ObjectMetadata(); - meta.setContentType(BUILD_CACHE_CONTENT_TYPE); - - try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { - writer.writeTo(os); - meta.setContentLength(os.size()); - try (InputStream is = new ByteArrayInputStream(os.toByteArray())) { - PutObjectRequest request = getPutObjectRequest(bucketPath, meta, is); - if(this.reducedRedundancy) { - request.withStorageClass(StorageClass.ReducedRedundancy); - } - s3.putObject(request); - } - } catch (IOException e) { - throw new BuildCacheException("Error while storing cache object in S3 bucket", e); - } - } - - protected PutObjectRequest getPutObjectRequest(String bucketPath, ObjectMetadata meta, InputStream is) { - return new PutObjectRequest(bucketName, bucketPath, is, meta); - } - - @Override - public void close() throws IOException { - // The AWS S3 client does not need to be closed - } -} diff --git a/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.java b/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.java deleted file mode 100644 index e1c42a8..0000000 --- a/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2017 the original author or 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 - * - * http://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 ch.myniva.gradle.caching.s3.internal; - -import static com.amazonaws.util.StringUtils.isNullOrEmpty; - -import com.amazonaws.ClientConfiguration; -import com.amazonaws.SdkClientException; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.auth.BasicSessionCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import java.util.Map; -import org.gradle.api.GradleException; -import org.gradle.caching.BuildCacheService; -import org.gradle.caching.BuildCacheServiceFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.myniva.gradle.caching.s3.AwsS3BuildCache; - -public class AwsS3BuildCacheServiceFactory implements BuildCacheServiceFactory { - - private static final Logger logger = LoggerFactory.getLogger(AwsS3BuildCacheServiceFactory.class); - - @Override - public BuildCacheService createBuildCacheService(AwsS3BuildCache config, Describer describer) { - logger.debug("Start creating S3 build cache service"); - - describer - .type("AWS S3") - .config("Region", config.getRegion()) - .config("Bucket", config.getBucket()) - .config("Reduced Redundancy", String.valueOf(config.isReducedRedundancy())); - - if (config.getPath() != null) { - describer.config("Path", config.getPath()); - } - - if (config.getEndpoint() != null) { - describer.config("Endpoint", config.getEndpoint()); - } - - verifyConfig(config); - AmazonS3 s3 = createS3Client(config); - - return new AwsS3BuildCacheService(s3, config.getBucket(), config.getPath(), config.isReducedRedundancy()); - } - - private void verifyConfig(AwsS3BuildCache config) { - if (isNullOrEmpty(config.getRegion())) { - throw new IllegalStateException("S3 build cache has no AWS region configured"); - } - if (isNullOrEmpty(config.getBucket())) { - throw new IllegalStateException("S3 build cache has no bucket configured"); - } - } - - private AmazonS3 createS3Client(AwsS3BuildCache config) { - AmazonS3 s3; - try { - AmazonS3ClientBuilder s3Builder = AmazonS3ClientBuilder.standard(); - if (!isNullOrEmpty(config.getAwsAccessKeyId()) && !isNullOrEmpty(config.getAwsSecretKey()) && - !isNullOrEmpty(config.getSessionToken())) { - s3Builder.withCredentials(new AWSStaticCredentialsProvider( - new BasicSessionCredentials(config.getAwsAccessKeyId(), config.getAwsSecretKey(), - config.getSessionToken()))); - } else if (!isNullOrEmpty(config.getAwsAccessKeyId()) && !isNullOrEmpty(config.getAwsSecretKey())) { - s3Builder.withCredentials(new AWSStaticCredentialsProvider( - new BasicAWSCredentials(config.getAwsAccessKeyId(), config.getAwsSecretKey()))); - } - - addHttpHeaders(s3Builder, config); - - if (isNullOrEmpty(config.getEndpoint())) { - s3Builder.withRegion(config.getRegion()); - } else { - s3Builder.withEndpointConfiguration( - new AwsClientBuilder.EndpointConfiguration(config.getEndpoint(), config.getRegion())); - } - s3 = s3Builder.build(); - } catch (SdkClientException e) { - logger.debug("Error while building AWS S3 client: {}", e.getMessage()); - throw new GradleException("Creation of S3 build cache failed; cannot create S3 client", e); - } - return s3; - } - - private void addHttpHeaders(final AmazonS3ClientBuilder s3Builder, final AwsS3BuildCache config) { - final Map headers = config.getHeaders(); - if (headers != null) { - final ClientConfiguration clientConfiguration = new ClientConfiguration(); - for (Map.Entry header : headers.entrySet()) { - if(header.getKey() != null && header.getValue() != null) { - clientConfiguration.addHeader(header.getKey(), header.getValue()); - } - } - s3Builder.setClientConfiguration(clientConfiguration); - } - } -} diff --git a/src/main/kotlin/ch/myniva/gradle/caching/s3/AwsS3BuildCache.kt b/src/main/kotlin/ch/myniva/gradle/caching/s3/AwsS3BuildCache.kt new file mode 100644 index 0000000..dcaaf6f --- /dev/null +++ b/src/main/kotlin/ch/myniva/gradle/caching/s3/AwsS3BuildCache.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2017 the original author or 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 + * + * http://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 ch.myniva.gradle.caching.s3 + +import org.gradle.caching.configuration.AbstractBuildCache + +open class AwsS3BuildCache : AbstractBuildCache() { + var region: String? = null + var bucket: String? = null + var path: String? = null + var isReducedRedundancy = true + var endpoint: String? = null + var headers: Map? = null + var awsAccessKeyId: String? = null + var awsSecretKey: String? = null + var sessionToken: String? = null +} diff --git a/src/main/java/ch/myniva/gradle/caching/s3/AwsS3Plugin.java b/src/main/kotlin/ch/myniva/gradle/caching/s3/AwsS3Plugin.kt similarity index 50% rename from src/main/java/ch/myniva/gradle/caching/s3/AwsS3Plugin.java rename to src/main/kotlin/ch/myniva/gradle/caching/s3/AwsS3Plugin.kt index 1f5945d..021cfd9 100644 --- a/src/main/java/ch/myniva/gradle/caching/s3/AwsS3Plugin.java +++ b/src/main/kotlin/ch/myniva/gradle/caching/s3/AwsS3Plugin.kt @@ -13,23 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package ch.myniva.gradle.caching.s3 -package ch.myniva.gradle.caching.s3; +import ch.myniva.gradle.caching.s3.internal.AwsS3BuildCacheServiceFactory +import org.gradle.api.Plugin +import org.gradle.api.initialization.Settings +import org.slf4j.LoggerFactory -import ch.myniva.gradle.caching.s3.internal.AwsS3BuildCacheServiceFactory; -import org.gradle.api.Plugin; -import org.gradle.api.initialization.Settings; -import org.gradle.caching.configuration.BuildCacheConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +class AwsS3Plugin : Plugin { + companion object { + private val logger = LoggerFactory.getLogger(AwsS3Plugin::class.java) + } -public class AwsS3Plugin implements Plugin { - private static final Logger logger = LoggerFactory.getLogger(AwsS3Plugin.class); - - @Override - public void apply(Settings settings) { - logger.info("Registering S3 build cache"); - BuildCacheConfiguration buildCacheConfiguration = settings.getBuildCache(); - buildCacheConfiguration.registerBuildCacheService(AwsS3BuildCache.class, AwsS3BuildCacheServiceFactory.class); - } + override fun apply(settings: Settings) { + logger.info("Registering S3 build cache") + settings.buildCache.registerBuildCacheService( + AwsS3BuildCache::class.java, + AwsS3BuildCacheServiceFactory::class.java + ) + } } diff --git a/src/main/kotlin/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheService.kt b/src/main/kotlin/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheService.kt new file mode 100644 index 0000000..a1e9c67 --- /dev/null +++ b/src/main/kotlin/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheService.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2017 the original author or 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 + * + * http://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 ch.myniva.gradle.caching.s3.internal + +import com.amazonaws.services.s3.AmazonS3 +import com.amazonaws.services.s3.model.AmazonS3Exception +import com.amazonaws.services.s3.model.ObjectMetadata +import com.amazonaws.services.s3.model.PutObjectRequest +import com.amazonaws.services.s3.model.StorageClass +import org.gradle.caching.* +import org.slf4j.LoggerFactory +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.IOException + +class AwsS3BuildCacheService internal constructor( + private val s3: AmazonS3, + private val bucketName: String, + private val path: String?, + private val reducedRedundancy: Boolean +) : BuildCacheService { + companion object { + private const val BUILD_CACHE_CONTENT_TYPE = "application/vnd.gradle.build-cache-artifact" + private val logger = LoggerFactory.getLogger(AwsS3BuildCacheService::class.java) + } + + override fun close() = s3.shutdown() + + private fun BuildCacheKey.getBucketPath() = if (path.isNullOrEmpty()) { + hashCode + } else { + "$path/$hashCode" + } + + override fun load(key: BuildCacheKey, reader: BuildCacheEntryReader): Boolean { + val bucketPath = key.getBucketPath() + try { + s3.getObject(bucketName, bucketPath).use { s3Object -> + reader.readFrom(s3Object.objectContent) + } + return true + } catch (e: AmazonS3Exception) { + if (e.statusCode == 403 || e.statusCode == 404) { + logger.info( + when (e.statusCode) { + 403 -> "Got 403 (Forbidden) when fetching cache item '{}' '{}' in S3 bucket" + else -> "Did not find cache item '{}' '{}' in S3 bucket" + }, + key.displayName, + bucketPath + ) + return false + } + logger.info( + "Unexpected error when fetching cache item '{}' '{}' in S3 bucket", + key.displayName, + bucketPath, + e + ) + return false; + } + } + + override fun store(key: BuildCacheKey, writer: BuildCacheEntryWriter) { + val bucketPath = key.getBucketPath() + logger.info("Start storing cache entry '{}' in S3 bucket", bucketPath) + val meta = ObjectMetadata().apply { + contentType = BUILD_CACHE_CONTENT_TYPE + contentLength = writer.size + } + try { + val stream = ByteArrayInputStream( + ByteArrayOutputStream() + .also { os -> writer.writeTo(os) } + .toByteArray() + ) + val request = PutObjectRequest(bucketName, bucketPath, stream, meta) + if (reducedRedundancy) { + request.withStorageClass(StorageClass.ReducedRedundancy) + } + s3.putObject(request) + } catch (e: IOException) { + throw BuildCacheException("Error while storing cache object in S3 bucket", e) + } + } + +} diff --git a/src/main/kotlin/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.kt b/src/main/kotlin/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.kt new file mode 100644 index 0000000..dcf3721 --- /dev/null +++ b/src/main/kotlin/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2017 the original author or 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 + * + * http://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 ch.myniva.gradle.caching.s3.internal + +import ch.myniva.gradle.caching.s3.AwsS3BuildCache +import com.amazonaws.ClientConfiguration +import com.amazonaws.auth.* +import com.amazonaws.auth.profile.ProfileCredentialsProvider +import com.amazonaws.client.builder.AwsClientBuilder +import com.amazonaws.services.s3.AmazonS3ClientBuilder +import org.gradle.caching.BuildCacheService +import org.gradle.caching.BuildCacheServiceFactory +import org.slf4j.LoggerFactory + +class AwsS3BuildCacheServiceFactory : BuildCacheServiceFactory { + companion object { + private val logger = LoggerFactory.getLogger(AwsS3BuildCacheServiceFactory::class.java) + } + + override fun createBuildCacheService( + config: AwsS3BuildCache, + describer: BuildCacheServiceFactory.Describer + ): BuildCacheService { + logger.debug("Start creating S3 build cache service") + describer.apply { + type("AWS S3") + describe("Region", config.region) + describe("Bucket", config.bucket) + describe("Reduced Redundancy", config.isReducedRedundancy) + describe("Path", config.path) + describe("Endpoint", config.endpoint) + } + verifyConfig(config) + return AwsS3BuildCacheService( + createS3Client(config), + config.bucket!!, + config.path, + config.isReducedRedundancy + ) + } + + private fun BuildCacheServiceFactory.Describer.describe(name: String, value: Any?) { + if (value != null) { + config(name, value.toString()) + } + } + + private fun verifyConfig(config: AwsS3BuildCache) { + check(!config.region.isNullOrEmpty()) { "S3 build cache has no AWS region configured" } + check(!config.bucket.isNullOrEmpty()) { "S3 build cache has no bucket configured" } + } + + private fun createS3Client(config: AwsS3BuildCache) = AmazonS3ClientBuilder.standard().run { + addHttpHeaders(config) + addCredentials(config) + if (config.endpoint.isNullOrEmpty()) { + withRegion(config.region) + } else { + withEndpointConfiguration( + AwsClientBuilder.EndpointConfiguration( + config.endpoint, + config.region + ) + ) + } + build() + } + + private fun AmazonS3ClientBuilder.addHttpHeaders( + config: AwsS3BuildCache + ) { + clientConfiguration = ClientConfiguration().apply { + for ((key, value) in config.headers ?: mapOf()) { + if (key != null && value != null) { + addHeader(key, value) + } + } + } + } + + private fun AmazonS3ClientBuilder.addCredentials(config: AwsS3BuildCache) { + val credentials = + if (config.awsAccessKeyId.isNullOrEmpty() || config.awsSecretKey.isNullOrEmpty()) { + return + } else { + AWSStaticCredentialsProvider( + if (config.awsAccessKeyId.isNullOrEmpty()) { + BasicAWSCredentials(config.awsAccessKeyId, config.awsSecretKey) + } else { + BasicSessionCredentials( + config.awsAccessKeyId, + config.awsSecretKey, + config.sessionToken + ) + } + ) + } + + withCredentials(credentials) + } +} diff --git a/src/test/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceTest.java b/src/test/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceTest.java deleted file mode 100644 index a337a4f..0000000 --- a/src/test/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2017 the original author or 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 - * - * http://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 ch.myniva.gradle.caching.s3.internal; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.S3ObjectInputStream; -import com.amazonaws.services.s3.model.StorageClass; -import org.gradle.caching.BuildCacheEntryReader; -import org.gradle.caching.BuildCacheEntryWriter; -import org.gradle.caching.BuildCacheKey; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -public class AwsS3BuildCacheServiceTest { - @Mock - AmazonS3 s3; - @Mock - BuildCacheKey key; - @Mock - BuildCacheEntryReader reader; - @Mock - BuildCacheEntryWriter writer; - @Mock - PutObjectRequest putObjectRequest = mock(PutObjectRequest.class); - - AwsS3BuildCacheService buildCacheService; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - doReturn("abcdefghijkl123456789").when(key).getHashCode(); - } - - @Test - public void loadGetsObjectsAndReturnsTrueIfItExistsInS3() throws Exception { - /** Setup **/ - buildCacheService = new AwsS3BuildCacheService(s3, "bucketName", null, true); - doReturn(true).when(s3).doesObjectExist("bucketName", "abcdefghijkl123456789"); - S3Object s3Object = mock(S3Object.class); - doReturn(s3Object).when(s3).getObject("bucketName", "abcdefghijkl123456789"); - S3ObjectInputStream s3ObjectInputStream = mock(S3ObjectInputStream.class); - doReturn(s3ObjectInputStream).when(s3Object).getObjectContent(); - - /** Run **/ - boolean result = buildCacheService.load(key, reader); - - /** Check **/ - assertTrue(result); - verify(reader).readFrom(s3ObjectInputStream); - } - - @Test - public void loadReturnsFalseIfItDoesntExistInS3() throws Exception { - /** Setup **/ - buildCacheService = new AwsS3BuildCacheService(s3, "bucketName", null, true); - doReturn(false).when(s3).doesObjectExist("bucketName", "abcdefghijkl123456789"); - - /** Run **/ - boolean result = buildCacheService.load(key, reader); - - /** Check **/ - assertFalse(result); - } - - @Test - public void storePutsObjectAndUsesReducedRedundancyWhenConfigured() throws IOException { - /** Setup **/ - buildCacheService = spy(new AwsS3BuildCacheService(s3, "bucketName", null, true)); - doReturn(putObjectRequest).when(buildCacheService).getPutObjectRequest(any(String.class), - any(ObjectMetadata.class), any(InputStream.class)); - - /** Run **/ - buildCacheService.store(key, writer); - - /** Check **/ - verifyThatStoreStores("abcdefghijkl123456789"); - verify(putObjectRequest).withStorageClass(eq(StorageClass.ReducedRedundancy)); - } - - @Test - public void storePutsObjectAndDoesNotUseReducedRedundancyWhenConfigured() throws IOException { - /** Setup **/ - buildCacheService = spy(new AwsS3BuildCacheService(s3, "bucketName", null, false)); - doReturn(putObjectRequest).when(buildCacheService).getPutObjectRequest(any(String.class), - any(ObjectMetadata.class), any(InputStream.class)); - - /** Run **/ - buildCacheService.store(key, writer); - - /** Check **/ - verifyThatStoreStores("abcdefghijkl123456789"); - verify(putObjectRequest, never()).withStorageClass(eq(StorageClass.ReducedRedundancy)); - } - - @Test - public void storePutsObjectAndUsesPathWhenConfigured() throws IOException { - /** Setup **/ - buildCacheService = spy(new AwsS3BuildCacheService(s3, "bucketName", "cache", false)); - doReturn(putObjectRequest).when(buildCacheService).getPutObjectRequest(eq("cache/abcdefghijkl123456789"), - any(ObjectMetadata.class), any(InputStream.class)); - - /** Run **/ - buildCacheService.store(key, writer); - - /** Check **/ - verifyThatStoreStores("cache/abcdefghijkl123456789"); - verify(putObjectRequest, never()).withStorageClass(eq(StorageClass.ReducedRedundancy)); - } - - private void verifyThatStoreStores(String bucketPath) throws IOException { - verify(writer).writeTo(any(ByteArrayOutputStream.class)); - verify(buildCacheService).getPutObjectRequest(eq(bucketPath), any(ObjectMetadata.class), any(InputStream.class)); - verify(s3).putObject(eq(putObjectRequest)); - } -}