diff --git a/src/main/java/hudson/plugins/s3/Redirect.java b/src/main/java/hudson/plugins/s3/Redirect.java new file mode 100644 index 00000000..980020b1 --- /dev/null +++ b/src/main/java/hudson/plugins/s3/Redirect.java @@ -0,0 +1,7 @@ +package hudson.plugins.s3; + +public final class Redirect { + public String bucket; + public String source; + public String destination; +} diff --git a/src/main/java/hudson/plugins/s3/S3BucketPublisher.java b/src/main/java/hudson/plugins/s3/S3BucketPublisher.java index efc0ae6a..2715b876 100644 --- a/src/main/java/hudson/plugins/s3/S3BucketPublisher.java +++ b/src/main/java/hudson/plugins/s3/S3BucketPublisher.java @@ -26,10 +26,7 @@ import java.io.IOException; import java.io.File; import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -42,6 +39,7 @@ public final class S3BucketPublisher extends Recorder implements Describable entries = new ArrayList(); + private List redirects = new ArrayList(); /** * User metadata key/value pairs to tag the upload with. @@ -105,6 +103,14 @@ public void setName(String profileName) { this.profileName = profileName; } + public List getRedirects() { + return redirects; + } + + public void setRedirects(List redirects) { + this.redirects = redirects; + } + @Override public Collection getProjectActions(AbstractProject project) { return ImmutableList.of(new S3ArtifactsProjectAction(project)); @@ -166,12 +172,20 @@ public boolean perform(AbstractBuild build, escapedMetadataPair.value = Util.replaceMacro(metadataPair.value, envVars); escapedUserMetadata.add(escapedMetadataPair); } + Set escapedRedirects = new HashSet(); + for (Redirect redirect : redirects) { + Redirect escapedRedirect = new Redirect(); + escapedRedirect.bucket = Util.replaceMacro(redirect.bucket, envVars); + escapedRedirect.source = Util.replaceMacro(redirect.source, envVars); + escapedRedirect.destination = Util.replaceMacro(redirect.destination, envVars); + escapedRedirects.add(escapedRedirect); + } List records = Lists.newArrayList(); for (FilePath src : paths) { - log(listener.getLogger(), "bucket=" + bucket + ", file=" + src.getName() + " region=" + selRegion + ", upload from slave=" + entry.uploadFromSlave + " managed="+ entry.managedArtifacts + " , server encryption "+entry.useServerSideEncryption); - records.add(profile.upload(build, listener, bucket, src, searchPathLength, escapedUserMetadata, storageClass, selRegion, entry.uploadFromSlave, entry.managedArtifacts, entry.useServerSideEncryption, entry.flatten)); + log(listener.getLogger(), String.format("bucket=%s, file=%s region=%s, upload from slave=%s managed=%s , server encryption %s", bucket, src.getName(), selRegion, entry.uploadFromSlave, entry.managedArtifacts, entry.useServerSideEncryption)); + records.add(profile.upload(build, listener, bucket, src, searchPathLength, escapedUserMetadata, escapedRedirects, storageClass, selRegion, entry.uploadFromSlave, entry.managedArtifacts, entry.useServerSideEncryption, entry.flatten)); } if (entry.managedArtifacts) { artifacts.addAll(records); @@ -267,6 +281,7 @@ public S3BucketPublisher newInstance(StaplerRequest req, net.sf.json.JSONObject req.bindParameters(pub, "s3."); pub.getEntries().addAll(req.bindParametersToList(Entry.class, "s3.entry.")); pub.getUserMetadata().addAll(req.bindParametersToList(MetadataPair.class, "s3.metadataPair.")); + pub.getRedirects().addAll(req.bindParametersToList(Redirect.class, "s3.redirect.")); return pub; } diff --git a/src/main/java/hudson/plugins/s3/S3Profile.java b/src/main/java/hudson/plugins/s3/S3Profile.java index f6d3a8af..17d9bca7 100644 --- a/src/main/java/hudson/plugins/s3/S3Profile.java +++ b/src/main/java/hudson/plugins/s3/S3Profile.java @@ -1,35 +1,27 @@ package hudson.plugins.s3; import com.amazonaws.ClientConfiguration; -import hudson.FilePath; - -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; -import java.net.URL; -import java.util.Date; -import java.util.List; - -import org.apache.tools.ant.types.selectors.FilenameSelector; -import org.kohsuke.stapler.DataBoundConstructor; - import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.services.s3.model.DeleteObjectRequest; -import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; -import com.amazonaws.services.s3.model.GetObjectRequest; -import com.amazonaws.services.s3.model.ListObjectsRequest; -import com.amazonaws.services.s3.model.ObjectListing; -import com.amazonaws.services.s3.model.ResponseHeaderOverrides; -import com.amazonaws.services.s3.model.S3ObjectSummary; +import com.amazonaws.services.s3.model.*; import com.google.common.collect.Lists; - -import hudson.model.BuildListener; +import hudson.FilePath; import hudson.model.AbstractBuild; +import hudson.model.BuildListener; import hudson.model.Run; import hudson.plugins.s3.callable.S3DownloadCallable; import hudson.plugins.s3.callable.S3UploadCallable; import hudson.util.Secret; +import org.apache.tools.ant.types.selectors.FilenameSelector; +import org.kohsuke.stapler.DataBoundConstructor; + +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.net.URL; +import java.util.Date; +import java.util.List; +import java.util.Set; public class S3Profile { private String name; @@ -113,7 +105,7 @@ public void check() throws Exception { getClient().listBuckets(); } - public FingerprintRecord upload(AbstractBuild build, final BuildListener listener, String bucketName, FilePath filePath, int searchPathLength, List userMetadata, + public FingerprintRecord upload(AbstractBuild build, final BuildListener listener, String bucketName, FilePath filePath, int searchPathLength, List userMetadata, Set redirects, String storageClass, String selregion, boolean uploadFromSlave, boolean managedArtifacts,boolean useServerSideEncryption, boolean flatten) throws IOException, InterruptedException { if (filePath.isDirectory()) { throw new IOException(filePath + " is a directory"); @@ -135,7 +127,7 @@ public FingerprintRecord upload(AbstractBuild build, final BuildListener li } try { - S3UploadCallable callable = new S3UploadCallable(produced, accessKey, secretKey, useRole, dest, userMetadata, storageClass, selregion,useServerSideEncryption); + S3UploadCallable callable = new S3UploadCallable(produced, accessKey, secretKey, useRole, dest, userMetadata, redirects, storageClass, selregion,useServerSideEncryption); if (uploadFromSlave) { return filePath.act(callable); } else { diff --git a/src/main/java/hudson/plugins/s3/callable/S3UploadCallable.java b/src/main/java/hudson/plugins/s3/callable/S3UploadCallable.java index d0655570..a06a8590 100644 --- a/src/main/java/hudson/plugins/s3/callable/S3UploadCallable.java +++ b/src/main/java/hudson/plugins/s3/callable/S3UploadCallable.java @@ -1,10 +1,17 @@ package hudson.plugins.s3.callable; +import com.amazonaws.regions.Region; +import com.amazonaws.regions.RegionUtils; +import com.amazonaws.regions.Regions; +import com.amazonaws.services.s3.internal.Mimetypes; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectResult; import hudson.FilePath; import hudson.FilePath.FileCallable; import hudson.plugins.s3.Destination; import hudson.plugins.s3.FingerprintRecord; import hudson.plugins.s3.MetadataPair; +import hudson.plugins.s3.Redirect; import hudson.remoting.VirtualChannel; import hudson.util.Secret; @@ -12,29 +19,25 @@ import java.io.IOException; import java.util.Date; import java.util.List; - -import com.amazonaws.regions.Region; -import com.amazonaws.regions.RegionUtils; -import com.amazonaws.regions.Regions; -import com.amazonaws.services.s3.internal.Mimetypes; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectResult; +import java.util.Set; public class S3UploadCallable extends AbstractS3Callable implements FileCallable { private static final long serialVersionUID = 1L; private final Destination dest; private final String storageClass; private final List userMetadata; + private final Set redirects; private final String selregion; private final boolean produced; private final boolean useServerSideEncryption; - public S3UploadCallable(boolean produced, String accessKey, Secret secretKey, boolean useRole, Destination dest, List userMetadata, String storageClass, + public S3UploadCallable(boolean produced, String accessKey, Secret secretKey, boolean useRole, Destination dest, List userMetadata, Set redirects, String storageClass, String selregion, boolean useServerSideEncryption) { super(accessKey, secretKey, useRole); this.dest = dest; this.storageClass = storageClass; this.userMetadata = userMetadata; + this.redirects = redirects; this.selregion = selregion; this.produced = produced; this.useServerSideEncryption = useServerSideEncryption; @@ -71,6 +74,11 @@ public FingerprintRecord invoke(File file, VirtualChannel channel) throws IOExce public FingerprintRecord invoke(FilePath file) throws IOException, InterruptedException { setRegion(); PutObjectResult result = getClient().putObject(dest.bucketName, dest.objectName, file.read(), buildMetadata(file)); + + for (Redirect redirect : redirects) { + getClient().setObjectRedirectLocation(redirect.bucket, redirect.source, redirect.destination); + } + return new FingerprintRecord(produced, dest.bucketName, file.getName(), result.getETag()); } diff --git a/src/main/resources/hudson/plugins/s3/S3BucketPublisher/config.jelly b/src/main/resources/hudson/plugins/s3/S3BucketPublisher/config.jelly index dfe9a4cc..2216e83a 100644 --- a/src/main/resources/hudson/plugins/s3/S3BucketPublisher/config.jelly +++ b/src/main/resources/hudson/plugins/s3/S3BucketPublisher/config.jelly @@ -75,4 +75,25 @@ + + + + + + + + + + + + + + +
+ +
+
+
+
+
diff --git a/src/main/webapp/help-redirect-bucket.html b/src/main/webapp/help-redirect-bucket.html new file mode 100644 index 00000000..268b7a7e --- /dev/null +++ b/src/main/webapp/help-redirect-bucket.html @@ -0,0 +1,3 @@ +
+ The bucket in which the source file is located. +
\ No newline at end of file diff --git a/src/main/webapp/help-redirect-destination.html b/src/main/webapp/help-redirect-destination.html new file mode 100644 index 00000000..a90b2bc8 --- /dev/null +++ b/src/main/webapp/help-redirect-destination.html @@ -0,0 +1,3 @@ +
+ Destination of the redirect. +
\ No newline at end of file diff --git a/src/main/webapp/help-redirect-source.html b/src/main/webapp/help-redirect-source.html new file mode 100644 index 00000000..ddaf99b9 --- /dev/null +++ b/src/main/webapp/help-redirect-source.html @@ -0,0 +1,3 @@ +
+ The key (path in the bucket) of the file to be redirected. +
\ No newline at end of file