From f7fe6aedc9bad47d800d94ddba75d1c76f372691 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sat, 20 Nov 2010 13:23:56 +0100 Subject: [PATCH] Issue 412: added initial support for elastichosts --- sandbox/elastichosts/pom.xml | 139 ++++++++++++++++++ .../elastichosts/ElasticHostsAsyncClient.java | 79 ++++++++++ .../elastichosts/ElasticHostsClient.java | 51 +++++++ .../ElasticHostsContextBuilder.java | 45 ++++++ .../ElasticHostsPropertiesBuilder.java | 47 ++++++ .../config/ElasticHostsRestClientModule.java | 59 ++++++++ .../handlers/ElasticHostsErrorHandler.java | 103 +++++++++++++ .../NewlineDelimitedStringHandler.java | 51 +++++++ .../ElasticHostsAsyncClientTest.java | 130 ++++++++++++++++ .../ElasticHostsClientLiveTest.java | 110 ++++++++++++++ .../NewlineDelimitedStringHandlerTest.java | 55 +++++++ .../ElasticHostsErrorHandlerTest.java | 124 ++++++++++++++++ .../elastichosts/src/test/resources/log4j.xml | 110 ++++++++++++++ .../elastichosts/src/test/resources/uuids.txt | 3 + 14 files changed, 1106 insertions(+) create mode 100644 sandbox/elastichosts/pom.xml create mode 100644 sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsAsyncClient.java create mode 100644 sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsClient.java create mode 100644 sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsContextBuilder.java create mode 100644 sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsPropertiesBuilder.java create mode 100644 sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/config/ElasticHostsRestClientModule.java create mode 100644 sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/handlers/ElasticHostsErrorHandler.java create mode 100644 sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/handlers/NewlineDelimitedStringHandler.java create mode 100644 sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/ElasticHostsAsyncClientTest.java create mode 100644 sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/ElasticHostsClientLiveTest.java create mode 100644 sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/NewlineDelimitedStringHandlerTest.java create mode 100644 sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/handlers/ElasticHostsErrorHandlerTest.java create mode 100644 sandbox/elastichosts/src/test/resources/log4j.xml create mode 100644 sandbox/elastichosts/src/test/resources/uuids.txt diff --git a/sandbox/elastichosts/pom.xml b/sandbox/elastichosts/pom.xml new file mode 100644 index 0000000000..cda61b4f8a --- /dev/null +++ b/sandbox/elastichosts/pom.xml @@ -0,0 +1,139 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.0-SNAPSHOT + ../project/pom.xml + + org.jclouds + jclouds-elastichosts + jclouds ElasticHosts core + jclouds components to access ElasticHosts + + + scm:svn:http://jclouds.googlecode.com/svn/trunk/elastichosts + scm:svn:https://jclouds.googlecode.com/svn/trunk/elastichosts + http://jclouds.googlecode.com/svn/trunk/elastichosts + + + + + + jclouds-googlecode-deploy + http://jclouds.googlecode.com/svn/repo + + + jclouds-rimu-snapshots-nexus + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + + + + trmkrun-ccc,test.trmk-924 + https://api.cloudsigma.com + 1.0 + FIXME + FIXME + + + + ${project.groupId} + jclouds-core + ${project.version} + + + ${project.groupId} + jclouds-core + ${project.version} + test-jar + test + + + log4j + log4j + 1.2.14 + test + + + ${project.groupId} + jclouds-log4j + ${project.version} + test + + + + + live + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration + integration-test + + test + + + + + test.elastichosts.endpoint + ${test.elastichosts.endpoint} + + + test.elastichosts.apiversion + ${test.elastichosts.apiversion} + + + test.elastichosts.identity + ${test.elastichosts.identity} + + + test.elastichosts.credential + ${test.elastichosts.credential} + + + jclouds.compute.blacklist-nodes + ${jclouds.compute.blacklist-nodes} + + + + + + + + + + + diff --git a/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsAsyncClient.java b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsAsyncClient.java new file mode 100644 index 0000000000..9c73974ad8 --- /dev/null +++ b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsAsyncClient.java @@ -0,0 +1,79 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.elastichosts.handlers.NewlineDelimitedStringHandler; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to ElasticHosts via their REST API. + *

+ * + * @see ElasticHostsClient + * @see + * @author Adrian Cole + */ +@RequestFilters(BasicAuthentication.class) +@Consumes(MediaType.TEXT_PLAIN) +public interface ElasticHostsAsyncClient { + /* + * TODO: define interface methods for ElasticHosts + */ + + /** + * @see ElasticHostsClient#listDrives() + */ + @GET + @Path("/drives/list") + @ResponseParser(NewlineDelimitedStringHandler.class) + ListenableFuture> listDrives(); + + /** + * @see ElasticHostsClient#get(long) + */ + @GET + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @Path("/drives/{uuid}/info") + ListenableFuture getDriveInfo(@PathParam("uuid") String uuid); + + /** + * @see ElasticHostsClient#delete + */ + @DELETE + @Path("/drives/{uuid}") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture deleteDrive(@PathParam("uuid") String uuid); +} diff --git a/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsClient.java b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsClient.java new file mode 100644 index 0000000000..bb691e5317 --- /dev/null +++ b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsClient.java @@ -0,0 +1,51 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; + +/** + * Provides synchronous access to ElasticHosts. + *

+ * + * @see ElasticHostsAsyncClient + * @see + * @author Adrian Cole + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface ElasticHostsClient { + /** + * list of drive uuids + * + * @return or empty set if no drives are found + */ + Set listDrives(); + + /** + * @return null, if not found + */ + String getDriveInfo(String uuid); + + void deleteDrive(String uuid); + +} diff --git a/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsContextBuilder.java b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsContextBuilder.java new file mode 100644 index 0000000000..8090e5ad5a --- /dev/null +++ b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsContextBuilder.java @@ -0,0 +1,45 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts; + +import java.util.List; +import java.util.Properties; + +import org.jclouds.elastichosts.config.ElasticHostsRestClientModule; +import org.jclouds.rest.RestContextBuilder; + +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class ElasticHostsContextBuilder extends + RestContextBuilder { + + public ElasticHostsContextBuilder(Properties props) { + super(ElasticHostsClient.class, ElasticHostsAsyncClient.class, props); + } + + protected void addClientModule(List modules) { + modules.add(new ElasticHostsRestClientModule()); + } + +} diff --git a/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsPropertiesBuilder.java b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsPropertiesBuilder.java new file mode 100644 index 0000000000..ead9d89ef3 --- /dev/null +++ b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/ElasticHostsPropertiesBuilder.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts; + +import static org.jclouds.Constants.PROPERTY_API_VERSION; +import static org.jclouds.Constants.PROPERTY_ENDPOINT; + +import java.util.Properties; + +import org.jclouds.PropertiesBuilder; + +/** + * Builds properties used in ElasticHosts Clients + * + * @author Adrian Cole + */ +public class ElasticHostsPropertiesBuilder extends PropertiesBuilder { + @Override + protected Properties defaultProperties() { + Properties properties = super.defaultProperties(); + properties.setProperty(PROPERTY_ENDPOINT, "https://api.elastichosts.com"); + properties.setProperty(PROPERTY_API_VERSION, "1.0"); + return properties; + } + + public ElasticHostsPropertiesBuilder(Properties properties) { + super(properties); + } + +} diff --git a/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/config/ElasticHostsRestClientModule.java b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/config/ElasticHostsRestClientModule.java new file mode 100644 index 0000000000..e5f91ad7d1 --- /dev/null +++ b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/config/ElasticHostsRestClientModule.java @@ -0,0 +1,59 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts.config; + +import org.jclouds.elastichosts.ElasticHostsAsyncClient; +import org.jclouds.elastichosts.ElasticHostsClient; +import org.jclouds.elastichosts.handlers.ElasticHostsErrorHandler; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.annotation.Redirection; +import org.jclouds.http.annotation.ServerError; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; + +/** + * Configures the ElasticHosts connection. + * + * @author Adrian Cole + */ +@RequiresHttp +@ConfiguresRestClient +public class ElasticHostsRestClientModule extends + RestClientModule { + + public ElasticHostsRestClientModule() { + super(ElasticHostsClient.class, ElasticHostsAsyncClient.class); + } + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ElasticHostsErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ElasticHostsErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ElasticHostsErrorHandler.class); + } + + @Override + protected void bindRetryHandlers() { + // TODO + } + +} diff --git a/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/handlers/ElasticHostsErrorHandler.java b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/handlers/ElasticHostsErrorHandler.java new file mode 100644 index 0000000000..a8c59baae4 --- /dev/null +++ b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/handlers/ElasticHostsErrorHandler.java @@ -0,0 +1,103 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts.handlers; + +import java.io.IOException; + +import javax.annotation.Resource; +import javax.inject.Singleton; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.logging.Logger; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Utils; + +import com.google.common.base.Throwables; +import com.google.common.io.Closeables; + +/** + * This will parse and set an appropriate exception on the command object. + * + *

+ * Errors are returned with an appropriate HTTP status code, an X-Elastic- Error header specifying + * the error type, and a text description in the HTTP body. + * + * @author Adrian Cole + * + */ +@Singleton +public class ElasticHostsErrorHandler implements HttpErrorHandler { + @Resource + protected Logger logger = Logger.NULL; + + public void handleError(HttpCommand command, HttpResponse response) { + // it is important to always read fully and close streams + String message = parseMessage(response); + Exception exception = message != null ? new HttpResponseException(command, response, message) + : new HttpResponseException(command, response); + try { + message = message != null ? message : String.format("%s -> %s", command.getRequest().getRequestLine(), + response.getStatusLine()); + switch (response.getStatusCode()) { + case 400: + exception = new IllegalArgumentException(message, exception); + break; + case 401: + exception = new AuthorizationException(message, exception); + break; + case 404: + if (!command.getRequest().getMethod().equals("DELETE")) { + exception = new ResourceNotFoundException(message, exception); + } + break; + case 405: + exception = new IllegalArgumentException(message, exception); + break; + case 409: + exception = new IllegalStateException(message, exception); + break; + } + } finally { + if (response.getPayload() != null) + Closeables.closeQuietly(response.getPayload().getInput()); + command.setException(exception); + } + } + + public String parseMessage(HttpResponse response) { + if (response.getPayload() == null) + return null; + try { + return Utils.toStringAndClose(response.getPayload().getInput()); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + response.getPayload().getInput().close(); + } catch (IOException e) { + Throwables.propagate(e); + } + } + } +} diff --git a/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/handlers/NewlineDelimitedStringHandler.java b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/handlers/NewlineDelimitedStringHandler.java new file mode 100644 index 0000000000..c970c4b873 --- /dev/null +++ b/sandbox/elastichosts/src/main/java/org/jclouds/elastichosts/handlers/NewlineDelimitedStringHandler.java @@ -0,0 +1,51 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts.handlers; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ReturnStringIf2xx; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.collect.Sets; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class NewlineDelimitedStringHandler implements Function> { + private final ReturnStringIf2xx returnStringIf200; + + @Inject + NewlineDelimitedStringHandler(ReturnStringIf2xx returnStringIf200) { + this.returnStringIf200 = returnStringIf200; + } + + @Override + public Set apply(HttpResponse response) { + return Sets.newTreeSet(Splitter.on('\n').split(returnStringIf200.apply(response))); + } +} \ No newline at end of file diff --git a/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/ElasticHostsAsyncClientTest.java b/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/ElasticHostsAsyncClientTest.java new file mode 100644 index 0000000000..d32444ed0d --- /dev/null +++ b/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/ElasticHostsAsyncClientTest.java @@ -0,0 +1,130 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts; + +import static org.jclouds.rest.RestContextFactory.contextSpec; +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.lang.reflect.Method; + +import org.jclouds.elastichosts.handlers.NewlineDelimitedStringHandler; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.http.functions.ReleasePayloadAndReturn; +import org.jclouds.http.functions.ReturnStringIf2xx; +import org.jclouds.rest.RestClientTest; +import org.jclouds.rest.RestContextSpec; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; +import com.google.inject.TypeLiteral; + +/** + * Tests annotation parsing of {@code ElasticHostsAsyncClient} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "elastichosts.ElasticHostsAsyncClientTest") +public class ElasticHostsAsyncClientTest extends RestClientTest { + + public void testListDrives() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticHostsAsyncClient.class.getMethod("listDrives"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.elastichosts.com/drives/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // now make sure request filters apply by replaying + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + + assertRequestLineEquals(httpRequest, "GET https://api.elastichosts.com/drives/list HTTP/1.1"); + // for example, using basic authentication, we should get "only one" + // header + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\nAuthorization: Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // TODO: insert expected response class, which probably extends ParseJson + assertResponseParserClassEquals(method, httpRequest, NewlineDelimitedStringHandler.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + + } + + public void testGetDriveInfo() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticHostsAsyncClient.class.getMethod("getDriveInfo", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "GET https://api.elastichosts.com/drives/uuid/info HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // TODO: insert expected response class, which probably extends ParseJson + assertResponseParserClassEquals(method, httpRequest, ReturnStringIf2xx.class); + assertSaxResponseParserClassEquals(method, null); + // note that get methods should convert 404's to null + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testDeleteDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticHostsAsyncClient.class.getMethod("deleteDrive", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "DELETE https://api.elastichosts.com/drives/uuid HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + @Override + protected void checkFilters(HttpRequest request) { + assertEquals(request.getFilters().size(), 1); + assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class); + } + + @Override + protected TypeLiteral> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @Override + public RestContextSpec createContextSpec() { + return contextSpec("elastichosts", "https://api.elastichosts.com", "1.0", "identity", "credential", + ElasticHostsClient.class, ElasticHostsAsyncClient.class); + } +} diff --git a/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/ElasticHostsClientLiveTest.java b/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/ElasticHostsClientLiveTest.java new file mode 100644 index 0000000000..1a6eaf3250 --- /dev/null +++ b/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/ElasticHostsClientLiveTest.java @@ -0,0 +1,110 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.rest.RestContextFactory.contextSpec; +import static org.jclouds.rest.RestContextFactory.createContext; +import static org.testng.Assert.assertNotNull; + +import java.util.Properties; +import java.util.Set; + +import org.jclouds.Constants; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.rest.RestContext; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; + +/** + * Tests behavior of {@code ElasticHostsClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "elastichosts.ElasticHostsClientLiveTest") +public class ElasticHostsClientLiveTest { + + private ElasticHostsClient connection; + private RestContext context; + + protected String provider = "elastichosts"; + protected String identity; + protected String credential; + protected String endpoint; + protected String apiversion; + + protected void setupCredentials() { + identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); + credential = System.getProperty("test." + provider + ".credential"); + endpoint = System.getProperty("test." + provider + ".endpoint"); + apiversion = System.getProperty("test." + provider + ".apiversion"); + } + + protected Properties setupProperties() { + Properties overrides = new Properties(); + overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); + overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true"); + overrides.setProperty(provider + ".identity", identity); + if (credential != null) + overrides.setProperty(provider + ".credential", credential); + if (endpoint != null) + overrides.setProperty(provider + ".endpoint", endpoint); + if (apiversion != null) + overrides.setProperty(provider + ".apiversion", apiversion); + return overrides; + } + + @BeforeGroups(groups = { "live" }) + public void setupClient() { + setupCredentials(); + Properties overrides = setupProperties(); + context = createContext( + contextSpec(provider, endpoint, "1.0", identity, credential, ElasticHostsClient.class, + ElasticHostsAsyncClient.class, (Class) ElasticHostsPropertiesBuilder.class, + (Class) ElasticHostsContextBuilder.class, ImmutableSet. of(new Log4JLoggingModule())), + overrides); + + connection = context.getApi(); + } + + @AfterGroups(groups = "live") + void tearDown() { + if (context != null) + context.close(); + } + + @Test + public void testListDrives() throws Exception { + Set drives = connection.listDrives(); + assertNotNull(drives); + } + + @Test + public void testGetDrive() throws Exception { + Set drives = connection.listDrives(); + for (String driveUUID : drives) { + assertNotNull(connection.getDriveInfo(driveUUID)); + } + } +} diff --git a/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/NewlineDelimitedStringHandlerTest.java b/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/NewlineDelimitedStringHandlerTest.java new file mode 100644 index 0000000000..01cf8a311b --- /dev/null +++ b/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/NewlineDelimitedStringHandlerTest.java @@ -0,0 +1,55 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.util.Set; + +import org.jclouds.elastichosts.handlers.NewlineDelimitedStringHandler; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; +import com.google.inject.Guice; + +/** + * Tests behavior of {@code NewlineDelimitedStringHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class NewlineDelimitedStringHandlerTest { + + static Function> createParser() { + return Guice.createInjector().getInstance(NewlineDelimitedStringHandler.class); + } + + public void test() { + InputStream is = NewlineDelimitedStringHandlerTest.class.getResourceAsStream("/uuids.txt"); + Set list = createParser().apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + assertEquals(list, ImmutableSortedSet.of("7e8ab721-81c9-4cb9-a651-4cafbfe1501c", + "ea6a8fdb-dab3-4d06-86c2-41a5835e6ed9", "74744450-d338-4087-b3b8-59b505110a57")); + } + +} diff --git a/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/handlers/ElasticHostsErrorHandlerTest.java b/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/handlers/ElasticHostsErrorHandlerTest.java new file mode 100644 index 0000000000..d0fa1c2c03 --- /dev/null +++ b/sandbox/elastichosts/src/test/java/org/jclouds/elastichosts/handlers/ElasticHostsErrorHandlerTest.java @@ -0,0 +1,124 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.jclouds.elastichosts.handlers; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; + +import java.net.URI; + +import org.easymock.IArgumentMatcher; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ElasticHostsErrorHandlerTest { + + @Test + public void test400MakesIllegalArgumentException() { + assertCodeMakes("GET", URI.create("https://elastichosts.com/foo"), 400, "", "Bad Request", + IllegalArgumentException.class); + } + + @Test + public void test401MakesAuthorizationException() { + assertCodeMakes("GET", URI.create("https://elastichosts.com/foo"), 401, "", "Unauthorized", + AuthorizationException.class); + } + + @Test + public void test404MakesResourceNotFoundException() { + assertCodeMakes("GET", URI.create("https://elastichosts.com/foo"), 404, "", "Not Found", + ResourceNotFoundException.class); + } + + @Test + public void test405MakesIllegalArgumentException() { + assertCodeMakes("GET", URI.create("https://elastichosts.com/foo"), 405, "", "Method Not Allowed", + IllegalArgumentException.class); + } + + @Test + public void test409MakesIllegalStateException() { + assertCodeMakes("GET", URI.create("https://elastichosts.com/foo"), 409, "", "Conflict", + IllegalStateException.class); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content, + Class expected) { + assertCodeMakes(method, uri, statusCode, message, "text/xml", content, expected); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType, + String content, Class expected) { + + ElasticHostsErrorHandler function = Guice.createInjector().getInstance(ElasticHostsErrorHandler.class); + + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = new HttpRequest(method, uri); + HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Utils + .toInputStream(content))); + response.getPayload().getContentMetadata().setContentType(contentType); + + expect(command.getRequest()).andReturn(request).atLeastOnce(); + command.setException(classEq(expected)); + + replay(command); + + function.handleError(command, response); + + verify(command); + } + + public static Exception classEq(final Class in) { + reportMatcher(new IArgumentMatcher() { + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("classEq("); + buffer.append(in); + buffer.append(")"); + } + + @Override + public boolean matches(Object arg) { + return arg.getClass() == in; + } + + }); + return null; + } + +} \ No newline at end of file diff --git a/sandbox/elastichosts/src/test/resources/log4j.xml b/sandbox/elastichosts/src/test/resources/log4j.xml new file mode 100644 index 0000000000..9e7c3bf976 --- /dev/null +++ b/sandbox/elastichosts/src/test/resources/log4j.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sandbox/elastichosts/src/test/resources/uuids.txt b/sandbox/elastichosts/src/test/resources/uuids.txt new file mode 100644 index 0000000000..b54f833b87 --- /dev/null +++ b/sandbox/elastichosts/src/test/resources/uuids.txt @@ -0,0 +1,3 @@ +7e8ab721-81c9-4cb9-a651-4cafbfe1501c +ea6a8fdb-dab3-4d06-86c2-41a5835e6ed9 +74744450-d338-4087-b3b8-59b505110a57 \ No newline at end of file