Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for redirects #32

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/main/java/hudson/plugins/s3/Redirect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package hudson.plugins.s3;

public final class Redirect {
public String bucket;
public String source;
public String destination;
}
27 changes: 21 additions & 6 deletions src/main/java/hudson/plugins/s3/S3BucketPublisher.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -42,6 +39,7 @@ public final class S3BucketPublisher extends Recorder implements Describable<Pub
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();

private final List<Entry> entries = new ArrayList<Entry>();
private List<Redirect> redirects = new ArrayList<Redirect>();

/**
* User metadata key/value pairs to tag the upload with.
Expand Down Expand Up @@ -105,6 +103,14 @@ public void setName(String profileName) {
this.profileName = profileName;
}

public List<Redirect> getRedirects() {
return redirects;
}

public void setRedirects(List<Redirect> redirects) {
this.redirects = redirects;
}

@Override
public Collection<? extends Action> getProjectActions(AbstractProject<?, ?> project) {
return ImmutableList.of(new S3ArtifactsProjectAction(project));
Expand Down Expand Up @@ -166,12 +172,20 @@ public boolean perform(AbstractBuild<?, ?> build,
escapedMetadataPair.value = Util.replaceMacro(metadataPair.value, envVars);
escapedUserMetadata.add(escapedMetadataPair);
}
Set<Redirect> escapedRedirects = new HashSet<Redirect>();
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<FingerprintRecord> 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);
Expand Down Expand Up @@ -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;
}

Expand Down
38 changes: 15 additions & 23 deletions src/main/java/hudson/plugins/s3/S3Profile.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<MetadataPair> userMetadata,
public FingerprintRecord upload(AbstractBuild<?,?> build, final BuildListener listener, String bucketName, FilePath filePath, int searchPathLength, List<MetadataPair> userMetadata, Set<Redirect> 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");
Expand All @@ -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 {
Expand Down
24 changes: 16 additions & 8 deletions src/main/java/hudson/plugins/s3/callable/S3UploadCallable.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,43 @@
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;

import java.io.File;
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<FingerprintRecord> {
private static final long serialVersionUID = 1L;
private final Destination dest;
private final String storageClass;
private final List<MetadataPair> userMetadata;
private final Set<Redirect> 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<MetadataPair> userMetadata, String storageClass,
public S3UploadCallable(boolean produced, String accessKey, Secret secretKey, boolean useRole, Destination dest, List<MetadataPair> userMetadata, Set<Redirect> 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;
Expand Down Expand Up @@ -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());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,25 @@
</table>
</f:repeatable>
</f:entry>

<f:entry title="Redirects">
<f:repeatable var="r" items="${instance.redirects}">
<table width="100%">
<f:entry title="Bucket" help="${helpURL}/help-redirect-bucket.html">
<f:textbox name="s3.redirect.bucket" value="${r.bucket}" />
</f:entry>
<f:entry title="Object to redirect" help="${helpURL}/help-redirect-source.html">
<f:textbox name="s3.redirect.source" value="${r.source}" />
</f:entry>
<f:entry title="Target" help="${helpURL}/help-redirect-destination.html">
<f:textbox name="s3.redirect.destination" value="${r.destination}" />
</f:entry>
<f:entry title="">
<div align="right">
<f:repeatableDeleteButton />
</div>
</f:entry>
</table>
</f:repeatable>
</f:entry>
</j:jelly>
3 changes: 3 additions & 0 deletions src/main/webapp/help-redirect-bucket.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
The bucket in which the source file is located.
</div>
3 changes: 3 additions & 0 deletions src/main/webapp/help-redirect-destination.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
Destination of the redirect.
</div>
3 changes: 3 additions & 0 deletions src/main/webapp/help-redirect-source.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
The key (path in the bucket) of the file to be redirected.
</div>