Issue 412: added initial support for elastichosts

This commit is contained in:
Adrian Cole 2010-11-20 13:23:56 +01:00
parent e652f91aa7
commit f7fe6aedc9
14 changed files with 1106 additions and 0 deletions

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2010 Cloud Conscious, LLC <info@cloudconscious.com>
====================================================================
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.html
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.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-elastichosts</artifactId>
<name>jclouds ElasticHosts core</name>
<description>jclouds components to access ElasticHosts</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/elastichosts</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/elastichosts</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/elastichosts</url>
</scm>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
<repository>
<id>jclouds-googlecode-deploy</id>
<url>http://jclouds.googlecode.com/svn/repo</url>
</repository>
<repository>
<id>jclouds-rimu-snapshots-nexus</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<!-- when instances are hung, open a ticket and add here -->
<jclouds.compute.blacklist-nodes>trmkrun-ccc,test.trmk-924</jclouds.compute.blacklist-nodes>
<test.elastichosts.endpoint>https://api.cloudsigma.com</test.elastichosts.endpoint>
<test.elastichosts.apiversion>1.0</test.elastichosts.apiversion>
<test.elastichosts.identity>FIXME</test.elastichosts.identity>
<test.elastichosts.credential>FIXME</test.elastichosts.credential>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-log4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>test.elastichosts.endpoint</name>
<value>${test.elastichosts.endpoint}</value>
</property>
<property>
<name>test.elastichosts.apiversion</name>
<value>${test.elastichosts.apiversion}</value>
</property>
<property>
<name>test.elastichosts.identity</name>
<value>${test.elastichosts.identity}</value>
</property>
<property>
<name>test.elastichosts.credential</name>
<value>${test.elastichosts.credential}</value>
</property>
<property>
<name>jclouds.compute.blacklist-nodes</name>
<value>${jclouds.compute.blacklist-nodes}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,79 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.
* <p/>
*
* @see ElasticHostsClient
* @see <a href="TODO: insert URL of provider documentation" />
* @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<Set<String>> listDrives();
/**
* @see ElasticHostsClient#get(long)
*/
@GET
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/drives/{uuid}/info")
ListenableFuture<String> getDriveInfo(@PathParam("uuid") String uuid);
/**
* @see ElasticHostsClient#delete
*/
@DELETE
@Path("/drives/{uuid}")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteDrive(@PathParam("uuid") String uuid);
}

View File

@ -0,0 +1,51 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.
* <p/>
*
* @see ElasticHostsAsyncClient
* @see <a href="TODO: insert URL of ElasticHosts documentation" />
* @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<String> listDrives();
/**
* @return null, if not found
*/
String getDriveInfo(String uuid);
void deleteDrive(String uuid);
}

View File

@ -0,0 +1,45 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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<ElasticHostsClient, ElasticHostsAsyncClient> {
public ElasticHostsContextBuilder(Properties props) {
super(ElasticHostsClient.class, ElasticHostsAsyncClient.class, props);
}
protected void addClientModule(List<Module> modules) {
modules.add(new ElasticHostsRestClientModule());
}
}

View File

@ -0,0 +1,47 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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);
}
}

View File

@ -0,0 +1,59 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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<ElasticHostsClient, ElasticHostsAsyncClient> {
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
}
}

View File

@ -0,0 +1,103 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.
*
* <p/>
* 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);
}
}
}
}

View File

@ -0,0 +1,51 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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<HttpResponse, Set<String>> {
private final ReturnStringIf2xx returnStringIf200;
@Inject
NewlineDelimitedStringHandler(ReturnStringIf2xx returnStringIf200) {
this.returnStringIf200 = returnStringIf200;
}
@Override
public Set<String> apply(HttpResponse response) {
return Sets.newTreeSet(Splitter.on('\n').split(returnStringIf200.apply(response)));
}
}

View File

@ -0,0 +1,130 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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<ElasticHostsAsyncClient> {
public void testListDrives() throws SecurityException, NoSuchMethodException, IOException {
Method method = ElasticHostsAsyncClient.class.getMethod("listDrives");
GeneratedHttpRequest<ElasticHostsAsyncClient> 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<ElasticHostsAsyncClient> 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<ElasticHostsAsyncClient> 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<RestAnnotationProcessor<ElasticHostsAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<ElasticHostsAsyncClient>>() {
};
}
@Override
public RestContextSpec<ElasticHostsClient, ElasticHostsAsyncClient> createContextSpec() {
return contextSpec("elastichosts", "https://api.elastichosts.com", "1.0", "identity", "credential",
ElasticHostsClient.class, ElasticHostsAsyncClient.class);
}
}

View File

@ -0,0 +1,110 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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<ElasticHostsClient, ElasticHostsAsyncClient> 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.<Module> of(new Log4JLoggingModule())),
overrides);
connection = context.getApi();
}
@AfterGroups(groups = "live")
void tearDown() {
if (context != null)
context.close();
}
@Test
public void testListDrives() throws Exception {
Set<String> drives = connection.listDrives();
assertNotNull(drives);
}
@Test
public void testGetDrive() throws Exception {
Set<String> drives = connection.listDrives();
for (String driveUUID : drives) {
assertNotNull(connection.getDriveInfo(driveUUID));
}
}
}

View File

@ -0,0 +1,55 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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<HttpResponse, Set<String>> createParser() {
return Guice.createInjector().getInstance(NewlineDelimitedStringHandler.class);
}
public void test() {
InputStream is = NewlineDelimitedStringHandlerTest.class.getResourceAsStream("/uuids.txt");
Set<String> 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"));
}
}

View File

@ -0,0 +1,124 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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<? extends Exception> 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<? extends Exception> 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<? extends Exception> 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;
}
}

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
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.
====================================================================
-->
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--
For more configuration infromation and examples see the Apache Log4j
website: http://logging.apache.org/log4j/
-->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message${symbol_escape}n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message${symbol_escape}n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message${symbol_escape}n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
-->
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG" />
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category><!--
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
--><!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>

View File

@ -0,0 +1,3 @@
7e8ab721-81c9-4cb9-a651-4cafbfe1501c
ea6a8fdb-dab3-4d06-86c2-41a5835e6ed9
74744450-d338-4087-b3b8-59b505110a57