Skip to content

Commit

Permalink
Merge pull request #100 from cyrille-leclerc/master
Browse files Browse the repository at this point in the history
[JENKINS-40654] Make plugin compatible with storage backends compatible with Amazon S3 (OpenStack Swift...)
  • Loading branch information
Jimilian committed Dec 23, 2016
2 parents 92247d2 + 2d1b795 commit 945f331
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 17 deletions.
17 changes: 17 additions & 0 deletions README.md
Expand Up @@ -25,6 +25,23 @@ and a post-build action called `Publish Artifacts to S3 Bucket`.
For Pipeline users, the same two actions are available via the
`step` step. You can use the snippet generator to get started.

When using an Amazon S3 compatible storage system (OpenStack Swift, EMC Atmos...),
the list of AWS regions can be overridden specifying a file
`classpath://com/amazonaws/partitions/override/endpoints.json` matching the format
defined in AWS SDK's [endpoints.json](https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/resources/com/amazonaws/partitions/endpoints.json).

A solution to add this `endpoints.json` file in the classpath of Jenkins is to use the
`java` command line parameter `-Xbootclasspath/a:/path/to/boot/classpath/folder/` and
to locate `com/amazonaws/partitions/override/endpoints.json` in `/path/to/boot/classpath/folder/`.


Even if most of the features of the Jenkins S3 Plugin require the user to specify the target region,
some feature rely on a default Amazon S3 region which is by default the "US Standard Amazon S3 Region"
and its endpoint `s3.amazonaws.com`. This default region can be overridden with the system property
`hudson.plugins.s3.DEFAULT_AMAZON_S3_REGION`.
Note that this default region name MUST match with a region define in the AWS SDK configuration file `endpoints.json`
(see above).

Notes
=====

Expand Down
60 changes: 48 additions & 12 deletions src/main/java/hudson/plugins/s3/ClientHelper.java
Expand Up @@ -5,51 +5,87 @@
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.AmazonS3Client;
import hudson.ProxyConfiguration;

import java.util.regex.Pattern;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class ClientHelper {

public static String DEFAULT_AMAZON_S3_REGION_NAME = System.getProperty(
"hudson.plugins.s3.DEFAULT_AMAZON_S3_REGION",
com.amazonaws.services.s3.model.Region.US_Standard.toAWSRegion().getName());

/**
* This method should be deprecated to always use an AWS region with {@link #createClient(String, String, boolean, String, ProxyConfiguration)}
*/
public static AmazonS3Client createClient(String accessKey, String secretKey, boolean useRole, ProxyConfiguration proxy)
{
return createClient(accessKey, secretKey, useRole, null, proxy);
return createClient(accessKey, secretKey, useRole, DEFAULT_AMAZON_S3_REGION_NAME, proxy);
}

public static AmazonS3Client createClient(String accessKey, String secretKey, boolean useRole, String region, ProxyConfiguration proxy)
{
final AmazonS3Client client;
Region awsRegion = getRegionFromString(region);

ClientConfiguration clientConfiguration = getClientConfiguration(proxy, awsRegion);

final AmazonS3Client client;
if (useRole) {
client = new AmazonS3Client(getClientConfiguration(proxy));
client = new AmazonS3Client(clientConfiguration);
} else {
client = new AmazonS3Client(new BasicAWSCredentials(accessKey, secretKey), getClientConfiguration(proxy));
client = new AmazonS3Client(new BasicAWSCredentials(accessKey, secretKey), clientConfiguration);
}

if (region != null)
{
client.setRegion(getRegionFromString(region));
}
client.setRegion(awsRegion);

return client;
}

private static Region getRegionFromString(String regionName) {
/**
* Gets the {@link Region} from its name with backward compatibility concerns and defaulting
*
* @param regionName nullable region name
* @return AWS region, never {@code null}, defaults to {@link com.amazonaws.services.s3.model.Region#US_Standard}
*/
@Nonnull
private static Region getRegionFromString(@Nullable String regionName) {
Region region = null;

if (regionName == null || regionName.isEmpty()) {
region = RegionUtils.getRegion(DEFAULT_AMAZON_S3_REGION_NAME);
}
// In 0.7, selregion comes from Regions#name
Region region = RegionUtils.getRegion(regionName);
if (region == null) {
region = RegionUtils.getRegion(regionName);
}

// In 0.6, selregion comes from Regions#valueOf
if (region == null) {
region = RegionUtils.getRegion(Regions.valueOf(regionName).getName());
}

if (region == null) {
region = RegionUtils.getRegion(DEFAULT_AMAZON_S3_REGION_NAME);
}

if (region == null) {
throw new IllegalStateException("No AWS Region found for name '" + regionName + "' and default region '" + DEFAULT_AMAZON_S3_REGION_NAME + "'");
}
return region;
}

public static ClientConfiguration getClientConfiguration(ProxyConfiguration proxy) {
@Nonnull
public static ClientConfiguration getClientConfiguration(@Nonnull ProxyConfiguration proxy, @Nonnull Region region) {
final ClientConfiguration clientConfiguration = new ClientConfiguration();

if (shouldUseProxy(proxy, "s3.amazonaws.com")) {
String s3Endpoint = region.getServiceEndpoint(AmazonS3.ENDPOINT_PREFIX);

if (shouldUseProxy(proxy, s3Endpoint)) {
clientConfiguration.setProxyHost(proxy.name);
clientConfiguration.setProxyPort(proxy.port);
if (proxy.getUserName() != null) {
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/hudson/plugins/s3/Entry.java
@@ -1,6 +1,8 @@
package hudson.plugins.s3;

import com.amazonaws.regions.Regions;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.RegionUtils;
import com.amazonaws.services.s3.AmazonS3;
import hudson.Extension;
import hudson.model.Describable;
import hudson.model.Descriptor;
Expand Down Expand Up @@ -36,7 +38,7 @@ public final class Entry implements Describable<Entry> {
/**
* Regions Values
*/
public static final Regions[] regions = Regions.values();
public static final List<Region> regions = RegionUtils.getRegionsForService(AmazonS3.ENDPOINT_PREFIX);
/**
* Stores the Region Value
*/
Expand Down Expand Up @@ -134,7 +136,7 @@ public ListBoxModel doFillStorageClassItems() {

public ListBoxModel doFillSelectedRegionItems() {
final ListBoxModel model = new ListBoxModel();
for (Regions r : regions) {
for (Region r : regions) {
model.add(r.getName(), r.getName());
}
return model;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/hudson/plugins/s3/S3BucketPublisher.java
@@ -1,7 +1,7 @@
package hudson.plugins.s3;

import com.amazonaws.AmazonClientException;
import com.amazonaws.regions.Regions;
import com.amazonaws.regions.Region;
import com.amazonaws.services.s3.AmazonS3Client;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
Expand Down Expand Up @@ -365,7 +365,7 @@ public DescriptorImpl(Class<? extends Publisher> clazz) {
load();
}

public Regions[] regions = Entry.regions;
public List<Region> regions = Entry.regions;

public String[] storageClasses = Entry.storageClasses;

Expand Down

0 comments on commit 945f331

Please sign in to comment.