Added SearchOptions to all search methods

Added a SearchOptions parameter to all search
methods in ChefApi. This way every search can be
customized and limited. Fixes #1.

This is still a WIP until the appropriate live tests
are added.
This commit is contained in:
Ignasi Barrera 2012-09-29 16:27:32 +02:00
parent c82de486dc
commit 4c6e48fc47
6 changed files with 252 additions and 25 deletions

View File

@ -34,6 +34,7 @@ import org.jclouds.chef.domain.Sandbox;
import org.jclouds.chef.domain.SearchResult;
import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.chef.options.SearchOptions;
import org.jclouds.concurrent.Timeout;
import org.jclouds.http.HttpResponseException;
import org.jclouds.io.Payload;
@ -530,9 +531,18 @@ public interface ChefApi {
* and the rows themselves.
*/
SearchResult<? extends Role> searchRoles();
/**
* search all roles that match the given options.
*
* @return The response contains the total number of rows that matched your
* request, the position this result set returns (useful for paging)
* and the rows themselves.
*/
SearchResult<? extends Role> searchRoles(SearchOptions options);
/**
* search all apis.
* search all clients.
* <p/>
* Note that without any request parameters this will return all of the data
* within the index.
@ -542,6 +552,15 @@ public interface ChefApi {
* and the rows themselves.
*/
SearchResult<? extends Client> searchClients();
/**
* search all clients that match the given options.
*
* @return The response contains the total number of rows that matched your
* request, the position this result set returns (useful for paging)
* and the rows themselves.
*/
SearchResult<? extends Client> searchClients(SearchOptions options);
/**
* search all nodes.
@ -554,19 +573,15 @@ public interface ChefApi {
* and the rows themselves.
*/
SearchResult<? extends Node> searchNodes();
/**
* search all nodes that match the query parameter.
* <p/>
* Note that without any request parameters this will return all of the data
* within the index.
* search all nodes that match the given options.
*
* @return The response contains the total number of rows that matched your
* request, the position this result set returns (useful for paging)
* and the rows themselves.
*/
SearchResult<? extends Node> searchNodes(String qeury);
SearchResult<? extends Node> searchNodes(SearchOptions options);
/**
* search all items in a databag.
@ -579,6 +594,15 @@ public interface ChefApi {
* and the rows themselves.
*/
SearchResult<? extends DatabagItem> searchDatabag(String databagName);
/**
* search all items in a databag that match the given options.
*
* @return The response contains the total number of rows that matched your
* request, the position this result set returns (useful for paging)
* and the rows themselves.
*/
SearchResult<? extends DatabagItem> searchDatabag(String databagName, SearchOptions options);
/**
* Get the contents of the given resource.

View File

@ -29,7 +29,6 @@ import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.QueryParam;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@ -63,6 +62,7 @@ import org.jclouds.chef.functions.ParseSearchNodesFromJson;
import org.jclouds.chef.functions.ParseSearchRolesFromJson;
import org.jclouds.chef.functions.UriForResource;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.chef.options.SearchOptions;
import org.jclouds.io.Payload;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
@ -416,6 +416,14 @@ public interface ChefAsyncApi {
@Path("/search/role")
@ResponseParser(ParseSearchRolesFromJson.class)
ListenableFuture<? extends SearchResult<? extends Role>> searchRoles();
/**
* @see ChefApi#searchRoles(SearchOptions)
*/
@GET
@Path("/search/role")
@ResponseParser(ParseSearchRolesFromJson.class)
ListenableFuture<? extends SearchResult<? extends Role>> searchRoles(SearchOptions options);
/**
* @see ChefApi#searchClients()
@ -424,6 +432,14 @@ public interface ChefAsyncApi {
@Path("/search/client")
@ResponseParser(ParseSearchClientsFromJson.class)
ListenableFuture<? extends SearchResult<? extends Client>> searchClients();
/**
* @see ChefApi#searchClients(SearchOptions)
*/
@GET
@Path("/search/client")
@ResponseParser(ParseSearchClientsFromJson.class)
ListenableFuture<? extends SearchResult<? extends Client>> searchClients(SearchOptions options);
/**
* @see ChefApi#searchNodes()
@ -432,14 +448,14 @@ public interface ChefAsyncApi {
@Path("/search/node")
@ResponseParser(ParseSearchNodesFromJson.class)
ListenableFuture<? extends SearchResult<? extends Node>> searchNodes();
/**
* @see ChefApi#searchNodes(String)
* @see ChefApi#searchNodes(SearchOptions)
*/
@GET
@Path("/search/node")
@ResponseParser(ParseSearchNodesFromJson.class)
ListenableFuture<? extends SearchResult<? extends Node>> searchNodes(@QueryParam("q") String query);
ListenableFuture<? extends SearchResult<? extends Node>> searchNodes(SearchOptions options);
/**
* @see ChefApi#searchDatabag(String)
@ -450,6 +466,15 @@ public interface ChefAsyncApi {
ListenableFuture<? extends SearchResult<? extends DatabagItem>> searchDatabag(
@PathParam("databagName") String databagName);
/**
* @see ChefApi#searchDatabag(String, SearchOptions)
*/
@GET
@Path("/search/{databagName}")
@ResponseParser(ParseSearchDatabagFromJson.class)
ListenableFuture<? extends SearchResult<? extends DatabagItem>> searchDatabag(
@PathParam("databagName") String databagName, SearchOptions options);
/**
* @see ChefApi#getResourceContents(Resource)
*/

View File

@ -199,11 +199,16 @@ public class BaseChefService implements ChefService {
} catch (IllegalStateException e) {
}
chefContext.getApi().updateDatabagItem(
databag,
new DatabagItem(group, chefContext.utils().json().toJson(
ImmutableMap.<String, List<String>> of("run_list", Lists.newArrayList(runList)),
RunListForGroup.RUN_LIST_TYPE)));
DatabagItem runlist = new DatabagItem(group, chefContext.utils().json().toJson(
ImmutableMap.<String, List<String>> of("run_list", Lists.newArrayList(runList)),
RunListForGroup.RUN_LIST_TYPE));
if (chefContext.getApi().getDatabagItem(databag, group) == null) {
chefContext.getApi().createDatabagItem(databag, runlist);
} else {
chefContext.getApi().updateDatabagItem(databag, runlist);
}
}
@Override

View File

@ -0,0 +1,99 @@
/**
* 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.chef.options;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Options for the search api.
*
* @author Ignasi Barrera
*/
public class SearchOptions extends BaseHttpRequestOptions {
/**
* A valid search string.
*/
public SearchOptions query(String query) {
this.queryParameters.put("q", checkNotNull(query, "query"));
return this;
}
/**
* A sort string, such as 'name DESC'.
*/
public SearchOptions sort(String sort) {
this.queryParameters.put("sort", checkNotNull(sort, "sort"));
return this;
}
/**
* The number of rows to return.
*/
public SearchOptions rows(int rows) {
this.queryParameters.put("rows", String.valueOf(rows));
return this;
}
/**
* The result number to start from.
*/
public SearchOptions start(int start) {
this.queryParameters.put("start", String.valueOf(start));
return this;
}
public static class Builder {
/**
* @see SearchOptions#query(String)
*/
public static SearchOptions query(String query) {
SearchOptions options = new SearchOptions();
return options.query(query);
}
/**
* @see SearchOptions#sort(String)
*/
public static SearchOptions start(String start) {
SearchOptions options = new SearchOptions();
return options.sort(start);
}
/**
* @see SearchOptions#rows(int)
*/
public static SearchOptions rows(int rows) {
SearchOptions options = new SearchOptions();
return options.rows(rows);
}
/**
* @see SearchOptions#start(int)
*/
public static SearchOptions start(int start) {
SearchOptions options = new SearchOptions();
return options.start(start);
}
}
}

View File

@ -51,6 +51,7 @@ import org.jclouds.chef.domain.Sandbox;
import org.jclouds.chef.domain.SearchResult;
import org.jclouds.chef.domain.UploadSandbox;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.chef.options.SearchOptions;
import org.jclouds.io.Payload;
import org.jclouds.util.Strings2;
@ -286,11 +287,23 @@ public class TransientChefAsyncApi implements ChefAsyncApi {
public ListenableFuture<? extends SearchResult<? extends Client>> searchClients() {
throw new UnsupportedOperationException();
}
@Override
public ListenableFuture<? extends SearchResult<? extends Client>> searchClients(
SearchOptions options) {
throw new UnsupportedOperationException();
}
@Override
public ListenableFuture<? extends SearchResult<? extends DatabagItem>> searchDatabag(String databagName) {
throw new UnsupportedOperationException();
}
@Override
public ListenableFuture<? extends SearchResult<? extends DatabagItem>> searchDatabag(
String databagName, SearchOptions options) {
throw new UnsupportedOperationException();
}
@Override
public ListenableFuture<? extends SearchResult<? extends Node>> searchNodes() {
@ -298,14 +311,21 @@ public class TransientChefAsyncApi implements ChefAsyncApi {
}
@Override
public ListenableFuture<? extends SearchResult<? extends Node>> searchNodes(String query) {
throw new UnsupportedOperationException();
}
public ListenableFuture<? extends SearchResult<? extends Node>> searchNodes(
SearchOptions options) {
throw new UnsupportedOperationException();
}
@Override
public ListenableFuture<? extends SearchResult<? extends Role>> searchRoles() {
throw new UnsupportedOperationException();
}
@Override
public ListenableFuture<? extends SearchResult<? extends Role>> searchRoles(
SearchOptions options) {
throw new UnsupportedOperationException();
}
@Override
public ListenableFuture<CookbookVersion> updateCookbook(String cookbookName, String version, CookbookVersion cookbook) {

View File

@ -44,6 +44,7 @@ import org.jclouds.chef.functions.ParseSearchDatabagFromJson;
import org.jclouds.chef.functions.ParseSearchNodesFromJson;
import org.jclouds.chef.functions.ParseSearchRolesFromJson;
import org.jclouds.chef.options.CreateClientOptions;
import org.jclouds.chef.options.SearchOptions;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpRequest;
@ -715,6 +716,23 @@ public class ChefAsyncApiTest extends BaseAsyncApiTest<ChefAsyncApi> {
checkFilters(httpRequest);
}
public void testSearchRolesWithOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncApi.class.getMethod("searchRoles", SearchOptions.class);
GeneratedHttpRequest httpRequest = processor.createRequest(method,
SearchOptions.Builder.query("text"));
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/role?q=text HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefAsyncApi.VERSION + "-test\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseSearchRolesFromJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
public void testSearchClients() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncApi.class.getMethod("searchClients");
@ -731,6 +749,23 @@ public class ChefAsyncApiTest extends BaseAsyncApiTest<ChefAsyncApi> {
checkFilters(httpRequest);
}
public void testSearchClientsWithOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncApi.class.getMethod("searchClients", SearchOptions.class);
GeneratedHttpRequest httpRequest = processor.createRequest(method,
SearchOptions.Builder.query("text").rows(5));
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/client?q=text&rows=5 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefAsyncApi.VERSION + "-test\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseSearchClientsFromJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
public void testSearchNodes() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncApi.class.getMethod("searchNodes");
@ -747,12 +782,13 @@ public class ChefAsyncApiTest extends BaseAsyncApiTest<ChefAsyncApi> {
checkFilters(httpRequest);
}
public void testSearchNodesWithOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncApi.class.getMethod("searchNodes", SearchOptions.class);
GeneratedHttpRequest httpRequest = processor.createRequest(method,
SearchOptions.Builder.query("foo:foo").start(3));
public void testSearchNodesQuery() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncApi.class.getMethod("searchNodes", String.class);
GeneratedHttpRequest httpRequest = processor.createRequest(method, "foo:foo");
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/node?q=foo%3Afoo HTTP/1.1");
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/node?q=foo%3Afoo&start=3 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefAsyncApi.VERSION + "-test\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -764,6 +800,7 @@ public class ChefAsyncApiTest extends BaseAsyncApiTest<ChefAsyncApi> {
}
public void testSearchDatabag() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncApi.class.getMethod("searchDatabag", String.class);
GeneratedHttpRequest httpRequest = processor.createRequest(method, "foo");
@ -780,6 +817,23 @@ public class ChefAsyncApiTest extends BaseAsyncApiTest<ChefAsyncApi> {
}
public void testSearchDatabagWithOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncApi.class.getMethod("searchDatabag", String.class, SearchOptions.class);
GeneratedHttpRequest httpRequest = processor.createRequest(method, "foo",
SearchOptions.Builder.query("bar").sort("name DESC"));
assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/foo?q=bar&sort=name%20DESC HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefAsyncApi.VERSION + "-test\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseSearchDatabagFromJson.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
public void testGetResourceContents() throws SecurityException, NoSuchMethodException, IOException {
Method method = ChefAsyncApi.class.getMethod("getResourceContents", Resource.class);
GeneratedHttpRequest httpRequest = processor.createRequest(method,