From e608674f934c1c2c0cf0c54b245428240194a3e8 Mon Sep 17 00:00:00 2001 From: andreisavu Date: Fri, 13 Jan 2012 16:11:27 +0200 Subject: [PATCH 1/3] Implemented Domain API for Domain Admin --- .../CloudStackDomainAsyncClient.java | 7 + .../cloudstack/CloudStackDomainClient.java | 7 + .../config/CloudStackRestClientModule.java | 3 + .../org/jclouds/cloudstack/domain/Domain.java | 192 ++++++++++++++++++ .../features/DomainDomainAsyncClient.java | 83 ++++++++ .../features/DomainDomainClient.java | 70 +++++++ .../options/ListDomainChildrenOptions.java | 133 ++++++++++++ .../options/ListDomainsOptions.java | 132 ++++++++++++ .../DomainDomainClientExpectTest.java | 182 +++++++++++++++++ .../features/DomainDomainClientLiveTest.java | 95 +++++++++ .../parse/ListDomainsResponseTest.java | 65 ++++++ .../src/test/resources/getdomainresponse.json | 2 + .../resources/listdomainchildrenresponse.json | 3 + .../test/resources/listdomainsresponse.json | 3 + 14 files changed, 977 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Domain.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/DomainDomainAsyncClient.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/DomainDomainClient.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListDomainChildrenOptions.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListDomainsOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/DomainDomainClientExpectTest.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/DomainDomainClientLiveTest.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListDomainsResponseTest.java create mode 100644 apis/cloudstack/src/test/resources/getdomainresponse.json create mode 100644 apis/cloudstack/src/test/resources/listdomainchildrenresponse.json create mode 100644 apis/cloudstack/src/test/resources/listdomainsresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackDomainAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackDomainAsyncClient.java index fc89a311d7..941ee5515e 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackDomainAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackDomainAsyncClient.java @@ -19,6 +19,7 @@ package org.jclouds.cloudstack; import org.jclouds.cloudstack.features.DomainAccountAsyncClient; +import org.jclouds.cloudstack.features.DomainDomainAsyncClient; import org.jclouds.cloudstack.features.DomainLimitAsyncClient; import org.jclouds.cloudstack.features.DomainUserAsyncClient; import org.jclouds.rest.annotations.Delegate; @@ -55,4 +56,10 @@ public interface CloudStackDomainAsyncClient extends CloudStackAsyncClient { @Delegate DomainUserAsyncClient getUserClient(); + /** + * Provides asynchronous access to Domains + */ + @Delegate + DomainDomainAsyncClient getDomainClient(); + } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackDomainClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackDomainClient.java index 62a29ea2e2..10537a505c 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackDomainClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackDomainClient.java @@ -21,6 +21,7 @@ package org.jclouds.cloudstack; import java.util.concurrent.TimeUnit; import org.jclouds.cloudstack.features.DomainAccountClient; +import org.jclouds.cloudstack.features.DomainDomainClient; import org.jclouds.cloudstack.features.DomainLimitClient; import org.jclouds.cloudstack.features.DomainUserClient; import org.jclouds.concurrent.Timeout; @@ -58,4 +59,10 @@ public interface CloudStackDomainClient extends CloudStackClient { */ @Delegate DomainUserClient getUserClient(); + + /** + * Provides synchronous access to Domains + */ + @Delegate + DomainDomainClient getDomainClient(); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java index 2c28734536..f4b060f2df 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java @@ -40,6 +40,8 @@ import org.jclouds.cloudstack.features.ConfigurationAsyncClient; import org.jclouds.cloudstack.features.ConfigurationClient; import org.jclouds.cloudstack.features.DomainAccountAsyncClient; import org.jclouds.cloudstack.features.DomainAccountClient; +import org.jclouds.cloudstack.features.DomainDomainAsyncClient; +import org.jclouds.cloudstack.features.DomainDomainClient; import org.jclouds.cloudstack.features.DomainLimitAsyncClient; import org.jclouds.cloudstack.features.DomainLimitClient; import org.jclouds.cloudstack.features.DomainUserAsyncClient; @@ -144,6 +146,7 @@ public class CloudStackRestClientModule extends RestClientModule { + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private long id; + private boolean hasChild; + private long level; + private String name; + private String networkDomain; + private long parentDomainId; + private String parentDomainName; + + public Builder id(long id) { + this.id = id; + return this; + } + + public Builder hasChild(boolean hasChild) { + this.hasChild = hasChild; + return this; + } + + public Builder level(long level) { + this.level = level; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder networkDomain(String networkDomain) { + this.networkDomain = networkDomain; + return this; + } + + public Builder parentDomainId(long parentDomainId) { + this.parentDomainId = parentDomainId; + return this; + } + + public Builder parentDomainName(String parentDomainName) { + this.parentDomainName = parentDomainName; + return this; + } + + public Domain build() { + return new Domain(id, hasChild, level, name, networkDomain, + parentDomainId, parentDomainName); + } + } + + // for deserialization + Domain() { + } + + private long id; + @SerializedName("haschild") + private boolean hasChild; + private long level; + private String name; + @SerializedName("networkdomain") + private String networkDomain; + @SerializedName("parentdomainid") + private long parentDomainId; + @SerializedName("parentdomainname") + private String parentDomainName; + + public Domain(long id, boolean hasChild, long level, String name, String networkDomain, + long parentDomainId, String parentDomainName) { + this.id = id; + this.hasChild = hasChild; + this.level = level; + this.name = name; + this.networkDomain = networkDomain; + this.parentDomainId = parentDomainId; + this.parentDomainName = parentDomainName; + } + + public long getId() { + return id; + } + + public boolean hasChild() { + return hasChild; + } + + public long getLevel() { + return level; + } + + public String getName() { + return name; + } + + public String getNetworkDomain() { + return networkDomain; + } + + public long getParentDomainId() { + return parentDomainId; + } + + public String getParentDomainName() { + return parentDomainName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Domain domain = (Domain) o; + + if (hasChild != domain.hasChild) return false; + if (id != domain.id) return false; + if (level != domain.level) return false; + if (parentDomainId != domain.parentDomainId) return false; + if (name != null ? !name.equals(domain.name) : domain.name != null) + return false; + if (networkDomain != null ? !networkDomain.equals(domain.networkDomain) : domain.networkDomain != null) + return false; + if (parentDomainName != null ? !parentDomainName.equals(domain.parentDomainName) : domain.parentDomainName != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (id ^ (id >>> 32)); + result = 31 * result + (hasChild ? 1 : 0); + result = 31 * result + (int) (level ^ (level >>> 32)); + result = 31 * result + (name != null ? name.hashCode() : 0); + result = 31 * result + (networkDomain != null ? networkDomain.hashCode() : 0); + result = 31 * result + (int) (parentDomainId ^ (parentDomainId >>> 32)); + result = 31 * result + (parentDomainName != null ? parentDomainName.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Domain{" + + "id=" + id + + ", hasChild=" + hasChild + + ", level=" + level + + ", name='" + name + '\'' + + ", networkDomain='" + networkDomain + '\'' + + ", parentDomainId=" + parentDomainId + + ", parentDomainName='" + parentDomainName + '\'' + + '}'; + } + + @Override + public int compareTo(Domain arg0) { + return new Long(id).compareTo(arg0.getId()); + } + +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/DomainDomainAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/DomainDomainAsyncClient.java new file mode 100644 index 0000000000..cbb620b94c --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/DomainDomainAsyncClient.java @@ -0,0 +1,83 @@ +/** + * 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.features; + +import com.google.common.util.concurrent.ListenableFuture; +import org.jclouds.cloudstack.domain.Domain; +import org.jclouds.cloudstack.filters.QuerySigner; +import org.jclouds.cloudstack.options.ListDomainChildrenOptions; +import org.jclouds.cloudstack.options.ListDomainsOptions; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.OnlyElement; +import org.jclouds.rest.annotations.QueryParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import java.util.Set; + +/** + * Provides asynchronous access to CloudStack Domain features available to Domain + * Admin users. + * + * @author Andrei Savu + * @see + */ +@RequestFilters(QuerySigner.class) +@QueryParams(keys = "response", values = "json") +public interface DomainDomainAsyncClient { + + /** + * @see DomainDomainClient#listDomains + */ + @GET + @QueryParams(keys = "command", values = "listDomains") + @SelectJson("domain") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listDomains(ListDomainsOptions... options); + + /** + * @see DomainDomainClient#getDomainById + */ + @GET + @QueryParams(keys = "command", values = "listDomains") + @SelectJson("domain") + @OnlyElement + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getDomainById(@QueryParam("id") long domainId); + + /** + * @see DomainDomainClient#listDomainChildren + */ + @GET + @QueryParams(keys = "command", values = "listDomainChildren") + @SelectJson("domain") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listDomainChildren(ListDomainChildrenOptions... options); +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/DomainDomainClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/DomainDomainClient.java new file mode 100644 index 0000000000..a2ae7ca5cc --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/DomainDomainClient.java @@ -0,0 +1,70 @@ +/** + * 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.features; + +import org.jclouds.cloudstack.domain.Domain; +import org.jclouds.cloudstack.options.ListDomainChildrenOptions; +import org.jclouds.cloudstack.options.ListDomainsOptions; +import org.jclouds.concurrent.Timeout; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * Provides synchronous access to CloudStack Domain features available to Domain + * Admin users. + * + * @author Andrei Savu + * @see + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface DomainDomainClient { + + /** + * List domains with detailed information + * + * @param options + * list filtering optional arguments + * @return + * set of domain instances or empty + */ + Set listDomains(ListDomainsOptions... options); + + /** + * Get a domain by ID + * + * @param domainId + * domain ID + * @return + * domain instance or null + */ + Domain getDomainById(long domainId); + + /** + * Lists all children domains belonging to a specified domain + * + * @param options + * list filtering optional arguments + * @return + * set of domain instances or empty + */ + Set listDomainChildren(ListDomainChildrenOptions... options); +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListDomainChildrenOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListDomainChildrenOptions.java new file mode 100644 index 0000000000..1adcea6a7b --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListDomainChildrenOptions.java @@ -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.options; + +import com.google.common.collect.ImmutableSet; +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Options used to control what domain children are returned + * + * @see + * @author Andrei Savu + */ +public class ListDomainChildrenOptions extends BaseHttpRequestOptions { + + public static final ListDomainChildrenOptions NONE = new ListDomainChildrenOptions(); + + /** + * @param parentDomainId + * firewall rule ID + */ + public ListDomainChildrenOptions parentDomainId(long parentDomainId) { + this.queryParameters.replaceValues("id", ImmutableSet.of(parentDomainId + "")); + return this; + } + + /** + * @param isRecursive + * to return the entire tree, use the value "true". To return + * the first level children, use the value "false". + */ + public ListDomainChildrenOptions isRecursive(boolean isRecursive) { + this.queryParameters.replaceValues("isrecursive", ImmutableSet.of(isRecursive + "")); + return this; + } + + /** + * @param keyword + * list by keyword + */ + public ListDomainChildrenOptions keyword(String keyword) { + this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword)); + return this; + } + + /** + * @param name + * list by domain name + */ + public ListDomainChildrenOptions name(String name) { + this.queryParameters.replaceValues("name", ImmutableSet.of(name)); + return this; + } + + public ListDomainChildrenOptions page(long page) { + this.queryParameters.replaceValues("page", ImmutableSet.of(page + "")); + return this; + } + + public ListDomainChildrenOptions pageSize(long pageSize) { + this.queryParameters.replaceValues("pagesize", ImmutableSet.of(pageSize + "")); + return this; + } + + public static class Builder { + + /** + * @see ListDomainChildrenOptions#parentDomainId + */ + public static ListDomainChildrenOptions parentDomainId(long parentDomainId) { + ListDomainChildrenOptions options = new ListDomainChildrenOptions(); + return options.parentDomainId(parentDomainId); + } + + /** + * @see ListDomainChildrenOptions#isRecursive + */ + public static ListDomainChildrenOptions isRecursive(boolean isRecursive) { + ListDomainChildrenOptions options = new ListDomainChildrenOptions(); + return options.isRecursive(isRecursive); + } + + /** + * @see ListDomainChildrenOptions#keyword + */ + public static ListDomainChildrenOptions keyword(String keyword) { + ListDomainChildrenOptions options = new ListDomainChildrenOptions(); + return options.keyword(keyword); + } + + /** + * @see ListDomainChildrenOptions#name + */ + public static ListDomainChildrenOptions name(String name) { + ListDomainChildrenOptions options = new ListDomainChildrenOptions(); + return options.name(name); + } + + /** + * @see ListDomainChildrenOptions#page + */ + public static ListDomainChildrenOptions page(long page) { + ListDomainChildrenOptions options = new ListDomainChildrenOptions(); + return options.page(page); + } + + /** + * @see ListDomainChildrenOptions#pageSize + */ + public static ListDomainChildrenOptions pageSize(long pageSize) { + ListDomainChildrenOptions options = new ListDomainChildrenOptions(); + return options.pageSize(pageSize); + } + } +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListDomainsOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListDomainsOptions.java new file mode 100644 index 0000000000..3b987df6ad --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListDomainsOptions.java @@ -0,0 +1,132 @@ +/** + * 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.options; + +import com.google.common.collect.ImmutableSet; +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Options used to control what domains are returned + * + * @see + * @author Andrei Savu + */ +public class ListDomainsOptions extends BaseHttpRequestOptions { + + public static final ListDomainsOptions NONE = new ListDomainsOptions(); + + /** + * @param id + * firewall rule ID + */ + public ListDomainsOptions id(long id) { + this.queryParameters.replaceValues("id", ImmutableSet.of(id + "")); + return this; + } + + /** + * @param keyword + * list by keyword + */ + public ListDomainsOptions keyword(String keyword) { + this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword)); + return this; + } + + /** + * @param level + * list by domain level + */ + public ListDomainsOptions level(long level) { + this.queryParameters.replaceValues("level", ImmutableSet.of(level + "")); + return this; + } + + /** + * @param name + * list by domain name + */ + public ListDomainsOptions name(String name) { + this.queryParameters.replaceValues("name", ImmutableSet.of(name)); + return this; + } + + public ListDomainsOptions page(long page) { + this.queryParameters.replaceValues("page", ImmutableSet.of(page + "")); + return this; + } + + public ListDomainsOptions pageSize(long pageSize) { + this.queryParameters.replaceValues("pagesize", ImmutableSet.of(pageSize + "")); + return this; + } + + public static class Builder { + + /** + * @see ListDomainsOptions#id + */ + public static ListDomainsOptions id(long id) { + ListDomainsOptions options = new ListDomainsOptions(); + return options.id(id); + } + + /** + * @see ListDomainsOptions#keyword + */ + public static ListDomainsOptions keyword(String keyword) { + ListDomainsOptions options = new ListDomainsOptions(); + return options.keyword(keyword); + } + + /** + * @see ListDomainsOptions#level + */ + public static ListDomainsOptions level(long level) { + ListDomainsOptions options = new ListDomainsOptions(); + return options.level(level); + } + + /** + * @see ListDomainsOptions#name + */ + public static ListDomainsOptions name(String name) { + ListDomainsOptions options = new ListDomainsOptions(); + return options.name(name); + } + + /** + * @see ListDomainsOptions#page + */ + public static ListDomainsOptions page(long page) { + ListDomainsOptions options = new ListDomainsOptions(); + return options.page(page); + } + + /** + * @see ListDomainsOptions#pageSize + */ + public static ListDomainsOptions pageSize(long pageSize) { + ListDomainsOptions options = new ListDomainsOptions(); + return options.pageSize(pageSize); + } + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/DomainDomainClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/DomainDomainClientExpectTest.java new file mode 100644 index 0000000000..f47d03e03d --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/DomainDomainClientExpectTest.java @@ -0,0 +1,182 @@ +/** + * 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.features; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.domain.Account; +import org.jclouds.cloudstack.domain.Domain; +import org.jclouds.cloudstack.domain.User; +import org.jclouds.cloudstack.options.ListDomainChildrenOptions; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import java.net.URI; +import java.util.Set; + +import static org.jclouds.cloudstack.options.ListDomainChildrenOptions.Builder.parentDomainId; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * Test the CloudStack DomainDomainClient + * + * @author Andrei Savu + */ +@Test(groups = "unit", testName = "DomainDomainClientExpectTest") +public class DomainDomainClientExpectTest extends BaseCloudStackRestClientExpectTest { + + public void testListDomainsWhenResponseIs2xx() { + DomainDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listDomains&apiKey=identity&signature=MmzRB%2FpKlYyWy7kE3IMXrg4BUtk%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/listdomainsresponse.json")) + .build()); + + assertEquals(client.listDomains(), + ImmutableSet.of( + Domain.builder().id(1L).name("ROOT").level(0).hasChild(true).build(), + Domain.builder().id(2L).name("jclouds1").level(1).parentDomainId(1) + .parentDomainName("ROOT").hasChild(false).build() + )); + } + + public void testListDomainsWhenResponseIs404() { + DomainDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listDomains&apiKey=identity&signature=MmzRB%2FpKlYyWy7kE3IMXrg4BUtk%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertEquals(client.listDomains(), ImmutableSet.of()); + } + + public void testGetDomainWhenResponseIs2xx() { + DomainDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listDomains&id=1&apiKey=identity&signature=emQKWkVhospRkaUzjKljME2rW0k%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/getdomainresponse.json")) + .build()); + + assertEquals(client.getDomainById(1), + Domain.builder().id(1L).name("ROOT").level(0).hasChild(true).build()); + } + + public void testGetDomainWhenResponseIs404() { + DomainDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listDomains&id=1&apiKey=identity&signature=emQKWkVhospRkaUzjKljME2rW0k%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertNull(client.getDomainById(1)); + } + + public void testListDomainChildrenWhenResponseIs2xx() { + DomainDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listDomainChildren&id=1&isrecursive=true&apiKey=identity&signature=bDMSkjme8k0ANUPm4YiTYKe2N88%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/listdomainchildrenresponse.json")) + .build()); + + assertEquals(client.listDomainChildren(parentDomainId(1).isRecursive(true)), + ImmutableSet.of( + Domain.builder().id(2L).name("jclouds1").level(1).parentDomainId(1) + .parentDomainName("ROOT").hasChild(false).build(), + Domain.builder().id(3L).name("jclouds2").level(1).parentDomainId(1) + .parentDomainName("ROOT").hasChild(false).build() + )); + } + + public void testListDomainChildrenWhenResponseIs404() { + DomainDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listDomainChildren&id=1&isrecursive=true&apiKey=identity&" + + "signature=bDMSkjme8k0ANUPm4YiTYKe2N88%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertEquals(client.listDomainChildren(parentDomainId(1).isRecursive(true)), ImmutableSet.of()); + } + + @Override + protected DomainDomainClient clientFrom(CloudStackContext context) { + return context.getDomainContext().getApi().getDomainClient(); + } +} \ No newline at end of file diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/DomainDomainClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/DomainDomainClientLiveTest.java new file mode 100644 index 0000000000..553a563fc4 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/DomainDomainClientLiveTest.java @@ -0,0 +1,95 @@ +/** + * 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.features; + +import com.google.common.base.Predicate; +import org.jclouds.cloudstack.domain.Domain; +import org.testng.annotations.Test; + +import javax.annotation.Nullable; +import java.util.Set; + +import static com.google.common.collect.Iterables.find; +import static org.jclouds.cloudstack.options.ListDomainChildrenOptions.Builder.parentDomainId; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +/** + * Tests behavior of {@code DomainDomainClient} + * + * @author Andrei Savu + */ +@Test(groups = "live", singleThreaded = true, testName = "DomainDomainClientLiveTest") +public class DomainDomainClientLiveTest extends BaseCloudStackClientLiveTest { + + @Test + public void testListDomains() { + assert domainAdminEnabled; + + Set allDomains = domainAdminClient.getDomainClient().listDomains(); + + Domain root = find(allDomains, withName("ROOT")); + assertEquals(root, domainAdminClient.getDomainClient().getDomainById(root.getId())); + assertEquals(root.getLevel(), 0); + assertEquals(root.getParentDomainId(), 0); + assertNull(root.getParentDomainName()); + if (allDomains.size() > 0) { + assertTrue(root.hasChild()); + } + + for (Domain domain : allDomains) { + checkDomain(domain, allDomains); + } + } + + @Test + public void testListDomainChildren() { + assert domainAdminEnabled; + + Set allDomains = domainAdminClient.getDomainClient().listDomains(); + Domain root = find(allDomains, withName("ROOT")); + + Set children = domainAdminClient.getDomainClient() + .listDomainChildren(parentDomainId(root.getId()).isRecursive(true)); + assertEquals(allDomains.size() - 1, children.size()); + + for (Domain domain : children) { + checkDomain(domain, allDomains); + } + } + + private Predicate withName(final String name) { + return new Predicate() { + @Override + public boolean apply(@Nullable Domain domain) { + return domain != null && domain.getName().equals(name); + } + }; + } + + private void checkDomain(Domain domain, Set allDomains) { + assert domain.getId() > 0 : domain; + if (domain.getParentDomainName() != null) { + Domain parent = find(allDomains, withName(domain.getParentDomainName())); + assertEquals(parent.getId(), domain.getParentDomainId()); + assertTrue(parent.hasChild()); + } + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListDomainsResponseTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListDomainsResponseTest.java new file mode 100644 index 0000000000..f6fa41acd4 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListDomainsResponseTest.java @@ -0,0 +1,65 @@ +/** + * 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.parse; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.jclouds.cloudstack.config.CloudStackParserModule; +import org.jclouds.cloudstack.domain.Domain; +import org.jclouds.json.BaseSetParserTest; +import org.jclouds.json.config.GsonModule; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +import java.util.Set; + +/** + * @author Andrei Savu + */ +@Test(groups = "unit") +public class ListDomainsResponseTest extends BaseSetParserTest { + + @Override + protected Injector injector() { + return Guice.createInjector(new CloudStackParserModule(), new GsonModule() { + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + }); + } + + @Override + public String resource() { + return "/listdomainsresponse.json"; + } + + @Override + @SelectJson("domain") + public Set expected() { + return ImmutableSet.of( + Domain.builder().id(1L).name("ROOT").level(0).hasChild(true).build(), + Domain.builder().id(2L).name("jclouds1").level(1).parentDomainId(1) + .parentDomainName("ROOT").hasChild(false).build() + ); + } + +} diff --git a/apis/cloudstack/src/test/resources/getdomainresponse.json b/apis/cloudstack/src/test/resources/getdomainresponse.json new file mode 100644 index 0000000000..a3baf5705a --- /dev/null +++ b/apis/cloudstack/src/test/resources/getdomainresponse.json @@ -0,0 +1,2 @@ +{ "listdomainsresponse" : { "count":1 ,"domain" : [ + {"id":1,"name":"ROOT","level":0,"haschild":true} ] } } \ No newline at end of file diff --git a/apis/cloudstack/src/test/resources/listdomainchildrenresponse.json b/apis/cloudstack/src/test/resources/listdomainchildrenresponse.json new file mode 100644 index 0000000000..5cd2289bac --- /dev/null +++ b/apis/cloudstack/src/test/resources/listdomainchildrenresponse.json @@ -0,0 +1,3 @@ +{ "listdomainchildrenresponse" : { "count":2 ,"domain" : [ + {"id":2,"name":"jclouds1","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false}, + {"id":3,"name":"jclouds2","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false} ] } } \ No newline at end of file diff --git a/apis/cloudstack/src/test/resources/listdomainsresponse.json b/apis/cloudstack/src/test/resources/listdomainsresponse.json new file mode 100644 index 0000000000..79d7e00237 --- /dev/null +++ b/apis/cloudstack/src/test/resources/listdomainsresponse.json @@ -0,0 +1,3 @@ +{ "listdomainsresponse" : { "count":2 ,"domain" : [ + {"id":1,"name":"ROOT","level":0,"haschild":true}, + {"id":2,"name":"jclouds1","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false} ] } } \ No newline at end of file From 23ce896dd2f4bb0ebbd81e9b9e43b562112967c1 Mon Sep 17 00:00:00 2001 From: andreisavu Date: Fri, 13 Jan 2012 17:37:25 +0200 Subject: [PATCH 2/3] Implemented Domain API for Global Admin --- .../CloudStackGlobalAsyncClient.java | 8 ++ .../cloudstack/CloudStackGlobalClient.java | 8 ++ .../config/CloudStackRestClientModule.java | 3 + .../features/GlobalDomainAsyncClient.java | 87 +++++++++++++++++++ .../features/GlobalDomainClient.java | 79 +++++++++++++++++ .../options/CreateDomainOptions.java | 75 ++++++++++++++++ .../options/UpdateDomainOptions.java | 72 +++++++++++++++ .../features/GlobalDomainClientLiveTest.java | 81 +++++++++++++++++ 8 files changed, 413 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalDomainAsyncClient.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalDomainClient.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateDomainOptions.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateDomainOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientLiveTest.java diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java index b73d74a416..28f23cb064 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java @@ -23,6 +23,7 @@ import org.jclouds.cloudstack.features.GlobalAlertAsyncClient; import org.jclouds.cloudstack.features.GlobalCapacityAsyncClient; import org.jclouds.cloudstack.features.GlobalConfigurationAsyncClient; import org.jclouds.cloudstack.features.GlobalConfigurationClient; +import org.jclouds.cloudstack.features.GlobalDomainAsyncClient; import org.jclouds.cloudstack.features.GlobalHostAsyncClient; import org.jclouds.cloudstack.features.GlobalOfferingAsyncClient; import org.jclouds.cloudstack.features.GlobalStoragePoolAsyncClient; @@ -99,4 +100,11 @@ public interface CloudStackGlobalAsyncClient extends CloudStackDomainAsyncClient @Delegate @Override GlobalConfigurationAsyncClient getConfigurationClient(); + + /** + * Provides asynchronous access to Domain + */ + @Delegate + @Override + GlobalDomainAsyncClient getDomainClient(); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java index b6dc916c60..135a2cb755 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java @@ -24,6 +24,7 @@ import org.jclouds.cloudstack.features.GlobalAccountClient; import org.jclouds.cloudstack.features.GlobalAlertClient; import org.jclouds.cloudstack.features.GlobalCapacityClient; import org.jclouds.cloudstack.features.GlobalConfigurationClient; +import org.jclouds.cloudstack.features.GlobalDomainClient; import org.jclouds.cloudstack.features.GlobalHostClient; import org.jclouds.cloudstack.features.GlobalOfferingClient; import org.jclouds.cloudstack.features.GlobalStoragePoolClient; @@ -102,4 +103,11 @@ public interface CloudStackGlobalClient extends CloudStackDomainClient { @Delegate @Override GlobalConfigurationClient getConfigurationClient(); + + /** + * Provides synchronous access to Domain + */ + @Delegate + @Override + GlobalDomainClient getDomainClient(); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java index f4b060f2df..62d4b1b284 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java @@ -58,6 +58,8 @@ import org.jclouds.cloudstack.features.GlobalCapacityAsyncClient; import org.jclouds.cloudstack.features.GlobalCapacityClient; import org.jclouds.cloudstack.features.GlobalConfigurationAsyncClient; import org.jclouds.cloudstack.features.GlobalConfigurationClient; +import org.jclouds.cloudstack.features.GlobalDomainAsyncClient; +import org.jclouds.cloudstack.features.GlobalDomainClient; import org.jclouds.cloudstack.features.GlobalHostAsyncClient; import org.jclouds.cloudstack.features.GlobalHostClient; import org.jclouds.cloudstack.features.GlobalOfferingAsyncClient; @@ -147,6 +149,7 @@ public class CloudStackRestClientModule extends RestClientModule + */ +@RequestFilters(QuerySigner.class) +@QueryParams(keys = "response", values = "json") +public interface GlobalDomainAsyncClient extends DomainDomainAsyncClient { + + /** + * @see GlobalDomainClient#createDomain + */ + @GET + @QueryParams(keys = "command", values = "createDomain") + @SelectJson("domain") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture createDomain(@QueryParam("name") String name, CreateDomainOptions... options); + + /** + * @see GlobalDomainClient#updateDomain + */ + @GET + @QueryParams(keys = "command", values = "updateDomain") + @SelectJson("domain") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture updateDomain(@QueryParam("id") long domainId, UpdateDomainOptions... options); + + /** + * @see GlobalDomainClient#deleteOnlyDomain + */ + @GET + @QueryParams(keys = {"command", "cleanup"}, values = {"deleteDomain", "false"}) + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture deleteOnlyDomain(@QueryParam("id") long id); + + /** + * @see GlobalDomainClient#deleteDomainAndAttachedResources + */ + @GET + @QueryParams(keys = {"command", "cleanup"}, values = {"deleteDomain", "true"}) + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture deleteDomainAndAttachedResources(@QueryParam("id") long id); +} + diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalDomainClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalDomainClient.java new file mode 100644 index 0000000000..9dd9099f43 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalDomainClient.java @@ -0,0 +1,79 @@ +/** + * 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.features; + +import org.jclouds.cloudstack.domain.Domain; +import org.jclouds.cloudstack.options.CreateDomainOptions; +import org.jclouds.cloudstack.options.UpdateDomainOptions; +import org.jclouds.concurrent.Timeout; + +import java.util.concurrent.TimeUnit; + +/** + * Provides synchronous access to CloudStack Domain features available to Global + * Admin users. + * + * @author Andrei Savu + * @see + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface GlobalDomainClient extends DomainDomainClient { + + /** + * Create new Domain + * + * @param name + * domain name + * @param options + * optional arguments + * @return + * domain instance + */ + Domain createDomain(String name, CreateDomainOptions... options); + + /** + * Update a domain + * + * @param domainId + * the ID of the domain + * @param options + * optional arguments + * @return + * domain instance + */ + Domain updateDomain(long domainId, UpdateDomainOptions... options); + + /** + * Delete domain (without deleting attached resources) + * + * @param id + * the domain ID + */ + Void deleteOnlyDomain(long id); + + /** + * Delete domain and cleanup all attached resources + * + * @param id + * the domain ID + */ + Void deleteDomainAndAttachedResources(long id); +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateDomainOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateDomainOptions.java new file mode 100644 index 0000000000..9012402b5b --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateDomainOptions.java @@ -0,0 +1,75 @@ +/** + * 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.options; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; +import org.jclouds.http.options.BaseHttpRequestOptions; + +import java.util.Set; + +/** + * Options used to control how a domain is created + * + * @see + * @author Andrei Savu + */ +public class CreateDomainOptions extends BaseHttpRequestOptions { + + public static final CreateDomainOptions NONE = new CreateDomainOptions(); + + /** + * @param networkDomain + * network domain for networks in the domain + */ + public CreateDomainOptions networkDomain(String networkDomain) { + this.queryParameters.replaceValues("networkdomain", ImmutableSet.of(networkDomain)); + return this; + } + + /** + * @param parentDomainId + * the ID of the parent domain + */ + public CreateDomainOptions parentDomainId(long parentDomainId) { + this.queryParameters.replaceValues("parentdomainid", ImmutableSet.of(parentDomainId + "")); + return this; + } + + public static class Builder { + + /** + * @see CreateDomainOptions#networkDomain + */ + public static CreateDomainOptions networkDomain(String networkDomain) { + CreateDomainOptions options = new CreateDomainOptions(); + return options.networkDomain(networkDomain); + } + + /** + * @see CreateDomainOptions#parentDomainId + */ + public static CreateDomainOptions parentDomainId(long parentDomainId) { + CreateDomainOptions options = new CreateDomainOptions(); + return options.parentDomainId(parentDomainId); + } + } +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateDomainOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateDomainOptions.java new file mode 100644 index 0000000000..d7d972f460 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateDomainOptions.java @@ -0,0 +1,72 @@ +/** + * 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.options; + +import com.google.common.collect.ImmutableSet; +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Options used to control how a domain is created + * + * @see + * @author Andrei Savu + */ +public class UpdateDomainOptions extends BaseHttpRequestOptions { + + public static final UpdateDomainOptions NONE = new UpdateDomainOptions(); + + /** + * @param name + * the new name for this domain + */ + public UpdateDomainOptions name(String name) { + this.queryParameters.replaceValues("name", ImmutableSet.of(name)); + return this; + } + + /** + * @param networkDomain + * network domain for networks in the domain + */ + public UpdateDomainOptions networkDomain(String networkDomain) { + this.queryParameters.replaceValues("networkdomain", ImmutableSet.of(networkDomain)); + return this; + } + + public static class Builder { + + /** + * @see UpdateDomainOptions#name + */ + public static UpdateDomainOptions name(String name) { + UpdateDomainOptions options = new UpdateDomainOptions(); + return options.name(name); + } + + /** + * @see UpdateDomainOptions#networkDomain + */ + public static UpdateDomainOptions networkDomain(String networkDomain) { + UpdateDomainOptions options = new UpdateDomainOptions(); + return options.networkDomain(networkDomain); + } + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientLiveTest.java new file mode 100644 index 0000000000..b58376e911 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientLiveTest.java @@ -0,0 +1,81 @@ +/** + * 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.features; + +import com.google.common.base.Predicate; +import org.jclouds.cloudstack.domain.Domain; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import javax.annotation.Nullable; + +import static com.google.common.collect.Iterables.find; +import static org.jclouds.cloudstack.options.UpdateDomainOptions.Builder.name; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * Tests behavior of {@code GlobalDomainClient} + * + * @author Andrei Savu + */ +@Test(groups = "live", singleThreaded = true, testName = "GlobalDomainClientLiveTest") +public class GlobalDomainClientLiveTest extends BaseCloudStackClientLiveTest { + + private GlobalDomainClient domainClient; + private Domain rootDomain; + + @BeforeMethod + public void before() { + domainClient = globalAdminClient.getDomainClient(); + rootDomain = find(domainClient.listDomains(), new Predicate() { + @Override + public boolean apply(@Nullable Domain domain) { + return domain != null && domain.getName().equals("ROOT"); + } + }); + } + + @Test + public void testCreateAndUpdateDomain() { + assert globalAdminEnabled; + + Domain domain = null; + try { + domain = domainClient.createDomain(prefix + "-domain"); + checkDomain(domain, rootDomain, prefix + "-domain"); + + Domain updated = domainClient.updateDomain(domain.getId(), name(prefix + "-domain-2")); + checkDomain(updated, rootDomain, prefix + "-domain-2"); + assertEquals(updated.getId(), domain.getId()); + + } finally { + if (domain != null) { + domainClient.deleteDomainAndAttachedResources(domain.getId()); + } + } + assertNull(domainClient.getDomainById(domain.getId())); + } + + private void checkDomain(Domain domain, Domain rootDomain, String expectedName) { + assertEquals(domain.getParentDomainId(), rootDomain.getId()); + assertEquals(domain.getName(), expectedName); + assertEquals(domain.getParentDomainName(), rootDomain.getName()); + } +} From eb0e11689b15505561fe2e67364d235080f43fde Mon Sep 17 00:00:00 2001 From: andreisavu Date: Fri, 13 Jan 2012 22:02:27 +0200 Subject: [PATCH 3/3] Added expect tests for global domain client --- .../GlobalDomainClientExpectTest.java | 163 ++++++++++++++++++ .../features/GlobalDomainClientLiveTest.java | 2 +- .../test/resources/createdomainresponse.json | 2 + .../test/resources/deletedomainresponse.json | 1 + .../test/resources/updatedomainresponse.json | 2 + 5 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientExpectTest.java create mode 100644 apis/cloudstack/src/test/resources/createdomainresponse.json create mode 100644 apis/cloudstack/src/test/resources/deletedomainresponse.json create mode 100644 apis/cloudstack/src/test/resources/updatedomainresponse.json diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientExpectTest.java new file mode 100644 index 0000000000..4b3ecb8715 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientExpectTest.java @@ -0,0 +1,163 @@ +/** + * 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.features; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.domain.Domain; +import org.jclouds.cloudstack.options.UpdateDomainOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import java.net.URI; + +import static org.jclouds.cloudstack.options.ListDomainChildrenOptions.Builder.parentDomainId; +import static org.jclouds.cloudstack.options.UpdateDomainOptions.Builder.name; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * Test the CloudStack GlobalDomainClient + * + * @author Andrei Savu + */ +@Test(groups = "unit", testName = "GlobalDomainClientExpectTest") +public class GlobalDomainClientExpectTest extends BaseCloudStackRestClientExpectTest { + + public void testCreateDomainWhenResponseIs2xx() { + GlobalDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&command=createDomain&" + + "name=test&apiKey=identity&signature=6cxzEo7h63G0hgTTMLm4lGsSDK8%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/createdomainresponse.json")) + .build()); + + assertEquals(client.createDomain("test"), + Domain.builder().id(10L).name("test").level(1).parentDomainId(1L) + .parentDomainName("ROOT").hasChild(false).build()); + } + + public void testCreateDomainWhenResponseIs404() { + GlobalDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&command=createDomain&" + + "name=test&apiKey=identity&signature=6cxzEo7h63G0hgTTMLm4lGsSDK8%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertNull(client.createDomain("test")); + } + + public void testUpdateDomainWhenResponseIs2xx() { + GlobalDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=updateDomain&id=10&name=test-2&apiKey=identity&signature=5t1eUf2Eyf%2FaB6qt%2BqIj%2BmcwFIo%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/updatedomainresponse.json")) + .build()); + + assertEquals(client.updateDomain(10, name("test-2")), + Domain.builder().id(10L).name("test-2").level(1).parentDomainId(1L) + .parentDomainName("ROOT").hasChild(false).build()); + } + + public void testUpdateDomainWhenResponseIs404() { + GlobalDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=updateDomain&id=10&name=test-2&apiKey=identity&signature=5t1eUf2Eyf%2FaB6qt%2BqIj%2BmcwFIo%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertNull(client.updateDomain(10, name("test-2"))); + } + + public void testDeleteOnlyDomain() { + GlobalDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=deleteDomain&cleanup=false&id=1&apiKey=identity&signature=%2F5aLbigg612t9IrZi0JZO7CyiOU%3D")) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/deletedomainresponse.json")) + .build()); + + client.deleteOnlyDomain(1); + } + + public void testDeleteDomainAndAttachedResources() { + GlobalDomainClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=deleteDomain&cleanup=true&id=1&apiKey=identity&signature=grL7JStvtYUT89Jr0D8FgwMyJpU%3D")) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/deletedomainresponse.json")) + .build()); + + client.deleteDomainAndAttachedResources(1); + } + + @Override + protected GlobalDomainClient clientFrom(CloudStackContext context) { + return context.getGlobalContext().getApi().getDomainClient(); + } +} \ No newline at end of file diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientLiveTest.java index b58376e911..d585ebef01 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalDomainClientLiveTest.java @@ -53,7 +53,7 @@ public class GlobalDomainClientLiveTest extends BaseCloudStackClientLiveTest { } @Test - public void testCreateAndUpdateDomain() { + public void testCreateUpdateDeleteDomain() { assert globalAdminEnabled; Domain domain = null; diff --git a/apis/cloudstack/src/test/resources/createdomainresponse.json b/apis/cloudstack/src/test/resources/createdomainresponse.json new file mode 100644 index 0000000000..c5882ab571 --- /dev/null +++ b/apis/cloudstack/src/test/resources/createdomainresponse.json @@ -0,0 +1,2 @@ +{ "createdomainresponse" : { "domain" : + {"id":10,"name":"test","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false} } } \ No newline at end of file diff --git a/apis/cloudstack/src/test/resources/deletedomainresponse.json b/apis/cloudstack/src/test/resources/deletedomainresponse.json new file mode 100644 index 0000000000..d617a158a2 --- /dev/null +++ b/apis/cloudstack/src/test/resources/deletedomainresponse.json @@ -0,0 +1 @@ +{ "deletedomainresponse" : {"jobid":2413} } \ No newline at end of file diff --git a/apis/cloudstack/src/test/resources/updatedomainresponse.json b/apis/cloudstack/src/test/resources/updatedomainresponse.json new file mode 100644 index 0000000000..1745eacf94 --- /dev/null +++ b/apis/cloudstack/src/test/resources/updatedomainresponse.json @@ -0,0 +1,2 @@ +{ "updatedomainresponse" : { "domain" : + {"id":10,"name":"test-2","level":1,"parentdomainid":1,"parentdomainname":"ROOT","haschild":false} } } \ No newline at end of file