Implement changes to Cloudstack template API suggested in review

This commit is contained in:
Richard Downer 2011-11-09 12:46:35 +02:00
parent 233cc822c0
commit 5791eaad8b
6 changed files with 218 additions and 29 deletions

View File

@ -0,0 +1,53 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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
*
* 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.cloudstack.binders;
import org.jclouds.cloudstack.domain.TemplateMetadata;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.core.UriBuilder;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Richard Downer
*/
public class BindTemplateMetadataToQueryParams implements Binder {
private final Provider<UriBuilder> uriBuilderProvider;
@Inject
public BindTemplateMetadataToQueryParams(Provider<UriBuilder> uriBuilderProvider) {
this.uriBuilderProvider = checkNotNull(uriBuilderProvider, "uriBuilderProvider");
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(input instanceof TemplateMetadata, "this binder is only valid for TemplateMetadata");
TemplateMetadata metadata = (TemplateMetadata) input;
request = ModifyRequest.addQueryParam(request, "name", metadata.getName(), uriBuilderProvider.get());
request = ModifyRequest.addQueryParam(request, "ostypeid", metadata.getOsTypeId(), uriBuilderProvider.get());
request = ModifyRequest.addQueryParam(request, "displaytext", metadata.getDisplayText(), uriBuilderProvider.get());
return request;
}
}

View File

@ -0,0 +1,133 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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
*
* 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.cloudstack.domain;
/**
* @author Richard Downer
*/
public class TemplateMetadata {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String name;
private long osTypeId;
private String displayText;
/**
* @param name the name of the template
*/
public Builder name(String name) {
this.name = name;
return this;
}
/**
* @param osTypeId the ID of the OS Type that best represents the OS of this template.
*/
public Builder osTypeId(long osTypeId) {
this.osTypeId = osTypeId;
return this;
}
/**
* @param displayText the display text of the template. This is usually used for display purposes.
*/
public Builder displayText(String displayText) {
this.displayText = displayText;
return this;
}
public TemplateMetadata build() {
return new TemplateMetadata(name, osTypeId, displayText);
}
}
private String name;
private long osTypeId;
private String displayText;
public TemplateMetadata(String name, long osTypeId, String displayText) {
this.name = name;
this.osTypeId = osTypeId;
this.displayText = displayText;
}
/**
* present only for serializer
*/
TemplateMetadata() {
}
/**
* @return the name of the template
*/
public String getName() {
return name;
}
/**
* @return the ID of the OS Type that best represents the OS of this template.
*/
public long getOsTypeId() {
return osTypeId;
}
/**
* @return the display text of the template. This is usually used for display purposes.
*/
public String getDisplayText() {
return displayText;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TemplateMetadata that = (TemplateMetadata) o;
if (osTypeId != that.osTypeId) return false;
if (displayText != null ? !displayText.equals(that.displayText) : that.displayText != null) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (int) (osTypeId ^ (osTypeId >>> 32));
result = 31 * result + (displayText != null ? displayText.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "[" +
"name='" + name + '\'' +
", osTypeId=" + osTypeId +
", displayText='" + displayText + '\'' +
']';
}
}

View File

@ -25,8 +25,10 @@ import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.cloudstack.binders.BindTemplateMetadataToQueryParams;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.domain.TemplateMetadata;
import org.jclouds.cloudstack.domain.TemplatePermission;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.AccountInDomainOptions;
@ -37,6 +39,7 @@ import org.jclouds.cloudstack.options.ListTemplatesOptions;
import org.jclouds.cloudstack.options.RegisterTemplateOptions;
import org.jclouds.cloudstack.options.UpdateTemplateOptions;
import org.jclouds.cloudstack.options.UpdateTemplatePermissionsOptions;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.OnlyElement;
import org.jclouds.rest.annotations.QueryParams;
@ -68,7 +71,7 @@ public interface TemplateAsyncClient {
@QueryParams(keys = "command", values = "createTemplate")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<AsyncCreateResponse> createTemplate(@QueryParam("name") String name, @QueryParam("ostypeid") long osTypeId, @QueryParam("displaytext") String displayText, CreateTemplateOptions... options);
ListenableFuture<AsyncCreateResponse> createTemplate(@BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata, CreateTemplateOptions... options);
/**
* @see TemplateClient#registerTemplate
@ -77,7 +80,7 @@ public interface TemplateAsyncClient {
@QueryParams(keys = "command", values = "registerTemplate")
@SelectJson("template")
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Template> registerTemplate(@QueryParam("name") String name, @QueryParam("ostypeid") long osTypeId, @QueryParam("format") String format, @QueryParam("hypervisor") String hypervisor, @QueryParam("url") String url, @QueryParam("zoneid") long zoneId, @QueryParam("displaytext") String displayText, RegisterTemplateOptions... options);
ListenableFuture<Template> registerTemplate(@BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata, @QueryParam("format") String format, @QueryParam("hypervisor") String hypervisor, @QueryParam("url") String url, @QueryParam("zoneid") long zoneId, RegisterTemplateOptions... options);
/**
* @see TemplateClient#updateTemplate
@ -95,7 +98,7 @@ public interface TemplateAsyncClient {
@QueryParams(keys = "command", values = "copyTemplate")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<AsyncCreateResponse> copyTemplate(@QueryParam("id") long id, @QueryParam("sourcezoneid") long sourceZoneId, @QueryParam("destzoneid") long destZoneId);
ListenableFuture<AsyncCreateResponse> copyTemplateToZone(@QueryParam("id") long id, @QueryParam("sourcezoneid") long sourceZoneId, @QueryParam("destzoneid") long destZoneId);
/**
* @see TemplateClient#deleteTemplate
@ -134,7 +137,7 @@ public interface TemplateAsyncClient {
@OnlyElement
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Template> getTemplateInZone(@QueryParam("zoneid") long zoneId, @QueryParam("id") long id);
ListenableFuture<Template> getTemplateInZone(@QueryParam("id") long templateId, @QueryParam("zoneid") long zoneId);
/**
* @see TemplateClient#updateTemplatePermissions
@ -159,5 +162,5 @@ public interface TemplateAsyncClient {
@QueryParams(keys = "command", values = "extractTemplate")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<AsyncCreateResponse> extractTemplate(@QueryParam("id") long id, @QueryParam("mode") String mode, @QueryParam("zoneid") long zoneId, ExtractTemplateOptions... options);
ListenableFuture<AsyncCreateResponse> extractTemplate(@QueryParam("id") long id, @QueryParam("mode") Template.ExtractMode mode, @QueryParam("zoneid") long zoneId, ExtractTemplateOptions... options);
}

View File

@ -88,7 +88,7 @@ public interface TemplateClient {
* @param destZoneId ID of the zone the template is being copied to.
* @return an asynchronous job response
*/
AsyncCreateResponse copyTemplate(long id, long sourceZoneId, long destZoneId);
AsyncCreateResponse copyTemplateToZone(long id, long sourceZoneId, long destZoneId);
/**
* Deletes a template from the system. All virtual machines using the deleted template will not be affected.
@ -119,13 +119,13 @@ public interface TemplateClient {
/**
* get a specific template by id
*
*
* @param templateId
* @param zoneId
* zone template is defined in
* @param id
* template to get
* @return template or null if not found
*/
Template getTemplateInZone(long zoneId, long id);
Template getTemplateInZone(long templateId, long zoneId);
/**
* Updates a template visibility permissions. A public template is visible to all accounts within the same domain. A private

View File

@ -24,6 +24,7 @@ import java.lang.reflect.Method;
import com.google.common.collect.ImmutableSet;
import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.domain.TemplateFilter;
import org.jclouds.cloudstack.domain.TemplateMetadata;
import org.jclouds.cloudstack.options.AccountInDomainOptions;
import org.jclouds.cloudstack.options.CreateTemplateOptions;
import org.jclouds.cloudstack.options.DeleteTemplateOptions;
@ -60,10 +61,10 @@ import javax.annotation.concurrent.Immutable;
public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<TemplateAsyncClient> {
public void testCreateTemplate() throws NoSuchMethodException {
Method method = TemplateAsyncClient.class.getMethod("createTemplate", String.class, long.class, String.class, CreateTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, "thename", 10, "description");
Method method = TemplateAsyncClient.class.getMethod("createTemplate", TemplateMetadata.class, CreateTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, TemplateMetadata.builder().name("thename").osTypeId(10).displayText("description").build());
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=createTemplate&name=thename&displaytext=description&ostypeid=10 HTTP/1.1");
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=createTemplate&name=thename&ostypeid=10&displaytext=description HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -75,11 +76,10 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
}
public void testCreateTemplateOptions() throws NoSuchMethodException {
Method method = TemplateAsyncClient.class.getMethod("createTemplate", String.class, long.class, String.class, CreateTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, "thename", 10, "description",
CreateTemplateOptions.Builder.bits(32).isFeatured(true).isPublic(true).passwordEnabled(true).requiresHVM(true).snapshotId(11).volumeId(12));
Method method = TemplateAsyncClient.class.getMethod("createTemplate", TemplateMetadata.class, CreateTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, TemplateMetadata.builder().name("thename").osTypeId(10).displayText("description").build(), CreateTemplateOptions.Builder.bits(32).isFeatured(true).isPublic(true).passwordEnabled(true).requiresHVM(true).snapshotId(11).volumeId(12));
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=createTemplate&name=thename&displaytext=description&ostypeid=10&bits=32&isfeatured=true&ispublic=true&passwordenabled=true&requireshvm=true&snapshotid=11&volumeid=12 HTTP/1.1");
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=createTemplate&bits=32&isfeatured=true&ispublic=true&passwordenabled=true&requireshvm=true&snapshotid=11&volumeid=12&name=thename&ostypeid=10&displaytext=description HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -91,10 +91,10 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
}
public void testRegisterTemplate() throws NoSuchMethodException {
Method method = TemplateAsyncClient.class.getMethod("registerTemplate", String.class, long.class, String.class, String.class, String.class, long.class, String.class, RegisterTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, "thename", 10, Template.Format.QCOW2, "xen", "http://example.com/", 20, "description");
Method method = TemplateAsyncClient.class.getMethod("registerTemplate", TemplateMetadata.class, String.class, String.class, String.class, long.class, RegisterTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, TemplateMetadata.builder().name("thename").osTypeId(10).displayText("description").build(), Template.Format.QCOW2, "xen", "http://example.com/", 20);
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=registerTemplate&displaytext=description&zoneid=20&name=thename&format=QCOW2&ostypeid=10&hypervisor=xen&url=http%3A%2F%2Fexample.com%2F HTTP/1.1");
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=registerTemplate&hypervisor=xen&format=QCOW2&url=http%3A%2F%2Fexample.com%2F&zoneid=20&name=thename&ostypeid=10&displaytext=description HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -106,11 +106,11 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
}
public void testRegisterTemplateOptions() throws NoSuchMethodException {
Method method = TemplateAsyncClient.class.getMethod("registerTemplate", String.class, long.class, String.class, String.class, String.class, long.class, String.class, RegisterTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, "thename", 10, Template.Format.QCOW2, "xen", "http://example.com/", 20, "description",
Method method = TemplateAsyncClient.class.getMethod("registerTemplate", TemplateMetadata.class, String.class, String.class, String.class, long.class, RegisterTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, TemplateMetadata.builder().name("thename").osTypeId(10).displayText("description").build(), Template.Format.QCOW2, "xen", "http://example.com/", 20,
RegisterTemplateOptions.Builder.accountInDomain("mydomain", 3).bits(32).checksum("ABC").isExtractable(true).isFeatured(true).isPublic(true).passwordEnabled(true).requiresHVM(true));
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=registerTemplate&displaytext=description&zoneid=20&name=thename&format=QCOW2&ostypeid=10&hypervisor=xen&url=http%3A%2F%2Fexample.com%2F&account=mydomain&domainid=3&bits=32&checksum=ABC&isextractable=true&isfeatured=true&ispublic=true&passwordenabled=true&requireshvm=true HTTP/1.1");
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=registerTemplate&hypervisor=xen&format=QCOW2&url=http%3A%2F%2Fexample.com%2F&zoneid=20&account=mydomain&domainid=3&bits=32&checksum=ABC&isextractable=true&isfeatured=true&ispublic=true&passwordenabled=true&requireshvm=true&name=thename&ostypeid=10&displaytext=description HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -152,7 +152,7 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
}
public void testCopyTemplate() throws NoSuchMethodException {
Method method = TemplateAsyncClient.class.getMethod("copyTemplate", long.class, long.class, long.class);
Method method = TemplateAsyncClient.class.getMethod("copyTemplateToZone", long.class, long.class, long.class);
HttpRequest httpRequest = processor.createRequest(method, 17, 18, 19);
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=copyTemplate&id=17&destzoneid=19&sourcezoneid=18 HTTP/1.1");
@ -237,11 +237,11 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
public void testGetTemplate() throws SecurityException, NoSuchMethodException, IOException {
Method method = TemplateAsyncClient.class.getMethod("getTemplateInZone", long.class, long.class);
HttpRequest httpRequest = processor.createRequest(method, 1, 5);
HttpRequest httpRequest = processor.createRequest(method, 5, 1);
assertRequestLineEquals(
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listTemplates&templatefilter=executable&zoneid=1&id=5 HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=listTemplates&templatefilter=executable&id=5&zoneid=1 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -315,8 +315,8 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
}
public void testExtractTemplate() throws NoSuchMethodException {
Method method = TemplateAsyncClient.class.getMethod("extractTemplate", long.class, String.class, long.class, ExtractTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, 3, "HTTP_DOWNLOAD", 5);
Method method = TemplateAsyncClient.class.getMethod("extractTemplate", long.class, Template.ExtractMode.class, long.class, ExtractTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, 3, Template.ExtractMode.HTTP_DOWNLOAD, 5);
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=extractTemplate&id=3&zoneid=5&mode=HTTP_DOWNLOAD HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
@ -330,7 +330,7 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
}
public void testExtractTemplateOptions() throws NoSuchMethodException {
Method method = TemplateAsyncClient.class.getMethod("extractTemplate", long.class, String.class, long.class, ExtractTemplateOptions[].class);
Method method = TemplateAsyncClient.class.getMethod("extractTemplate", long.class, Template.ExtractMode.class, long.class, ExtractTemplateOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, 3, Template.ExtractMode.HTTP_DOWNLOAD, 5, ExtractTemplateOptions.Builder.url("http://example.com/"));
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/client/api?response=json&command=extractTemplate&id=3&zoneid=5&mode=HTTP_DOWNLOAD&url=http%3A%2F%2Fexample.com%2F HTTP/1.1");

View File

@ -46,7 +46,7 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
Template newDetails = Iterables.getOnlyElement(client.getTemplateClient().listTemplates(
zoneId(template.getZoneId()).id(template.getId())));
assertEquals(template, newDetails);
assertEquals(template, client.getTemplateClient().getTemplateInZone(template.getZoneId(), template.getId()));
assertEquals(template, client.getTemplateClient().getTemplateInZone(template.getId(), template.getZoneId()));
assert template.getId() > 0 : template;
assert template.getName() != null : template;
assert template.getDisplayText() != null : template;