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

Improve error handling and stability for Jenkins Plugin #30

Open
wants to merge 3 commits 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 @@ -7,22 +7,46 @@
import jenkins.model.TransientActionFactory;

import javax.annotation.Nonnull;
import java.lang.System;
import java.lang.Thread;
import java.util.concurrent.TimeUnit;
import java.util.Collection;
import java.util.Collections;



/**
* Creates our action for showing and displaying current status.
*/
@Extension
public class SDElementsActionFactory extends TransientActionFactory<Job> {
// seconds to wait for a complete build
private static final int TIMEOUT = 10;
// milliseconds to wait between build checks
private static final int INTERVAL = 1000;

@Override
public Class<Job> type() {
return Job.class;
}

private void waitForBuild(@Nonnull Job job, int timeout) throws InterruptedException {
long timeStarted = System.currentTimeMillis();
long timeoutMs = TimeUnit.SECONDS.toMillis(timeout);

while (job.getLastCompletedBuild() == null && System.currentTimeMillis() - timeStarted < timeoutMs) {
Thread.sleep(INTERVAL);
}
}

@Nonnull
@Override
public Collection<? extends Action> createFor(@Nonnull Job job) {
try {
waitForBuild(job, TIMEOUT);
} catch (InterruptedException e) {
// sleep was interrupted, continue
}
Run<?,?> r = job.getLastCompletedBuild();
SDElementsRiskIndicatorBuildAction sdba = r.getAction(SDElementsRiskIndicatorBuildAction.class);
SDElementsRiskIndicatorProjectAction sdpa = new SDElementsRiskIndicatorProjectAction(sdba.getRiskIndicator(), sdba.getProjectUrl(), sdba.getBaseUrl());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;

import org.json.JSONObject;
import org.json.JSONException;

import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Objects;


public class SDElementsLibrary {

private final String accessKey;
Expand All @@ -21,30 +24,61 @@ public SDElementsLibrary(String accessKey, String url) {
this.url = Objects.requireNonNull(url, "url must not be null");
}

private HttpResponse<JsonNode> getProject(int id) throws SDLibraryException {
private JsonNode getProject(int id) throws SDLibraryException {
String projects = url + "/api/" + apiVersion + "/projects/"+id+"/";
HashMap<String,String> headers = new HashMap<>();
headers.put("Accept", "application/json");
headers.put("Authorization","Token "+accessKey);
HttpResponse<JsonNode> resp = null;

HttpResponse<String> response = null;
try {
resp = Unirest.get(projects).
headers(headers).asJson();
response = Unirest.get(projects)
.headers(headers)
.asString();
} catch (UnirestException e) {
if(e.getCause() instanceof UnknownHostException) {
throw new SDLibraryException("Host not found: "+url, e);
if (e.getCause() instanceof UnknownHostException) {
throw new SDLibraryException("Host not found: " + url, e);
}
else throw new UnhandledSDLibraryException("Unknown error encountered", e);
String errorMessage = "Unknown exception encountered.";
if (e.getCause() != null) {
errorMessage = (
errorMessage +
"\nException message: " +
e.getCause().getMessage()
);
}
throw new UnhandledSDLibraryException(errorMessage, e);
}

// attempt to manually parse the original string so we can stil pass
// along the original body in case of error.
String body = response.getBody();
JsonNode node = null;
try {
node = new JsonNode(body);
} catch (JSONException e) {
throw new SDLibraryException(
"Unable to parse non-JSON API response.: \n" + body,
response
);
}

// Raise error for any known error conditions for the request
int status = response.getStatus();
if(status == 404 && node != null && node.getObject().getString("detail").equals("Not found.")) {
throw new SDLibraryException("Project with id "+id+" Not found", response);
}
return resp;

if(status == 401 && node != null && node.getObject().getString("detail").equals("Invalid token.")) {
throw new SDLibraryException("Invalid token in credentials", response);
}

return node;
}

public String getProjectUrl(int id) throws SDLibraryException {
HttpResponse<JsonNode> node = getProject(id);
if(node.getStatus() == 200) {
return node.getBody().getObject().getString("url");
}
return null;
JsonNode node = getProject(id);
return node.getObject().getString("url");
}

/**
Expand All @@ -54,27 +88,20 @@ public String getProjectUrl(int id) throws SDLibraryException {
* @throws SDLibraryException when we determine that we didn't get a correct result from SDElements. Empty result, or access denied
*/
public RiskPolicyCompliance getProjectCompliance(int id) throws SDLibraryException {
HttpResponse<JsonNode> node = getProject(id);
int status = node.getStatus();
JsonNode body = node.getBody();
if(status == 404 && body != null && body.getObject().getString("detail").equals("Not found.")) {
throw new SDLibraryException("Project with id "+id+" Not found", node);
} else if(status == 401 && body != null && body.getObject().getString("detail").equals("Invalid token.")) {
throw new SDLibraryException("Invalid token in credentials", node);
} else {
JSONObject obj = node.getBody().getObject();
if (obj != null) {
if (obj.isNull("risk_policy_compliant")) {
return RiskPolicyCompliance.UNDETERMINED;
}
if (obj.getBoolean("risk_policy_compliant")) {
return RiskPolicyCompliance.PASS;
} else {
return RiskPolicyCompliance.FAIL;
}
JsonNode node = getProject(id);
JSONObject obj = node.getObject();

if (obj != null) {
if (obj.isNull("risk_policy_compliant")) {
return RiskPolicyCompliance.UNDETERMINED;
}
if (obj.getBoolean("risk_policy_compliant")) {
return RiskPolicyCompliance.PASS;
} else {
throw new UnhandledSDLibraryException("Unknown response detected for project with id: " + id, node);
return RiskPolicyCompliance.FAIL;
}
} else {
throw new UnhandledSDLibraryException("Unknown response detected for project with id: " + id);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public SDLibraryException(String message, Throwable cause) {
super(message, cause);
}

public SDLibraryException(String message) {
super(message);
}

@Override
public String getMessage() {
if(resp != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ public UnhandledSDLibraryException(String message, HttpResponse<?> resp) {
public UnhandledSDLibraryException(String message, Throwable cause) {
super(message, cause);
}

public UnhandledSDLibraryException(String message) {
super(message);
}
}