From cc11fc691881c0a22e02a37a1cd891ffbdcf66cb Mon Sep 17 00:00:00 2001 From: Michael J Bailey Date: Fri, 18 Jan 2019 14:53:12 -0700 Subject: [PATCH 1/5] Issue #13 Add support for custom headers Some non-AWS S3 implementations need custom headers on requests. --- README.md | 2 ++ .../gradle/caching/s3/AwsS3BuildCache.java | 6 ++++++ .../AwsS3BuildCacheServiceFactory.java | 19 ++++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e28258..a583de4 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ The AWS S3 build cache implementation has a few configuration options: | `path` | The path under which all cache objects should be stored. | no | | | `reducedRedundancy` | Whether or not to use [reduced redundancy](https://aws.amazon.com/s3/reduced-redundancy/). | no | true | | `endpoint` | Alternative S3 compatible endpoint | no | | +| `headers` | A map with HTTP headers to be added to each request | no | | | `awsAccessKeyId` | The AWS access key id | no | from DefaultAWSCredentialsProviderChain | | `awsSecretKey` | The AWS secret key | no | from DefaultAWSCredentialsProviderChain | @@ -68,6 +69,7 @@ The `buildCache` configuration block might look like this: region = 'eu-west-1' bucket = 'your-bucket' push = isCiServer + headers = [ 'x-header-name': 'header-value' ] } } diff --git a/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java b/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java index 8a5962d..a48a929 100644 --- a/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java +++ b/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java @@ -16,6 +16,7 @@ package ch.myniva.gradle.caching.s3; +import java.util.Map; import org.gradle.caching.configuration.AbstractBuildCache; public class AwsS3BuildCache extends AbstractBuildCache { @@ -24,6 +25,7 @@ public class AwsS3BuildCache extends AbstractBuildCache { private String path; private boolean reducedRedundancy = true; private String endpoint; + private Map headers; private String awsAccessKeyId; private String awsSecretKey; @@ -67,6 +69,10 @@ public void setEndpoint(String endpoint) { this.endpoint = endpoint; } + public Map getHeaders() { return headers; } + + public void setHeaders(final Map headers) { this.headers = headers; } + public String getAwsAccessKeyId() { return awsAccessKeyId; } 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 index e99c329..274c3c1 100644 --- a/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.java +++ b/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.java @@ -18,13 +18,14 @@ 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.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; @@ -78,6 +79,9 @@ private AmazonS3 createS3Client(AwsS3BuildCache config) { s3Builder.withCredentials(new AWSStaticCredentialsProvider( new BasicAWSCredentials(config.getAwsAccessKeyId(), config.getAwsSecretKey()))); } + + addHttpHeaders(s3Builder, config); + if (isNullOrEmpty(config.getEndpoint())) { s3Builder.withRegion(config.getRegion()); } else { @@ -91,4 +95,17 @@ private AmazonS3 createS3Client(AwsS3BuildCache config) { } 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); + } + } } From ad769134df20c565d304c0306f8fb74e8a3c982d Mon Sep 17 00:00:00 2001 From: Michael J Bailey Date: Mon, 21 Jan 2019 14:58:45 -0700 Subject: [PATCH 2/5] Add some test to make sure it doesn't crash on nulls in the config --- README.md | 2 +- .../AwsS3BuildCacheServiceFactory.java | 2 +- .../AwsS3BuildCacheServiceFactoryTest.java | 45 +++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a583de4..5a5ed45 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The AWS S3 build cache implementation has a few configuration options: | `path` | The path under which all cache objects should be stored. | no | | | `reducedRedundancy` | Whether or not to use [reduced redundancy](https://aws.amazon.com/s3/reduced-redundancy/). | no | true | | `endpoint` | Alternative S3 compatible endpoint | no | | -| `headers` | A map with HTTP headers to be added to each request | no | | +| `headers` | A map with HTTP headers to be added to each request (nulls are ignored) | no | | | `awsAccessKeyId` | The AWS access key id | no | from DefaultAWSCredentialsProviderChain | | `awsSecretKey` | The AWS secret key | no | from DefaultAWSCredentialsProviderChain | 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 index 274c3c1..6436b0a 100644 --- a/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.java +++ b/src/main/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactory.java @@ -101,7 +101,7 @@ private void addHttpHeaders(final AmazonS3ClientBuilder s3Builder, final AwsS3Bu if (headers != null) { final ClientConfiguration clientConfiguration = new ClientConfiguration(); for (Map.Entry header : headers.entrySet()) { - if(header.getKey()!= null && header.getValue() != null) { + if(header.getKey() != null && header.getValue() != null) { clientConfiguration.addHeader(header.getKey(), header.getValue()); } } diff --git a/src/test/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactoryTest.java b/src/test/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactoryTest.java index a775621..0178baf 100644 --- a/src/test/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactoryTest.java +++ b/src/test/java/ch/myniva/gradle/caching/s3/internal/AwsS3BuildCacheServiceFactoryTest.java @@ -19,6 +19,8 @@ import static org.junit.Assert.assertNotNull; import ch.myniva.gradle.caching.s3.AwsS3BuildCache; +import java.util.HashMap; +import java.util.Map; import org.gradle.caching.BuildCacheService; import org.gradle.caching.BuildCacheServiceFactory.Describer; import org.junit.Before; @@ -58,6 +60,49 @@ public void testPath() { assertNotNull(service); } + @Test + public void testNullHeaders() { + AwsS3BuildCache conf = new AwsS3BuildCache(); + conf.setRegion("us-west-1"); + conf.setBucket("my-bucket"); + conf.setHeaders(null); + + BuildCacheService service = subject.createBuildCacheService(conf, buildCacheDescriber); + + assertNotNull(service); + } + + + @Test + public void testNullHeaderName() { + AwsS3BuildCache conf = new AwsS3BuildCache(); + conf.setRegion("us-west-1"); + conf.setBucket("my-bucket"); + Map headers = new HashMap(){{ + put(null, "foo"); + }}; + conf.setHeaders(headers); + + BuildCacheService service = subject.createBuildCacheService(conf, buildCacheDescriber); + + assertNotNull(service); + } + + @Test + public void testNullHeaderValue() { + AwsS3BuildCache conf = new AwsS3BuildCache(); + conf.setRegion("us-west-1"); + conf.setBucket("my-bucket"); + Map headers = new HashMap(){{ + put("x-foo", null); + }}; + conf.setHeaders(headers); + + BuildCacheService service = subject.createBuildCacheService(conf, buildCacheDescriber); + + assertNotNull(service); + } + @Test(expected = IllegalStateException.class) public void testIllegalConfigWithoutRegion() throws Exception { AwsS3BuildCache conf = new AwsS3BuildCache(); From 2e79a81762e913d72875e77f7076e65b2094f82c Mon Sep 17 00:00:00 2001 From: Michael J Bailey Date: Thu, 24 Jan 2019 14:10:04 -0700 Subject: [PATCH 3/5] Per PR comment, keep the config example simple --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a5ed45..1cf63f4 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The AWS S3 build cache implementation has a few configuration options: | `path` | The path under which all cache objects should be stored. | no | | | `reducedRedundancy` | Whether or not to use [reduced redundancy](https://aws.amazon.com/s3/reduced-redundancy/). | no | true | | `endpoint` | Alternative S3 compatible endpoint | no | | -| `headers` | A map with HTTP headers to be added to each request (nulls are ignored) | no | | +| `headers` | A map with HTTP headers to be added to each request (nulls are ignored). e.g. `[ 'x-header-name': 'header-value' ]` | no | | | `awsAccessKeyId` | The AWS access key id | no | from DefaultAWSCredentialsProviderChain | | `awsSecretKey` | The AWS secret key | no | from DefaultAWSCredentialsProviderChain | @@ -69,7 +69,6 @@ The `buildCache` configuration block might look like this: region = 'eu-west-1' bucket = 'your-bucket' push = isCiServer - headers = [ 'x-header-name': 'header-value' ] } } From af7e2594baed4c7a0246d9e808177c9df05939f2 Mon Sep 17 00:00:00 2001 From: Michael J Bailey Date: Thu, 24 Jan 2019 14:15:03 -0700 Subject: [PATCH 4/5] Per PR comment, use existing formatting and do a defensive copy --- .../ch/myniva/gradle/caching/s3/AwsS3BuildCache.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java b/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java index a48a929..e49f855 100644 --- a/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java +++ b/src/main/java/ch/myniva/gradle/caching/s3/AwsS3BuildCache.java @@ -16,6 +16,7 @@ package ch.myniva.gradle.caching.s3; +import java.util.HashMap; import java.util.Map; import org.gradle.caching.configuration.AbstractBuildCache; @@ -69,9 +70,13 @@ public void setEndpoint(String endpoint) { this.endpoint = endpoint; } - public Map getHeaders() { return headers; } + public Map getHeaders() { + return headers; + } - public void setHeaders(final Map headers) { this.headers = headers; } + public void setHeaders(final Map headers) { + this.headers = headers != null ? new HashMap<>(headers) : null; + } public String getAwsAccessKeyId() { return awsAccessKeyId; From aea61cd9a2d19d314497ac54b210601caff1c5f2 Mon Sep 17 00:00:00 2001 From: Michael J Bailey Date: Thu, 24 Jan 2019 14:24:10 -0700 Subject: [PATCH 5/5] Per PR comment, bump version --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index c1caba8..c45152d 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ #Currently building version -version=0.7.1 +version=0.8.0 #Previous version used to generate release notes delta previousVersion=0.7.0