Issue 427: started on deltacloud

This commit is contained in:
Adrian Cole 2010-12-17 19:17:22 +01:00
parent c1f6eab2c4
commit 01eba379d8
18 changed files with 1145 additions and 0 deletions

View File

@ -66,6 +66,7 @@ import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.RestContextBuilder;
import org.xml.sax.Attributes;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
@ -88,6 +89,16 @@ import com.google.inject.spi.Message;
* @author Adrian Cole
*/
public class Utils {
public static Map<String, String> cleanseAttributes(Attributes in) {
Map<String, String> attrs = Maps.newLinkedHashMap();
for (int i = 0; i < in.getLength(); i++) {
String name = in.getQName(i);
if (name.indexOf(':') != -1)
name = name.substring(name.indexOf(':') + 1);
attrs.put(name, in.getValue(i));
}
return attrs;
}
/**
* If the supplied map contains the key {@code k1}, its value will be assigned to the key

View File

@ -92,6 +92,9 @@ bluelock-vcdirector.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloud
gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder
gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder
deltacloud.propertiesbuilder=org.jclouds.deltacloud.DeltacloudPropertiesBuilder
deltacloud.contextbuilder=org.jclouds.deltacloud.DeltacloudContextBuilder
elasticstack.propertiesbuilder=org.jclouds.elasticstack.ElasticStackPropertiesBuilder
elasticstack.contextbuilder=org.jclouds.elasticstack.ElasticStackContextBuilder

133
sandbox/deltacloud/pom.xml Normal file
View File

@ -0,0 +1,133 @@
<?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-deltacloud</artifactId>
<name>jclouds deltacloud core</name>
<description>jclouds components to access deltacloud</description>
<!-- 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.deltacloud.endpoint>http://localhost:3001/api</test.deltacloud.endpoint>
<test.deltacloud.apiversion>1.0</test.deltacloud.apiversion>
<test.deltacloud.identity>FIXME</test.deltacloud.identity>
<test.deltacloud.credential>FIXME</test.deltacloud.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.deltacloud.endpoint</name>
<value>${test.deltacloud.endpoint}</value>
</property>
<property>
<name>test.deltacloud.apiversion</name>
<value>${test.deltacloud.apiversion}</value>
</property>
<property>
<name>test.deltacloud.identity</name>
<value>${test.deltacloud.identity}</value>
</property>
<property>
<name>test.deltacloud.credential</name>
<value>${test.deltacloud.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,69 @@
/**
*
* 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.deltacloud;
import java.net.URI;
import java.util.Map;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import org.jclouds.deltacloud.options.CreateInstanceOptions;
import org.jclouds.deltacloud.reference.DeltacloudCollection;
import org.jclouds.deltacloud.xml.LinksHandler;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to deltacloud via their REST API.
* <p/>
*
* @see DeltacloudClient
* @see <a href="TODO: insert URL of provider documentation" />
* @author Adrian Cole
*/
@RequestFilters(BasicAuthentication.class)
@Consumes(MediaType.APPLICATION_XML)
public interface DeltacloudAsyncClient {
/**
* @see DeltacloudClient#getCollections
*/
@GET
@Path("")
@XMLResponseParser(LinksHandler.class)
ListenableFuture<Map<DeltacloudCollection, URI>> getCollections();
/**
* @see DeltacloudClient#createInstance
*/
@POST
@Path("")
ListenableFuture<String> createInstance(URI instanceCollection, @FormParam("image_id") String imageId,
CreateInstanceOptions... options);
}

View File

@ -0,0 +1,66 @@
/**
*
* 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.deltacloud;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.deltacloud.options.CreateInstanceOptions;
import org.jclouds.deltacloud.reference.DeltacloudCollection;
/**
* Provides synchronous access to deltacloud.
* <p/>
*
* @see DeltacloudAsyncClient
* @see <a href="TODO: insert URL of deltacloud documentation" />
* @author Adrian Cole
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface DeltacloudClient {
/**
* The result of this entry-point is a set of entry-points into other collections, such as
* images, instances, hardware profiles and realms, among others.
*
* @return named links to available collections, or empty map, if no resources are found
*/
Map<DeltacloudCollection, URI> getCollections();
/**
* Create a new Instance
*
* <h4>Note</h4>
*
* If options realmId or hardwareProfileName are not specified, the provider must select
* reasonable defaults. The architecture of the selected hardware profile must match the
* architecture of the specified image.
*
* @param instanceCollection
* which endpoint to create the instance in
* @param imageId
* The identifier (not URL) of the image from which to base the instance
* @param options
* includes realm, hardware profile, etc.
* @return newly-created instance including a URL to retrieve the instance in the future.
*/
String createInstance(URI instanceCollection, String imageId, CreateInstanceOptions... options);
}

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.deltacloud;
import java.util.List;
import java.util.Properties;
import org.jclouds.deltacloud.config.DeltacloudRestClientModule;
import org.jclouds.rest.RestContextBuilder;
import com.google.inject.Module;
/**
*
* @author Adrian Cole
*/
public class DeltacloudContextBuilder extends
RestContextBuilder<DeltacloudClient, DeltacloudAsyncClient> {
public DeltacloudContextBuilder(Properties props) {
super(DeltacloudClient.class, DeltacloudAsyncClient.class, props);
}
protected void addClientModule(List<Module> modules) {
modules.add(new DeltacloudRestClientModule());
}
}

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.deltacloud;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
/**
* Builds properties used in deltacloud Clients
*
* @author Adrian Cole
*/
public class DeltacloudPropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_API_VERSION, "1.0");
return properties;
}
public DeltacloudPropertiesBuilder(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.deltacloud.config;
import org.jclouds.deltacloud.DeltacloudAsyncClient;
import org.jclouds.deltacloud.DeltacloudClient;
import org.jclouds.deltacloud.handlers.DeltacloudErrorHandler;
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 deltacloud connection.
*
* @author Adrian Cole
*/
@RequiresHttp
@ConfiguresRestClient
public class DeltacloudRestClientModule extends RestClientModule<DeltacloudClient, DeltacloudAsyncClient> {
public DeltacloudRestClientModule() {
super(DeltacloudClient.class, DeltacloudAsyncClient.class);
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(DeltacloudErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(DeltacloudErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(DeltacloudErrorHandler.class);
}
@Override
protected void bindRetryHandlers() {
// TODO
}
}

View File

@ -0,0 +1,98 @@
/**
*
* 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.deltacloud.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;
/**
*
* @author Adrian Cole
*
*/
@Singleton
public class DeltacloudErrorHandler 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,50 @@
package org.jclouds.deltacloud.options;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Contains options supported in the Deltacloud API for the Create Instance operation. <h2>
* Usage</h2> The recommended way to instantiate a CreateInstanceOptions object is to statically
* import CreateInstanceOptions.Builder.* and invoke a static creation method followed by an
* instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.deltacloud.options.CreateInstanceOptions.Builder.*
* <p/>
* DeltacloudClient connection = // get connection
* ListenableFuture<Instance> instance = client.createInstance(collection, "imageId", named("robot"));
* <code>
*
* @author Adrian Cole
* @see <a href="http://deltacloud.org/api.html#h1" />
*/
public class CreateInstanceOptions extends BaseHttpRequestOptions {
public static final CreateInstanceOptions NONE = new CreateInstanceOptions();
/**
* A short label to identify the instance.
*
*/
public CreateInstanceOptions named(String name) {
formParameters.put("name", checkNotNull(name, "name"));
return this;
}
public String getName() {
return this.getFirstFormOrNull("name");
}
public static class Builder {
/**
* @see CreateInstanceOptions#named
*/
public static CreateInstanceOptions named(String name) {
CreateInstanceOptions options = new CreateInstanceOptions();
return options.named(name);
}
}
}

View File

@ -0,0 +1,30 @@
package org.jclouds.deltacloud.reference;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.CaseFormat;
/**
*
* @author Adrian Cole
*/
public enum DeltacloudCollection {
HARDWARE_PROFILES, INSTANCE_STATES, REALMS, IMAGES, INSTANCES, UNRECOGNIZED;
public String value() {
return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_UNDERSCORE, name()));
}
@Override
public String toString() {
return value();
}
public static DeltacloudCollection fromValue(String link) {
try {
return valueOf(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(link, "link")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

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.links/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.deltacloud.xml;
import java.net.URI;
import java.util.Map;
import org.jclouds.deltacloud.reference.DeltacloudCollection;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.util.Utils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import com.google.common.collect.Maps;
/**
* @author Adrian Cole
*/
public class LinksHandler extends ParseSax.HandlerWithResult<Map<DeltacloudCollection, URI>> {
private Map<DeltacloudCollection, URI> links = Maps.newLinkedHashMap();
public Map<DeltacloudCollection, URI> getResult() {
return links;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
Map<String, String> attributes = Utils.cleanseAttributes(attrs);
if (qName.equals("link")) {
String rel = attributes.get("rel");
if (rel != null) {
DeltacloudCollection link = DeltacloudCollection.fromValue(rel);
links.put(link, URI.create(attributes.get("href")));
}
}
}
}

View File

@ -0,0 +1,132 @@
/**
*
* 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.deltacloud;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Properties;
import org.jclouds.deltacloud.options.CreateInstanceOptions;
import org.jclouds.deltacloud.xml.LinksHandler;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.rest.RestContextSpec;
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 DeltacloudAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "deltacloud.DeltacloudAsyncClientTest")
public class DeltacloudAsyncClientTest extends RestClientTest<DeltacloudAsyncClient> {
public void testGetCollections() throws SecurityException, NoSuchMethodException, IOException {
Method method = DeltacloudAsyncClient.class.getMethod("getCollections");
GeneratedHttpRequest<DeltacloudAsyncClient> httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest, "GET http://localhost:3001/api HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/xml\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 http://localhost:3001/api HTTP/1.1");
// for example, using basic authentication, we should get "only one"
// header
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/xml\nAuthorization: Basic Zm9vOmJhcg==\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseSax.class);
assertSaxResponseParserClassEquals(method, LinksHandler.class);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testCreateInstance() throws SecurityException, NoSuchMethodException, IOException {
Method method = DeltacloudAsyncClient.class.getMethod("createInstance", URI.class, String.class,
CreateInstanceOptions[].class);
GeneratedHttpRequest<DeltacloudAsyncClient> httpRequest = processor.createRequest(method,
URI.create("http://localhost:3001/api/instances"), "imageId-1");
assertRequestLineEquals(httpRequest, "POST http://localhost:3001/api HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/xml\n");
assertPayloadEquals(httpRequest, "image_id=imageId-1", "application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, httpRequest, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testCreateInstanceWithOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = DeltacloudAsyncClient.class.getMethod("createInstance", URI.class, String.class,
CreateInstanceOptions[].class);
GeneratedHttpRequest<DeltacloudAsyncClient> httpRequest = processor.createRequest(method,
URI.create("http://localhost:3001/api/instances"), "imageId-1", CreateInstanceOptions.Builder.named("foo"));
assertRequestLineEquals(httpRequest, "POST http://localhost:3001/api HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/xml\n");
assertPayloadEquals(httpRequest, "image_id=imageId-1&name=foo", "application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, httpRequest, ReturnStringIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
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<DeltacloudAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<DeltacloudAsyncClient>>() {
};
}
@Override
public RestContextSpec<DeltacloudClient, DeltacloudAsyncClient> createContextSpec() {
Properties props = new Properties();
props.setProperty("deltacloud.endpoint", "http://localhost:3001/api");
return new RestContextFactory().createContextSpec("deltacloud", "foo", "bar", props);
}
}

View File

@ -0,0 +1,113 @@
/**
*
* 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.deltacloud;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertNotNull;
import java.net.URI;
import java.util.Map;
import java.util.Properties;
import org.jclouds.Constants;
import org.jclouds.deltacloud.reference.DeltacloudCollection;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory;
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 DeltacloudClient}
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true)
public class DeltacloudClientLiveTest {
protected DeltacloudClient client;
protected RestContext<DeltacloudClient, DeltacloudAsyncClient> context;
protected String provider = "deltacloud";
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 = new RestContextFactory().createContext(provider, ImmutableSet.<Module> of(new Log4JLoggingModule()),
overrides);
client = context.getApi();
}
@AfterGroups(groups = "live")
void tearDown() {
if (context != null)
context.close();
}
@Test
public void testGetLinksContainsAll() throws Exception {
Map<DeltacloudCollection, URI> links = client.getCollections();
assertNotNull(links);
for (DeltacloudCollection link : DeltacloudCollection.values())
assert (links.get(link) != null) : link;
}
@Test
public void testCreateInstance() throws Exception {
// TODO
}
@Test
public void testCreateInstanceWithOptions() throws Exception {
// TODO
}
}

View File

@ -0,0 +1,123 @@
/**
*
* 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.deltacloud.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 DeltacloudErrorHandlerTest {
@Test
public void test400MakesIllegalArgumentException() {
assertCodeMakes("GET", URI.create("https://deltacloud.com/foo"), 400, "", "Bad Request",
IllegalArgumentException.class);
}
@Test
public void test401MakesAuthorizationException() {
assertCodeMakes("GET", URI.create("https://deltacloud.com/foo"), 401, "", "Unauthorized",
AuthorizationException.class);
}
@Test
public void test404MakesResourceNotFoundException() {
assertCodeMakes("GET", URI.create("https://deltacloud.com/foo"), 404, "", "Not Found",
ResourceNotFoundException.class);
}
@Test
public void test405MakesIllegalArgumentException() {
assertCodeMakes("GET", URI.create("https://deltacloud.com/foo"), 405, "", "Method Not Allowed",
IllegalArgumentException.class);
}
@Test
public void test409MakesIllegalStateException() {
assertCodeMakes("GET", URI.create("https://deltacloud.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) {
DeltacloudErrorHandler function = Guice.createInjector().getInstance(DeltacloudErrorHandler.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,58 @@
/**
*
* 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.deltacloud.handlers;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.net.URI;
import java.util.Map;
import org.jclouds.deltacloud.reference.DeltacloudCollection;
import org.jclouds.deltacloud.xml.LinksHandler;
import org.jclouds.http.functions.BaseHandlerTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/**
* Tests behavior of {@code LinksHandler}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class LinksHandlerTest extends BaseHandlerTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/links.xml");
Map<DeltacloudCollection, URI> result = factory.create(injector.getInstance(LinksHandler.class)).parse(is);
assertEquals(result, ImmutableMap.of(//
DeltacloudCollection.HARDWARE_PROFILES, URI.create("http://fancycloudprovider.com/api/hardware_profiles"),//
DeltacloudCollection.INSTANCE_STATES, URI.create("http://fancycloudprovider.com/api/instance_states"),//
DeltacloudCollection.REALMS, URI.create("http://fancycloudprovider.com/api/realms"),//
DeltacloudCollection.IMAGES, URI.create("http://fancycloudprovider.com/api/images"),//
DeltacloudCollection.INSTANCES, URI.create("http://fancycloudprovider.com/api/instances")
));
}
}

View File

@ -0,0 +1,48 @@
package org.jclouds.deltacloud.options;
import static org.jclouds.deltacloud.options.CreateInstanceOptions.Builder.named;
import static org.testng.Assert.assertEquals;
import java.util.Collections;
import org.jclouds.http.options.HttpRequestOptions;
import org.testng.annotations.Test;
/**
* Tests possible uses of CreateInstanceOptions and CreateInstanceOptions.Builder.*
*
* @author Adrian Cole
*/
public class CreateInstanceOptionsTest {
@Test
public void testAssignability() {
assert HttpRequestOptions.class.isAssignableFrom(CreateInstanceOptions.class);
assert !String.class.isAssignableFrom(CreateInstanceOptions.class);
}
@Test
public void testWithNamed() {
CreateInstanceOptions options = new CreateInstanceOptions();
options.named("test");
assertEquals(options.buildFormParameters().get("name"), Collections.singletonList("test"));
}
@Test
public void testNullWithNamed() {
CreateInstanceOptions options = new CreateInstanceOptions();
assertEquals(options.buildFormParameters().get("name"), Collections.EMPTY_LIST);
}
@Test
public void testWithNamedStatic() {
CreateInstanceOptions options = named("test");
assertEquals(options.buildFormParameters().get("name"), Collections.singletonList("test"));
}
@Test(expectedExceptions = NullPointerException.class)
public void testWithNamedNPE() {
named(null);
}
}

View File

@ -0,0 +1,7 @@
<api driver='ec2' version='1.0'>
<link href='http://fancycloudprovider.com/api/hardware_profiles' rel='hardware_profiles' />
<link href='http://fancycloudprovider.com/api/instance_states' rel='instance_states' />
<link href='http://fancycloudprovider.com/api/realms' rel='realms' />
<link href='http://fancycloudprovider.com/api/images' rel='images' />
<link href='http://fancycloudprovider.com/api/instances' rel='instances' />
</api>