From de9691cccbace70dd289f2b0fd9ee05453064e94 Mon Sep 17 00:00:00 2001 From: andreisavu Date: Tue, 10 Jan 2012 18:13:52 +0200 Subject: [PATCH 1/5] Implemented listConfigurationEntries API --- .../CloudStackGlobalAsyncClient.java | 9 ++ .../cloudstack/CloudStackGlobalClient.java | 8 + .../config/CloudStackRestClientModule.java | 3 + .../cloudstack/domain/ConfigurationEntry.java | 139 ++++++++++++++++++ .../GlobalConfigurationAsyncClient.java | 59 ++++++++ .../features/GlobalConfigurationClient.java | 50 +++++++ .../ListConfigurationEntriesOptions.java | 115 +++++++++++++++ .../GlobalConfigurationClientExpectTest.java | 79 ++++++++++ .../GlobalConfigurationClientLiveTest.java | 58 ++++++++ .../ListConfigurationEntriesResponseTest.java | 69 +++++++++ .../resources/listconfigurationsresponse.json | 4 + 11 files changed, 593 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/ConfigurationEntry.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListConfigurationEntriesOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListConfigurationEntriesResponseTest.java create mode 100644 apis/cloudstack/src/test/resources/listconfigurationsresponse.json 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 677309887c..b73d74a416 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java @@ -21,6 +21,8 @@ package org.jclouds.cloudstack; import org.jclouds.cloudstack.features.GlobalAccountAsyncClient; 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.GlobalHostAsyncClient; import org.jclouds.cloudstack.features.GlobalOfferingAsyncClient; import org.jclouds.cloudstack.features.GlobalStoragePoolAsyncClient; @@ -90,4 +92,11 @@ public interface CloudStackGlobalAsyncClient extends CloudStackDomainAsyncClient */ @Delegate GlobalUsageAsyncClient getUsageClient(); + + /** + * Provides asynchronous access to Configuration + */ + @Delegate + @Override + GlobalConfigurationAsyncClient getConfigurationClient(); } 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 a1f73671dc..b6dc916c60 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java @@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit; 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.GlobalHostClient; import org.jclouds.cloudstack.features.GlobalOfferingClient; import org.jclouds.cloudstack.features.GlobalStoragePoolClient; @@ -94,4 +95,11 @@ public interface CloudStackGlobalClient extends CloudStackDomainClient { */ @Delegate GlobalUsageClient getUsageClient(); + + /** + * Provides synchronous access to Configuration + */ + @Delegate + @Override + GlobalConfigurationClient getConfigurationClient(); } 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 5b2bc37fe7..2c28734536 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 @@ -54,6 +54,8 @@ import org.jclouds.cloudstack.features.GlobalAlertAsyncClient; import org.jclouds.cloudstack.features.GlobalAlertClient; 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.GlobalHostAsyncClient; import org.jclouds.cloudstack.features.GlobalHostClient; import org.jclouds.cloudstack.features.GlobalOfferingAsyncClient; @@ -138,6 +140,7 @@ public class CloudStackRestClientModule extends RestClientModule { + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private String category; + private String description; + private String name; + private String value; + + public Builder category(String category) { + this.category = category; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder value(String value) { + this.value = value; + return this; + } + + public ConfigurationEntry build() { + return new ConfigurationEntry(category, description, name, value); + } + } + + // for deserialization + ConfigurationEntry() { + } + + private String category; + private String description; + private String name; + private String value; + + public ConfigurationEntry(String category, String description, String name, String value) { + this.category = category; + this.description = description; + this.name = name; + this.value = value; + } + + @Override + public int compareTo(ConfigurationEntry arg0) { + return name.compareTo(arg0.getName()); + } + + public String getCategory() { + return category; + } + + public String getDescription() { + return description; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ConfigurationEntry that = (ConfigurationEntry) o; + + if (category != null ? !category.equals(that.category) : that.category != null) + return false; + if (description != null ? !description.equals(that.description) : that.description != null) + return false; + if (name != null ? !name.equals(that.name) : that.name != null) + return false; + if (value != null ? !value.equals(that.value) : that.value != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = category != null ? category.hashCode() : 0; + result = 31 * result + (description != null ? description.hashCode() : 0); + result = 31 * result + (name != null ? name.hashCode() : 0); + result = 31 * result + (value != null ? value.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "ConfigurationEntry{" + + "category='" + category + '\'' + + ", description='" + description + '\'' + + ", name='" + name + '\'' + + ", value='" + value + '\'' + + '}'; + } +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java new file mode 100644 index 0000000000..7af26740f8 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java @@ -0,0 +1,59 @@ +/** + * 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.ConfigurationEntry; +import org.jclouds.cloudstack.filters.QuerySigner; +import org.jclouds.cloudstack.options.ListConfigurationEntriesOptions; +import org.jclouds.rest.annotations.ExceptionParser; +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 javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.core.MediaType; +import java.util.Set; + +/** + * Provides asynchronous access to CloudStack Configuration features available to Global + * Admin users. + * + * @author Andrei Savu + * @see + */ +@RequestFilters(QuerySigner.class) +@QueryParams(keys = "response", values = "json") +public interface GlobalConfigurationAsyncClient extends ConfigurationAsyncClient { + + /** + * @see GlobalConfigurationClient#listConfigurationEntries + */ + @GET + @QueryParams(keys = "command", values = "listConfigurations") + @SelectJson("configuration") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listConfigurationEntries(ListConfigurationEntriesOptions... options); + +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java new file mode 100644 index 0000000000..e9783eb795 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java @@ -0,0 +1,50 @@ +/** + * 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.ConfigurationEntry; +import org.jclouds.cloudstack.options.ListConfigurationEntriesOptions; +import org.jclouds.concurrent.Timeout; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * Provides synchronous access to CloudStack Configuration features available to Global + * Admin users. + * + * @author Andrei Savu + * @see + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface GlobalConfigurationClient extends ConfigurationClient { + + /** + * List all configuration entries + * + * @param options + * result set filtering options + * @return + * a set of entries or empty + */ + Set listConfigurationEntries(ListConfigurationEntriesOptions... options); + +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListConfigurationEntriesOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListConfigurationEntriesOptions.java new file mode 100644 index 0000000000..1f585ae529 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListConfigurationEntriesOptions.java @@ -0,0 +1,115 @@ +/** + * 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 configuration entries are returned + * + * @see + * @author Andrei Savu + */ +public class ListConfigurationEntriesOptions extends BaseHttpRequestOptions { + + public static final ListConfigurationEntriesOptions NONE = new ListConfigurationEntriesOptions(); + + /** + * @param category + * list by category name + */ + public ListConfigurationEntriesOptions category(String category) { + this.queryParameters.replaceValues("category", ImmutableSet.of(category)); + return this; + } + + /** + * @param keyword + * list by keyword + */ + public ListConfigurationEntriesOptions keyword(String keyword) { + this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword)); + return this; + } + + /** + * @param name + * list by entry name + */ + public ListConfigurationEntriesOptions name(String name) { + this.queryParameters.replaceValues("name", ImmutableSet.of(name)); + return this; + } + + public ListConfigurationEntriesOptions page(long page) { + this.queryParameters.replaceValues("page", ImmutableSet.of(page + "")); + return this; + } + + public ListConfigurationEntriesOptions pageSize(long pageSize) { + this.queryParameters.replaceValues("pagesize", ImmutableSet.of(pageSize + "")); + return this; + } + + public static class Builder { + + /** + * @see ListConfigurationEntriesOptions#category + */ + public static ListConfigurationEntriesOptions category(String category) { + ListConfigurationEntriesOptions options = new ListConfigurationEntriesOptions(); + return options.category(category); + } + + /** + * @see ListConfigurationEntriesOptions#keyword + */ + public static ListConfigurationEntriesOptions keyword(String keyword) { + ListConfigurationEntriesOptions options = new ListConfigurationEntriesOptions(); + return options.keyword(keyword); + } + + /** + * @see ListConfigurationEntriesOptions#name + */ + public static ListConfigurationEntriesOptions name(String name) { + ListConfigurationEntriesOptions options = new ListConfigurationEntriesOptions(); + return options.name(name); + } + + /** + * @see ListConfigurationEntriesOptions#page + */ + public static ListConfigurationEntriesOptions page(long page) { + ListConfigurationEntriesOptions options = new ListConfigurationEntriesOptions(); + return options.page(page); + } + + /** + * @see ListConfigurationEntriesOptions#pageSize + */ + public static ListConfigurationEntriesOptions pageSize(long pageSize) { + ListConfigurationEntriesOptions options = new ListConfigurationEntriesOptions(); + return options.pageSize(pageSize); + } + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java new file mode 100644 index 0000000000..9133e4c113 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.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 com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.CloudStackClient; +import org.jclouds.cloudstack.CloudStackGlobalClient; +import org.jclouds.cloudstack.domain.AsyncCreateResponse; +import org.jclouds.cloudstack.domain.ConfigurationEntry; +import org.jclouds.cloudstack.domain.FirewallRule; +import org.jclouds.cloudstack.domain.PortForwardingRule; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.BaseRestClientExpectTest; +import org.testng.annotations.Test; + +import java.net.URI; +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * Test the CloudStack GlobalConfigurationClient + * + * @author Andrei Savu + */ +@Test(groups = "unit", testName = "GlobalConfigurationClientExpectTest") +public class GlobalConfigurationClientExpectTest extends BaseRestClientExpectTest { + + public GlobalConfigurationClientExpectTest() { + provider = "cloudstack"; + } + + @Test(enabled = false) + public void testListConfigurationEntriesWhenResponseIs2xx() { + GlobalConfigurationClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&command=listFirewallRules&" + + "apiKey=identity&signature=MktZKKH3USVKiC9SlYTSHMCaCcg%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/listconfigurationsresponse.json")) + .build()) + .getConfigurationClient(); + + assertEquals(client.listConfigurationEntries(), + ImmutableSet.of( + ConfigurationEntry.builder().category("Advanced").name("account.cleanup.interval").value("86400") + .description("The interval (in seconds) between cleanup for removed accounts").build(), + ConfigurationEntry.builder().category("Advanced").name("agent.lb.enabled").value("true") + .description("If agent load balancing enabled in cluster setup").build() + )); + } +} \ No newline at end of file diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java new file mode 100644 index 0000000000..89810cbd2f --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java @@ -0,0 +1,58 @@ +/** + * 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.ImmutableSet; +import org.jclouds.cloudstack.domain.ConfigurationEntry; +import org.testng.annotations.Test; +import org.testng.collections.Sets; + +import java.util.Set; + +/** + * Tests behavior of {@code GlobalConfigurationClient} + * + * @author Andrei Savu + */ +@Test(groups = "live", singleThreaded = true, testName = "GlobalConfigurationClientLiveTest") +public class GlobalConfigurationClientLiveTest extends BaseCloudStackClientLiveTest { + + @Test + public void testListConfigurationEntries() { + assert globalAdminEnabled; + + Set entries = globalAdminClient + .getConfigurationClient().listConfigurationEntries(); + + Set categories = Sets.newHashSet(); + for(ConfigurationEntry entry : entries) { + checkConfigurationEntry(entry); + categories.add(entry.getCategory()); + } + + assert categories.containsAll(ImmutableSet.of("Network", "Advanced", "Premium", + "Storage", "Usage", "Snapshots", "Account Defaults", "Console Proxy", "Alert")); + } + + private void checkConfigurationEntry(ConfigurationEntry entry) { + assert entry.getCategory() != null : entry; + assert entry.getDescription() != null : entry; + assert entry.getName() != null : entry; + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListConfigurationEntriesResponseTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListConfigurationEntriesResponseTest.java new file mode 100644 index 0000000000..0a734a98a0 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/parse/ListConfigurationEntriesResponseTest.java @@ -0,0 +1,69 @@ +/** + * 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.ConfigurationEntry; +import org.jclouds.cloudstack.domain.FirewallRule; +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 ListConfigurationEntriesResponseTest 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 "/listconfigurationsresponse.json"; + } + + @Override + @SelectJson("configuration") + public Set expected() { + return ImmutableSet.of( + ConfigurationEntry.builder().category("Advanced").name("account.cleanup.interval").value("86400") + .description("The interval (in seconds) between cleanup for removed accounts").build(), + ConfigurationEntry.builder().category("Advanced").name("agent.lb.enabled").value("true") + .description("If agent load balancing enabled in cluster setup").build() + ); + } + +} diff --git a/apis/cloudstack/src/test/resources/listconfigurationsresponse.json b/apis/cloudstack/src/test/resources/listconfigurationsresponse.json new file mode 100644 index 0000000000..25bc7a189a --- /dev/null +++ b/apis/cloudstack/src/test/resources/listconfigurationsresponse.json @@ -0,0 +1,4 @@ +{ "listconfigurationsresponse" : { "count":2 ,"configuration" : [ + {"category":"Advanced","name":"account.cleanup.interval","value":"86400","description":"The interval (in seconds) between cleanup for removed accounts"}, + {"category":"Advanced","name":"agent.lb.enabled","value":"true","description":"If agent load balancing enabled in cluster setup"}] +}} \ No newline at end of file From 00e7657a09552f426eb27b898361d86bc5a8e289 Mon Sep 17 00:00:00 2001 From: andreisavu Date: Wed, 11 Jan 2012 01:49:12 +0200 Subject: [PATCH 2/5] Implemented update & create configuration APIs --- .../GlobalConfigurationAsyncClient.java | 28 +++++++++ .../features/GlobalConfigurationClient.java | 32 +++++++++++ .../GlobalConfigurationClientLiveTest.java | 57 ++++++++++++++++++- 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java index 7af26740f8..29db91101d 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java @@ -23,13 +23,16 @@ import org.jclouds.cloudstack.domain.ConfigurationEntry; import org.jclouds.cloudstack.filters.QuerySigner; import org.jclouds.cloudstack.options.ListConfigurationEntriesOptions; 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; @@ -56,4 +59,29 @@ public interface GlobalConfigurationAsyncClient extends ConfigurationAsyncClient @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) ListenableFuture> listConfigurationEntries(ListConfigurationEntriesOptions... options); + /** + * @see GlobalConfigurationClient#updateConfigurationEntry + */ + @GET + @QueryParams(keys = "command", values = "updateConfiguration") + @SelectJson("configuration") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture updateConfigurationEntry( + @QueryParam("name") String name, @QueryParam("value") String value); + + + /** + * @see GlobalConfigurationClient#createConfigurationEntry + */ + @GET + @QueryParams(keys = "command", values = "createConfiguration") + @SelectJson("configuration") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture createConfigurationEntry(@QueryParam("category")String category, + @QueryParam("component") String component, @QueryParam("instance") String instance, + @QueryParam("name") String name, @QueryParam("description") String description, + @QueryParam("value") String value); + } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java index e9783eb795..c77b7d5526 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java @@ -47,4 +47,36 @@ public interface GlobalConfigurationClient extends ConfigurationClient { */ Set listConfigurationEntries(ListConfigurationEntriesOptions... options); + /** + * Update a configuration entry + * + * @param name + * the name of the configuration + * @param value + * the value of the configuration + * @return + * the updated configuration value + */ + ConfigurationEntry updateConfigurationEntry(String name, String value); + + /** + * Create a new configuration value + * + * @param category + * the component category + * @param component + * the component of the configuration + * @param instance + * the instance of the configuration + * @param name + * the name of the configuration + * @param description + * the description of the configuration + * @param value + * the value of the configuration + * @return + */ + ConfigurationEntry createConfigurationEntry(String category, String component, + String instance, String name, String description, String value ); + } diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java index 89810cbd2f..8ca75d8bcc 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java @@ -18,13 +18,22 @@ */ package org.jclouds.cloudstack.features; +import com.google.common.base.Objects; +import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import org.jclouds.cloudstack.domain.ConfigurationEntry; import org.testng.annotations.Test; import org.testng.collections.Sets; +import javax.annotation.Nullable; import java.util.Set; +import static com.google.common.collect.Iterables.getOnlyElement; +import static org.jclouds.cloudstack.options.ListConfigurationEntriesOptions.Builder.name; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + /** * Tests behavior of {@code GlobalConfigurationClient} * @@ -41,7 +50,7 @@ public class GlobalConfigurationClientLiveTest extends BaseCloudStackClientLiveT .getConfigurationClient().listConfigurationEntries(); Set categories = Sets.newHashSet(); - for(ConfigurationEntry entry : entries) { + for (ConfigurationEntry entry : entries) { checkConfigurationEntry(entry); categories.add(entry.getCategory()); } @@ -50,9 +59,55 @@ public class GlobalConfigurationClientLiveTest extends BaseCloudStackClientLiveT "Storage", "Usage", "Snapshots", "Account Defaults", "Console Proxy", "Alert")); } + @Test + public void testUpdateConfigurationEntry() { + assert globalAdminEnabled; + + Set entries = globalAdminClient + .getConfigurationClient().listConfigurationEntries(); + + long expungeDelay = Long.parseLong(getValueByName(entries, "expunge.delay")); + assert expungeDelay > 0; + + globalAdminClient.getConfigurationClient() + .updateConfigurationEntry("expunge.delay", "" + (expungeDelay + 1)); + + long newDelay = Long.parseLong(getOnlyElement(globalAdminClient.getConfigurationClient() + .listConfigurationEntries(name("expunge.delay"))).getValue()); + assertEquals(newDelay, expungeDelay + 1); + + globalAdminClient.getConfigurationClient() + .updateConfigurationEntry("expunge.delay", "" + expungeDelay); + } + + @Test(enabled = false) + public void testCreateConfigurationEntry() { + assert globalAdminEnabled; + + ConfigurationEntry result = globalAdminClient.getConfigurationClient() + .createConfigurationEntry("Advanced", "component", + "instance", prefix + "-jclouds", "description", "jclouds"); + checkConfigurationEntry(result); + } + private void checkConfigurationEntry(ConfigurationEntry entry) { + assertEquals(entry, getEntryByName(globalAdminClient.getConfigurationClient() + .listConfigurationEntries(), entry.getName())); assert entry.getCategory() != null : entry; assert entry.getDescription() != null : entry; assert entry.getName() != null : entry; } + + private String getValueByName(Set entries, String name) { + return getEntryByName(entries, name).getValue(); + } + + private ConfigurationEntry getEntryByName(Set entries, final String name) { + return Iterables.find(entries, new Predicate() { + @Override + public boolean apply(@Nullable ConfigurationEntry entry) { + return entry != null && Objects.equal(name, entry.getName()); + } + }); + } } From 77ebfe8f1e6c766eb2774bf3dd24d185ae10f51e Mon Sep 17 00:00:00 2001 From: andreisavu Date: Wed, 11 Jan 2012 02:06:18 +0200 Subject: [PATCH 3/5] Removed create configuration API call - not useful --- .../GlobalConfigurationAsyncClient.java | 17 +-------------- .../features/GlobalConfigurationClient.java | 21 ------------------- .../GlobalConfigurationClientLiveTest.java | 13 +----------- 3 files changed, 2 insertions(+), 49 deletions(-) diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java index 29db91101d..21212e3812 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationAsyncClient.java @@ -69,19 +69,4 @@ public interface GlobalConfigurationAsyncClient extends ConfigurationAsyncClient @ExceptionParser(ReturnNullOnNotFoundOr404.class) ListenableFuture updateConfigurationEntry( @QueryParam("name") String name, @QueryParam("value") String value); - - - /** - * @see GlobalConfigurationClient#createConfigurationEntry - */ - @GET - @QueryParams(keys = "command", values = "createConfiguration") - @SelectJson("configuration") - @Consumes(MediaType.APPLICATION_JSON) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture createConfigurationEntry(@QueryParam("category")String category, - @QueryParam("component") String component, @QueryParam("instance") String instance, - @QueryParam("name") String name, @QueryParam("description") String description, - @QueryParam("value") String value); - -} +} \ No newline at end of file diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java index c77b7d5526..1b03c439a2 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalConfigurationClient.java @@ -58,25 +58,4 @@ public interface GlobalConfigurationClient extends ConfigurationClient { * the updated configuration value */ ConfigurationEntry updateConfigurationEntry(String name, String value); - - /** - * Create a new configuration value - * - * @param category - * the component category - * @param component - * the component of the configuration - * @param instance - * the instance of the configuration - * @param name - * the name of the configuration - * @param description - * the description of the configuration - * @param value - * the value of the configuration - * @return - */ - ConfigurationEntry createConfigurationEntry(String category, String component, - String instance, String name, String description, String value ); - } diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java index 8ca75d8bcc..2ad890f518 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientLiveTest.java @@ -32,7 +32,6 @@ import java.util.Set; import static com.google.common.collect.Iterables.getOnlyElement; import static org.jclouds.cloudstack.options.ListConfigurationEntriesOptions.Builder.name; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; /** * Tests behavior of {@code GlobalConfigurationClient} @@ -80,19 +79,9 @@ public class GlobalConfigurationClientLiveTest extends BaseCloudStackClientLiveT .updateConfigurationEntry("expunge.delay", "" + expungeDelay); } - @Test(enabled = false) - public void testCreateConfigurationEntry() { - assert globalAdminEnabled; - - ConfigurationEntry result = globalAdminClient.getConfigurationClient() - .createConfigurationEntry("Advanced", "component", - "instance", prefix + "-jclouds", "description", "jclouds"); - checkConfigurationEntry(result); - } - private void checkConfigurationEntry(ConfigurationEntry entry) { assertEquals(entry, getEntryByName(globalAdminClient.getConfigurationClient() - .listConfigurationEntries(), entry.getName())); + .listConfigurationEntries(name(entry.getName())), entry.getName())); assert entry.getCategory() != null : entry; assert entry.getDescription() != null : entry; assert entry.getName() != null : entry; From 7c4603f44a56b1ba5d14bdf1d4bac64829089508 Mon Sep 17 00:00:00 2001 From: andreisavu Date: Wed, 11 Jan 2012 02:18:35 +0200 Subject: [PATCH 4/5] Re-enabled the failing Expect test --- .../features/GlobalConfigurationClientExpectTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java index 9133e4c113..25aba8d71a 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java @@ -49,7 +49,7 @@ public class GlobalConfigurationClientExpectTest extends BaseRestClientExpectTes provider = "cloudstack"; } - @Test(enabled = false) + @Test public void testListConfigurationEntriesWhenResponseIs2xx() { GlobalConfigurationClient client = requestSendsResponse( HttpRequest.builder() From a752ecbb989f46340a360dca94f1877404733077 Mon Sep 17 00:00:00 2001 From: andreisavu Date: Wed, 11 Jan 2012 03:35:30 +0200 Subject: [PATCH 5/5] Added missing Expect test cases --- .../GlobalConfigurationClientExpectTest.java | 86 +++++++++++++++++-- .../updateconfigurationsresponse.json | 2 + 2 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 apis/cloudstack/src/test/resources/updateconfigurationsresponse.json diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java index 25aba8d71a..913f0219fa 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalConfigurationClientExpectTest.java @@ -21,6 +21,7 @@ package org.jclouds.cloudstack.features; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import org.jclouds.cloudstack.CloudStackClient; +import org.jclouds.cloudstack.CloudStackContext; import org.jclouds.cloudstack.CloudStackGlobalClient; import org.jclouds.cloudstack.domain.AsyncCreateResponse; import org.jclouds.cloudstack.domain.ConfigurationEntry; @@ -43,11 +44,7 @@ import static org.testng.Assert.assertNull; * @author Andrei Savu */ @Test(groups = "unit", testName = "GlobalConfigurationClientExpectTest") -public class GlobalConfigurationClientExpectTest extends BaseRestClientExpectTest { - - public GlobalConfigurationClientExpectTest() { - provider = "cloudstack"; - } +public class GlobalConfigurationClientExpectTest extends BaseCloudStackRestClientExpectTest { @Test public void testListConfigurationEntriesWhenResponseIs2xx() { @@ -55,8 +52,8 @@ public class GlobalConfigurationClientExpectTest extends BaseRestClientExpectTes HttpRequest.builder() .method("GET") .endpoint( - URI.create("http://localhost:8080/client/api?response=json&command=listFirewallRules&" + - "apiKey=identity&signature=MktZKKH3USVKiC9SlYTSHMCaCcg%3D")) + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listConfigurations&apiKey=identity&signature=FUQCDbc4TH2S%2B7ExDgrOCqKI2bw%3D")) .headers( ImmutableMultimap.builder() .put("Accept", "application/json") @@ -65,8 +62,7 @@ public class GlobalConfigurationClientExpectTest extends BaseRestClientExpectTes HttpResponse.builder() .statusCode(200) .payload(payloadFromResource("/listconfigurationsresponse.json")) - .build()) - .getConfigurationClient(); + .build()); assertEquals(client.listConfigurationEntries(), ImmutableSet.of( @@ -76,4 +72,76 @@ public class GlobalConfigurationClientExpectTest extends BaseRestClientExpectTes .description("If agent load balancing enabled in cluster setup").build() )); } + + @Test + public void testListConfigurationEntriesEmptyOn404() { + GlobalConfigurationClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listConfigurations&apiKey=identity&signature=FUQCDbc4TH2S%2B7ExDgrOCqKI2bw%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertEquals(client.listConfigurationEntries(), ImmutableSet.of()); + } + + @Test + public void testUpdateConfigurationEntryWhenResponseIs2xx() { + GlobalConfigurationClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=updateConfiguration&name=expunge.delay&value=11&" + + "apiKey=identity&signature=I2yG35EhfgIXYObeLfU3cvf%2BPeE%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/updateconfigurationsresponse.json")) + .build()); + + assertEquals(client.updateConfigurationEntry("expunge.delay", "11"), + ConfigurationEntry.builder().category("Advanced").name("expunge.delay").value("11") + .description("Determines how long (in seconds) to wait before actually expunging " + + "destroyed vm. The default value = the default value of expunge.interval").build() + ); + } + + @Test + public void testUpdateConfigurationEntryNullOn404() { + GlobalConfigurationClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=updateConfiguration&name=expunge.delay&value=11&" + + "apiKey=identity&signature=I2yG35EhfgIXYObeLfU3cvf%2BPeE%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertNull(client.updateConfigurationEntry("expunge.delay", "11")); + } + + @Override + protected GlobalConfigurationClient clientFrom(CloudStackContext context) { + return context.getGlobalContext().getApi().getConfigurationClient(); + } } \ No newline at end of file diff --git a/apis/cloudstack/src/test/resources/updateconfigurationsresponse.json b/apis/cloudstack/src/test/resources/updateconfigurationsresponse.json new file mode 100644 index 0000000000..6013bd559d --- /dev/null +++ b/apis/cloudstack/src/test/resources/updateconfigurationsresponse.json @@ -0,0 +1,2 @@ +{ "updateconfigurationresponse" : { "configuration" : + {"category":"Advanced","name":"expunge.delay","value":"11","description":"Determines how long (in seconds) to wait before actually expunging destroyed vm. The default value = the default value of expunge.interval"} } } \ No newline at end of file