mirror of https://github.com/apache/jclouds.git
Properly handler ProfitBricks service errors
This commit is contained in:
parent
59a88ff898
commit
72f2652dca
|
@ -302,11 +302,16 @@ public class ProfitBricksComputeServiceAdapter implements ComputeServiceAdapter<
|
||||||
public Provisionable getImage(String id) {
|
public Provisionable getImage(String id) {
|
||||||
// try search images
|
// try search images
|
||||||
logger.trace("<< searching for image with id=%s", id);
|
logger.trace("<< searching for image with id=%s", id);
|
||||||
|
try {
|
||||||
Image image = api.imageApi().getImage(id);
|
Image image = api.imageApi().getImage(id);
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
logger.trace(">> found image [%s].", image.name());
|
logger.trace(">> found image [%s].", image.name());
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.warn(ex, ">> unexpected error getting image. Trying to get as a snapshot...");
|
||||||
|
}
|
||||||
|
|
||||||
// try search snapshots
|
// try search snapshots
|
||||||
logger.trace("<< not found from images. searching for snapshot with id=%s", id);
|
logger.trace("<< not found from images. searching for snapshot with id=%s", id);
|
||||||
Snapshot snapshot = api.snapshotApi().getSnapshot(id);
|
Snapshot snapshot = api.snapshotApi().getSnapshot(id);
|
||||||
|
|
|
@ -16,12 +16,33 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.profitbricks.domain;
|
package org.jclouds.profitbricks.domain;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.auto.value.AutoValue;
|
import com.google.auto.value.AutoValue;
|
||||||
import com.google.common.base.Enums;
|
import com.google.common.base.Enums;
|
||||||
|
|
||||||
@AutoValue
|
@AutoValue
|
||||||
public abstract class ServiceFault {
|
public abstract class ServiceFault {
|
||||||
|
|
||||||
|
public abstract String faultCode();
|
||||||
|
public abstract String faultString();
|
||||||
|
@Nullable public abstract Details details();
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new AutoValue_ServiceFault.Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder faultCode(String faultCode);
|
||||||
|
public abstract Builder faultString(String faultString);
|
||||||
|
public abstract Builder details(Details details);
|
||||||
|
public abstract ServiceFault build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class Details {
|
||||||
|
|
||||||
public enum FaultCode {
|
public enum FaultCode {
|
||||||
|
|
||||||
BAD_REQUEST,
|
BAD_REQUEST,
|
||||||
|
@ -42,29 +63,21 @@ public abstract class ServiceFault {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract FaultCode faultCode();
|
public abstract FaultCode faultCode();
|
||||||
|
|
||||||
public abstract int httpCode();
|
public abstract int httpCode();
|
||||||
|
|
||||||
public abstract String message();
|
public abstract String message();
|
||||||
|
|
||||||
public abstract int requestId();
|
public abstract int requestId();
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
return new AutoValue_ServiceFault.Builder();
|
return new AutoValue_ServiceFault_Details.Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AutoValue.Builder
|
@AutoValue.Builder
|
||||||
public abstract static class Builder {
|
public abstract static class Builder {
|
||||||
|
|
||||||
public abstract Builder faultCode(FaultCode faultCode);
|
public abstract Builder faultCode(FaultCode faultCode);
|
||||||
|
|
||||||
public abstract Builder httpCode(int httpCode);
|
public abstract Builder httpCode(int httpCode);
|
||||||
|
|
||||||
public abstract Builder message(String message);
|
public abstract Builder message(String message);
|
||||||
|
|
||||||
public abstract Builder requestId(int requestId);
|
public abstract Builder requestId(int requestId);
|
||||||
|
public abstract Details build();
|
||||||
public abstract ServiceFault build();
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.profitbricks.handlers;
|
package org.jclouds.profitbricks.handlers;
|
||||||
|
|
||||||
|
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
|
||||||
import static org.jclouds.util.Closeables2.closeQuietly;
|
import static org.jclouds.util.Closeables2.closeQuietly;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -39,7 +40,15 @@ public class ProfitBricksHttpErrorHandler implements HttpErrorHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleError(final HttpCommand command, final HttpResponse response) {
|
public void handleError(final HttpCommand command, final HttpResponse response) {
|
||||||
Exception exception = null;
|
// it is important to always read fully and close streams
|
||||||
|
byte[] data = closeClientButKeepContentStream(response);
|
||||||
|
String message = data != null ? new String(data) : null;
|
||||||
|
|
||||||
|
Exception exception = message != null ? new HttpResponseException(command, response, message)
|
||||||
|
: new HttpResponseException(command, response);
|
||||||
|
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
|
||||||
|
response.getStatusLine());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch (response.getStatusCode()) {
|
switch (response.getStatusCode()) {
|
||||||
case 400:
|
case 400:
|
||||||
|
@ -49,6 +58,9 @@ public class ProfitBricksHttpErrorHandler implements HttpErrorHandler {
|
||||||
case 401:
|
case 401:
|
||||||
exception = new AuthorizationException("This request requires authentication.", exception);
|
exception = new AuthorizationException("This request requires authentication.", exception);
|
||||||
break;
|
break;
|
||||||
|
case 403:
|
||||||
|
exception = new AuthorizationException(response.getMessage(), exception);
|
||||||
|
break;
|
||||||
case 402:
|
case 402:
|
||||||
case 409:
|
case 409:
|
||||||
exception = new IllegalStateException(response.getMessage(), exception);
|
exception = new IllegalStateException(response.getMessage(), exception);
|
||||||
|
|
|
@ -94,10 +94,13 @@ public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl
|
||||||
try {
|
try {
|
||||||
if (isSoapPayload(in)) {
|
if (isSoapPayload(in)) {
|
||||||
ServiceFault fault = faultHandler.parse(in);
|
ServiceFault fault = faultHandler.parse(in);
|
||||||
if (fault != null)
|
if (fault != null) {
|
||||||
responseBuilder
|
if (fault.details() != null) {
|
||||||
.statusCode(fault.httpCode())
|
responseBuilder.statusCode(fault.details().httpCode()).message(fault.details().message());
|
||||||
.message(fault.message());
|
} else {
|
||||||
|
responseBuilder.message(fault.faultString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// ignore
|
// ignore
|
||||||
|
|
|
@ -17,27 +17,40 @@
|
||||||
package org.jclouds.profitbricks.http.parser;
|
package org.jclouds.profitbricks.http.parser;
|
||||||
|
|
||||||
import org.jclouds.profitbricks.domain.ServiceFault;
|
import org.jclouds.profitbricks.domain.ServiceFault;
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
public class ServiceFaultResponseHandler extends BaseProfitBricksResponseHandler<ServiceFault> {
|
public class ServiceFaultResponseHandler extends BaseProfitBricksResponseHandler<ServiceFault> {
|
||||||
|
|
||||||
private final ServiceFault.Builder builder;
|
private final ServiceFault.Builder builder;
|
||||||
|
private ServiceFault.Details.Builder detailsBuilder;
|
||||||
private boolean done = false;
|
private boolean done = false;
|
||||||
|
|
||||||
ServiceFaultResponseHandler() {
|
ServiceFaultResponseHandler() {
|
||||||
this.builder = ServiceFault.builder();
|
this.builder = ServiceFault.builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||||
|
if ("detail".equals(qName)) {
|
||||||
|
detailsBuilder = ServiceFault.Details.builder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setPropertyOnEndTag(String qName) {
|
protected void setPropertyOnEndTag(String qName) {
|
||||||
if ("faultCode".equals(qName))
|
if ("faultcode".equals(qName))
|
||||||
builder.faultCode(ServiceFault.FaultCode.fromValue(textToStringValue()));
|
builder.faultCode(textToStringValue());
|
||||||
|
else if ("faultstring".equals(qName))
|
||||||
|
builder.faultString(textToStringValue());
|
||||||
|
else if ("faultCode".equals(qName))
|
||||||
|
detailsBuilder.faultCode(ServiceFault.Details.FaultCode.fromValue(textToStringValue()));
|
||||||
else if ("httpCode".equals(qName))
|
else if ("httpCode".equals(qName))
|
||||||
builder.httpCode(textToIntValue());
|
detailsBuilder.httpCode(textToIntValue());
|
||||||
else if ("message".equals(qName))
|
else if ("message".equals(qName))
|
||||||
builder.message(textToStringValue());
|
detailsBuilder.message(textToStringValue());
|
||||||
else if ("requestId".equals(qName))
|
else if ("requestId".equals(qName))
|
||||||
builder.requestId(textToIntValue());
|
detailsBuilder.requestId(textToIntValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -45,8 +58,10 @@ public class ServiceFaultResponseHandler extends BaseProfitBricksResponseHandler
|
||||||
if (done)
|
if (done)
|
||||||
return;
|
return;
|
||||||
setPropertyOnEndTag(qName);
|
setPropertyOnEndTag(qName);
|
||||||
if ("detail".equals(qName))
|
if ("S:Fault".equals(qName))
|
||||||
done = true;
|
done = true;
|
||||||
|
if ("detail".equals(qName))
|
||||||
|
builder.details(detailsBuilder.build());
|
||||||
clearTextBuffer();
|
clearTextBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import static org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
import org.jclouds.http.functions.ParseSax;
|
import org.jclouds.http.functions.ParseSax;
|
||||||
import org.jclouds.profitbricks.domain.ServiceFault;
|
import org.jclouds.profitbricks.domain.ServiceFault;
|
||||||
|
import org.jclouds.profitbricks.domain.ServiceFault.Details;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
@Test(groups = "unit", testName = "ServiceFaultResponseHandlerTest")
|
@Test(groups = "unit", testName = "ServiceFaultResponseHandlerTest")
|
||||||
|
@ -37,11 +38,30 @@ public class ServiceFaultResponseHandlerTest extends BaseResponseHandlerTest<Ser
|
||||||
ServiceFault actual = parser.parse(payloadFromResource("/fault-404.xml"));
|
ServiceFault actual = parser.parse(payloadFromResource("/fault-404.xml"));
|
||||||
assertNotNull(actual, "Parsed content returned null");
|
assertNotNull(actual, "Parsed content returned null");
|
||||||
|
|
||||||
ServiceFault expected = ServiceFault.builder()
|
ServiceFault expected = ServiceFault
|
||||||
.faultCode(ServiceFault.FaultCode.RESOURCE_NOT_FOUND)
|
.builder()
|
||||||
|
.faultCode("S:Server")
|
||||||
|
.faultString(
|
||||||
|
"The requested resource could not be found. Please refer to Request Id : 16370720. [VDC-6-404] The requested resource does not exist or already deleted by the users. ResourceId random-non-existing-id")
|
||||||
|
.details(
|
||||||
|
Details
|
||||||
|
.builder()
|
||||||
|
.faultCode(ServiceFault.Details.FaultCode.RESOURCE_NOT_FOUND)
|
||||||
.httpCode(404)
|
.httpCode(404)
|
||||||
.message("The requested resource could not be found. Please refer to Request Id : 16370720. [VDC-6-404] The requested resource does not exist or already deleted by the users. ResourceId random-non-existing-id")
|
.message(
|
||||||
.requestId(16370720)
|
"The requested resource could not be found. Please refer to Request Id : 16370720. [VDC-6-404] The requested resource does not exist or already deleted by the users. ResourceId random-non-existing-id")
|
||||||
|
.requestId(16370720).build()).build();
|
||||||
|
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseSoapServiceFaultWithoutDetails() {
|
||||||
|
ParseSax<ServiceFault> parser = createParser();
|
||||||
|
ServiceFault actual = parser.parse(payloadFromResource("/fault-500.xml"));
|
||||||
|
assertNotNull(actual, "Parsed content returned null");
|
||||||
|
|
||||||
|
ServiceFault expected = ServiceFault.builder().faultCode("S:Server").faultString("javax.ejb.EJBException")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
|
||||||
|
<S:Body>
|
||||||
|
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
|
||||||
|
<faultcode>S:Server</faultcode>
|
||||||
|
<faultstring>javax.ejb.EJBException</faultstring>
|
||||||
|
</S:Fault>
|
||||||
|
</S:Body>
|
||||||
|
</S:Envelope>
|
Loading…
Reference in New Issue