Skip to content

Commit

Permalink
Merge pull request #651 from ajkannan/resourcemanager-page
Browse files Browse the repository at this point in the history
Support paging in Resource Manager
  • Loading branch information
aozarov committed Feb 18, 2016
2 parents 1dd2c04 + b9cd1a7 commit da544a9
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,6 @@ public static ProjectListOption pageToken(String pageToken) {
*
* <p>The server can return fewer projects than requested. When there are more results than the
* page size, the server will return a page token that can be used to fetch other results.
* Note: pagination is not yet supported; the server currently ignores this field and returns
* all results.
*/
public static ProjectListOption pageSize(int pageSize) {
return new ProjectListOption(ResourceManagerRpc.Option.PAGE_SIZE, pageSize);
Expand Down Expand Up @@ -228,8 +226,7 @@ public static ProjectListOption fields(ProjectField... fields) {
*
* <p>This method returns projects in an unspecified order. New projects do not necessarily appear
* at the end of the list. Use {@link ProjectListOption} to filter this list, set page size, and
* set page tokens. Note that pagination is currently not implemented by the Cloud Resource
* Manager API.
* set page tokens.
*
* @see <a
* href="https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects/list">Cloud
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
Expand Down Expand Up @@ -71,7 +71,7 @@ public class LocalResourceManagerHelper {
ImmutableSet.of('-', '\'', '"', ' ', '!');

private final HttpServer server;
private final ConcurrentHashMap<String, Project> projects = new ConcurrentHashMap<>();
private final ConcurrentSkipListMap<String, Project> projects = new ConcurrentSkipListMap<>();
private final int port;

private static class Response {
Expand Down Expand Up @@ -228,7 +228,7 @@ private static String[] parseFields(String query) {
return null;
}

private static Map<String, Object> parseListOptions(String query) {
private static Map<String, Object> parseListOptions(String query) throws IOException {
Map<String, Object> options = new HashMap<>();
if (query != null) {
String[] args = query.split("&");
Expand All @@ -245,10 +245,14 @@ private static Map<String, Object> parseListOptions(String query) {
options.put("filter", argEntry[1].split(" "));
break;
case "pageToken":
// support pageToken when Cloud Resource Manager supports this (#421)
options.put("pageToken", argEntry[1]);
break;
case "pageSize":
// support pageSize when Cloud Resource Manager supports this (#421)
int pageSize = Integer.valueOf(argEntry[1]);
if (pageSize < 1) {
throw new IOException("Page size must be greater than 0.");
}
options.put("pageSize", pageSize);
break;
}
}
Expand Down Expand Up @@ -353,16 +357,28 @@ Response get(String projectId, String[] fields) {
}

Response list(Map<String, Object> options) {
// Use pageSize and pageToken options when Cloud Resource Manager does so (#421)
List<String> projectsSerialized = new ArrayList<>();
String[] filters = (String[]) options.get("filter");
if (filters != null && !isValidFilter(filters)) {
return Error.INVALID_ARGUMENT.response("Could not parse the filter.");
}
String[] fields = (String[]) options.get("fields");
for (Project p : projects.values()) {
int count = 0;
String pageToken = (String) options.get("pageToken");
Integer pageSize = (Integer) options.get("pageSize");
String nextPageToken = null;
Map<String, Project> projectsToScan = projects;
if (pageToken != null) {
projectsToScan = projects.tailMap(pageToken);
}
for (Project p : projectsToScan.values()) {
if (pageSize != null && count >= pageSize) {
nextPageToken = p.getProjectId();
break;
}
boolean includeProject = includeProject(p, filters);
if (includeProject) {
count++;
try {
projectsSerialized.add(jsonFactory.toString(extractFields(p, fields)));
} catch (IOException e) {
Expand All @@ -374,7 +390,13 @@ Response list(Map<String, Object> options) {
StringBuilder responseBody = new StringBuilder();
responseBody.append("{\"projects\": [");
Joiner.on(",").appendTo(responseBody, projectsSerialized);
responseBody.append("]}");
responseBody.append(']');
if (nextPageToken != null) {
responseBody.append(", \"nextPageToken\": \"");
responseBody.append(nextPageToken);
responseBody.append('"');
}
responseBody.append('}');
return new Response(HTTP_OK, responseBody.toString());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.junit.Test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class LocalResourceManagerHelperTest {
Expand Down Expand Up @@ -278,7 +279,7 @@ public void testGetWithOptions() {
public void testList() {
Tuple<String, Iterable<com.google.api.services.cloudresourcemanager.model.Project>> projects =
rpc.list(EMPTY_RPC_OPTIONS);
assertNull(projects.x()); // change this when #421 is resolved
assertNull(projects.x());
assertFalse(projects.y().iterator().hasNext());
rpc.create(COMPLETE_PROJECT);
RESOURCE_MANAGER_HELPER.changeLifecycleState(
Expand All @@ -296,12 +297,43 @@ public void testList() {
}
}

@Test
public void testInvalidListPaging() {
Map<ResourceManagerRpc.Option, Object> rpcOptions = new HashMap<>();
rpcOptions.put(ResourceManagerRpc.Option.PAGE_SIZE, -1);
try {
rpc.list(rpcOptions);
} catch (ResourceManagerException e) {
assertEquals("Page size must be greater than 0.", e.getMessage());
}
}

@Test
public void testListPaging() {
Map<ResourceManagerRpc.Option, Object> rpcOptions = new HashMap<>();
rpcOptions.put(ResourceManagerRpc.Option.PAGE_SIZE, 1);
rpc.create(PARTIAL_PROJECT);
rpc.create(COMPLETE_PROJECT);
Tuple<String, Iterable<com.google.api.services.cloudresourcemanager.model.Project>> projects =
rpc.list(rpcOptions);
assertNotNull(projects.x());
Iterator<com.google.api.services.cloudresourcemanager.model.Project> iterator =
projects.y().iterator();
compareReadWriteFields(COMPLETE_PROJECT, iterator.next());
assertFalse(iterator.hasNext());
rpcOptions = new HashMap<>();
rpcOptions.put(ResourceManagerRpc.Option.PAGE_TOKEN, projects.x());
projects = rpc.list(rpcOptions);
iterator = projects.y().iterator();
compareReadWriteFields(PARTIAL_PROJECT, iterator.next());
assertFalse(iterator.hasNext());
assertNull(projects.x());
}

@Test
public void testListFieldOptions() {
Map<ResourceManagerRpc.Option, Object> rpcOptions = new HashMap<>();
rpcOptions.put(ResourceManagerRpc.Option.FIELDS, "projects(projectId,name,labels)");
rpcOptions.put(ResourceManagerRpc.Option.PAGE_TOKEN, "somePageToken");
rpcOptions.put(ResourceManagerRpc.Option.PAGE_SIZE, 1);
rpc.create(PROJECT_WITH_PARENT);
Tuple<String, Iterable<com.google.api.services.cloudresourcemanager.model.Project>> projects =
rpc.list(rpcOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.util.Iterator;
import java.util.Map;

public class ResourceManagerImplTest {
Expand Down Expand Up @@ -166,7 +167,7 @@ public void testGetWithOptions() {
@Test
public void testList() {
Page<Project> projects = RESOURCE_MANAGER.list();
assertFalse(projects.values().iterator().hasNext()); // TODO: change this when #421 is resolved
assertFalse(projects.values().iterator().hasNext());
RESOURCE_MANAGER.create(PARTIAL_PROJECT);
RESOURCE_MANAGER.create(COMPLETE_PROJECT);
for (Project p : RESOURCE_MANAGER.list().values()) {
Expand All @@ -181,6 +182,22 @@ public void testList() {
}
}

@Test
public void testListPaging() {
RESOURCE_MANAGER.create(PARTIAL_PROJECT);
RESOURCE_MANAGER.create(COMPLETE_PROJECT);
Page<Project> page = RESOURCE_MANAGER.list(ProjectListOption.pageSize(1));
assertNotNull(page.nextPageCursor());
Iterator<Project> iterator = page.values().iterator();
compareReadWriteFields(COMPLETE_PROJECT, iterator.next());
assertFalse(iterator.hasNext());
page = page.nextPage();
iterator = page.values().iterator();
compareReadWriteFields(PARTIAL_PROJECT, iterator.next());
assertFalse(iterator.hasNext());
assertNull(page.nextPageCursor());
}

@Test
public void testListFieldOptions() {
RESOURCE_MANAGER.create(COMPLETE_PROJECT);
Expand Down

0 comments on commit da544a9

Please sign in to comment.