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

Handle corner case in getLatest artifact, which cascades to Poller #61

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
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ private GoPluginApiResponse handleLatestRevisionSince(GoPluginApiRequest goPlugi
S3ArtifactStore artifactStore = s3ArtifactStore(s3Bucket);
try {
RevisionStatus revision = artifactStore.getLatest(artifact(packageKeyValuePairs));
if (!revision.isValid) {
logger.warn("Received invalid revision from artifact store with this message: "+revision.toString());
return createResponse(DefaultGoPluginApiResponse.INTERNAL_ERROR, revision.toMap());
}

if(new Revision(revision.revision.getRevision()).compareTo(new Revision(previousRevision)) > 0) {
return createResponse(DefaultGoPluginApiResponse.SUCCESS_RESPONSE_CODE, revision.toMap());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import java.util.Date

import com.amazonaws.services.s3.AmazonS3Client
import com.google.gson.GsonBuilder
import com.indix.gocd.models.{Artifact, Revision, RevisionStatus}
import com.indix.gocd.models.{Artifact, BadRevisionStatus, Revision, RevisionStatus}
import com.indix.gocd.utils.store.S3ArtifactStore
import com.thoughtworks.go.plugin.api.request.GoPluginApiRequest
import org.mockito.Matchers
Expand Down Expand Up @@ -71,6 +71,38 @@ class S3PackageMaterialPollerSpec extends FlatSpec with MockitoSugar with org.sc
assert(resultMap == null)
}

it should "handle BadRevisionStatus response from artifact store appropriately" in {
val status = new BadRevisionStatus(new Artifact("Pipeline", "Stage", "Job", new Revision("1.1")), "No valid revision found for this artifact")
doReturn(status).when(mockS3ArtifactStore).getLatest(Matchers.any[Artifact])
val result = sut.handle(getRequest(S3PackageMaterialPoller.REQUEST_LATEST_REVISION_SINCE, """
|{
| "repository-configuration": {
| "S3_BUCKET": {
| "value": "S3 Bucket"
| }
| },
| "package-configuration": {
| "PIPELINE_NAME": {
| "value": "Pipeline"
| },
| "STAGE_NAME": {
| "value": "Stage"
| },
| "JOB_NAME": {
| "value": "Job"
| }
| },
| "previous-revision": {
| "revision": "1.1",
| "timestamp": ""
| }
|}
""".stripMargin))
val resultMap = new GsonBuilder().create.fromJson[AnyRef](result.responseBody(), classOf[Any])
assert(result.responseCode() == 200)
Copy link
Contributor Author

@brewkode brewkode Jan 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't understand this. I send a INTERNAL_ERROR when handling this particular request from the Plugin side via createResponse(DefaultGoPluginApiResponse.INTERNAL_ERROR, revision.toMap()) . However, the response that's received still has 200 status. I checked other tests which asserts some failures, which returns INTERNAL_ERROR, they also have assertions expecting a 200 response code. Perhaps, is this how, plugin api response is expected?

assert(resultMap == null)
}

it should "get more latest revision since previous revision" in {
val status = new RevisionStatus(new Revision("1.2"), new Date(), "", "", "")
doReturn(status).when(mockS3ArtifactStore).getLatest(Matchers.any[Artifact])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public TaskExecutionResult execute(Config config, final Context context) {
}
}

// A configured destination prefix is used to deploy files rather than publish artifacts
// We want to set metadata only when publishing artifacts
if(!hasConfigDestinationPrefix(config)) {
setMetadata(env, bucket, destinationPrefix, store);
}
Expand Down
33 changes: 33 additions & 0 deletions utils/src/main/java/com/indix/gocd/models/BadRevisionStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.indix.gocd.models;

import java.util.HashMap;
import java.util.Map;

public class BadRevisionStatus extends RevisionStatus {
public Artifact artifact = null;
public Boolean isValid = false;
public String msg = null;
public BadRevisionStatus(Artifact artifact, String msg) {
super(artifact.revision, null, null, null, null);
this.artifact = artifact;
this.msg = msg;
this.isValid = false;
}

@Override
public String toString() {
return "BadRevisionStatus{" +
"artifact=" + artifact.prefixWithRevision() +
", msg=" + msg +
'}';
}

@Override
public Map toMap() {
final HashMap result = new HashMap();
result.put("artifact", artifact.prefixWithRevision());
result.put("msg", this.msg);

return result;
}
}
2 changes: 2 additions & 0 deletions utils/src/main/java/com/indix/gocd/models/Revision.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.indix.gocd.models;

import java.util.Arrays;

public class Revision implements Comparable {
private String revision;
private String[] parts;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class RevisionStatus {
public String tracebackUrl;
public String user;
public String revisionLabel;
public Boolean isValid = true;
private static final String DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

public RevisionStatus(Revision revision, Date lastModified, String tracebackUrl, String user) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.indix.gocd.models.Artifact;
import com.indix.gocd.models.ResponseMetadataConstants;
import com.indix.gocd.models.Revision;
import com.indix.gocd.models.RevisionStatus;
import com.indix.gocd.models.*;
import com.indix.gocd.utils.GoEnvironment;
import com.indix.gocd.utils.utils.Function;
import com.indix.gocd.utils.utils.Functions;
Expand Down Expand Up @@ -183,6 +180,9 @@ public RevisionStatus getLatest(Artifact artifact) {
ObjectListing listing = client.listObjects(listObjectsRequest);
if (listing != null) {
Revision recent = latestOf(listing);
if (recent.compareTo(Revision.base()) == 0) {
return new BadRevisionStatus(artifact, "No artifacts found which are later than this");
}
Artifact artifactWithRevision = artifact.withRevision(recent);
GetObjectMetadataRequest objectMetadataRequest = new GetObjectMetadataRequest(bucket, artifactWithRevision.prefixWithRevision());
ObjectMetadata metadata = client.getObjectMetadata(objectMetadataRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.indix.gocd.models.Artifact;
import com.indix.gocd.models.BadRevisionStatus;
import com.indix.gocd.models.RevisionStatus;
import com.indix.gocd.utils.GoEnvironment;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
Expand All @@ -20,6 +23,7 @@
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;

Expand Down Expand Up @@ -114,6 +118,18 @@ public void shouldReturnNullWhenObjectListingIsSize0() {
assertNull(prefix);
}

@Test
public void shouldReturnBadRevisionStatusOnGetLatest() {
ObjectListing listing = new ObjectListing();
doReturn(listing).when(mockClient).listObjects(any(ListObjectsRequest.class));
S3ArtifactStore store = new S3ArtifactStore(mockClient, "foo-bar");

RevisionStatus status = store.getLatest(new Artifact("pipeline", "stage", "job"));
assertNotNull(status);
assertEquals(status instanceof BadRevisionStatus, true);
}


@Test
public void shouldReturnTheLatestStageCounter() {
ObjectListing listing = new ObjectListing();
Expand Down