Skip to content

Commit

Permalink
Fix docs and return null if project not found by get.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ajay Kannan committed Dec 16, 2015
1 parent ad8ea4d commit 6b9e941
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 81 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ Google Cloud Resource Manager
Here is a code snippet showing a simple usage example. Note that you must supply Google SDK credentials for this service, not other forms of authentication listed in the [Authentication section](#authentication).
```java
import com.google.common.collect.ImmutableMap;
import com.google.gcloud.resourcemanager.ProjectInfo;
import com.google.gcloud.resourcemanager.ResourceManager;
import com.google.gcloud.resourcemanager.ResourceManagerOptions;
Expand All @@ -203,10 +202,10 @@ import java.util.Iterator;
ResourceManager resourceManager = ResourceManagerOptions.defaultInstance().service();
ProjectInfo myProject = resourceManager.get("some-project-id-that-I-own");
ProjectInfo newProjectInfo = resourceManager.replace(projectFromServer.toBuilder()
.labels(ImmutableMap.of("launch-status", "in-development")).build());
ProjectInfo newProjectInfo = resourceManager.replace(myProject.toBuilder()
.addLabel("launch-status", "in-development").build());
System.out.println("Updated the labels of project " + newProjectInfo.projectId()
+ " to be " + newProjectInfo.labels() + System.lineSeparator());
+ " to be " + newProjectInfo.labels());
// List all the projects you have permission to view.
Iterator<ProjectInfo> projectIterator = resourceManager.list().iterateAll();
System.out.println("Projects I can view:");
Expand Down
4 changes: 2 additions & 2 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ You can test against a temporary local Resource Manager by following these steps

This will spawn a server thread that listens to `localhost` at an ephemeral port for Resource Manager requests.

2. In your program, create and use a Resource Manager service object whose host is set host to `localhost` at the appropriate port. For example:
2. In your program, create and use a Resource Manager service object whose host is set to `localhost` at the appropriate port. For example:

```java
ResourceManager resourceManager = ResourceManagerOptions.builder()
Expand All @@ -97,7 +97,7 @@ You can test against a temporary local Resource Manager by following these steps
helper.stop();
```

This method will block a short amount of time until the server thread has been terminated.
This method will block until the server thread has been terminated.

#### On a remote machine

Expand Down
18 changes: 6 additions & 12 deletions gcloud-java-resourcemanager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ with the Cloud Resource Manager using this client Library.
Getting Started
---------------
#### Prerequisites
You will also need to set up the local development environment by [installing the Google Cloud SDK](https://cloud.google.com/sdk/) and running the following commands in command line: `gcloud auth login`.
You will need to set up the local development environment by [installing the Google Cloud SDK](https://cloud.google.com/sdk/) and running the following command in command line: `gcloud auth login`.

> Note: You don't need a project ID to use this service. If you have a project ID set in the Google Cloud SDK, you can unset it by typing `gcloud config unset project` in command line.
Expand All @@ -68,7 +68,7 @@ ResourceManager resourceManager = ResourceManagerOptions.defaultInstance().servi
```

#### Creating a project
All you need to create a project is a globally unique project ID. You can also optionally attach a non-unique name and labels to your project. Read more about naming guidelines for project IDs, names, and labels [here](https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects). To create a project, add the following imports at the top of your file:
All you need to create a project is a globally unique project ID. You can also optionally attach a non-unique name and labels to your project. Read more about naming guidelines for project IDs, names, and labels [here](https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects). To create a project, add the following import at the top of your file:

```java
import com.google.gcloud.resourcemanager.ProjectInfo;
Expand All @@ -84,7 +84,7 @@ ProjectInfo myProject = resourceManager.create(ProjectInfo.builder(myProjectId).
Note that the return value from `create` is a `ProjectInfo` that includes additional read-only information, like creation time, project number, and lifecycle state. Read more about these fields on the [Projects page](https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects).

#### Getting a specific project
You can load a project if you know it's project ID and have read permissions to the project. For example, say we wanted to get the project we just created. We can do the following:
You can load a project if you know it's project ID and have read permissions to the project. For example, to get the project we just created we can do the following:

```java
ProjectInfo projectFromServer = resourceManager.get(myProjectId);
Expand All @@ -93,23 +93,17 @@ ProjectInfo projectFromServer = resourceManager.get(myProjectId);
#### Editing a project
To edit a project, create a new `ProjectInfo` object and pass it in to the `ResourceManager.replace` method.

Suppose that you want to add a label for the newly created project to denote that it's launch status is "in development". Import the following:

```java
import com.google.common.collect.ImmutableMap;
```

Then add the following code to your program:
For example, to add a label for the newly created project to denote that it's launch status is "in development", add the following code:

```java
ProjectInfo newProjectInfo = resourceManager.replace(projectFromServer.toBuilder()
.labels(ImmutableMap.of("launch-status", "in-development")).build());
.addLabel("launch-status", "in-development").build());
```

Note that the values of the project you pass in to `replace` overwrite the server's values for non-read-only fields, namely `projectName` and `labels`. For example, if you create a project with `projectName` "some-project-name" and subsequently call replace using a `ProjectInfo` object that didn't set the `projectName`, then the server will unset the project's name. The server ignores any attempted changes to the read-only fields `projectNumber`, `lifecycleState`, and `createTime`. The `projectId` cannot change.

#### Listing all projects
Suppose that we want list of all projects for which we have read permissions. Add the following import:
Suppose that we want a list of all projects for which we have read permissions. Add the following import:

```java
import java.util.Iterator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public interface ResourceManager extends Service<ResourceManagerOptions> {
/**
* The fields of a project.
*
* These values can be used to specify the fields to include in a partial response when calling
* <p>These values can be used to specify the fields to include in a partial response when calling
* {@link ResourceManager#get} or {@link ResourceManager#list}. Project ID is always returned,
* even if not specified.
*/
Expand Down Expand Up @@ -82,7 +82,7 @@ private ProjectGetOption(ResourceManagerRpc.Option option, Object value) {
/**
* Returns an option to specify the project's fields to be returned by the RPC call.
*
* If this option is not provided all project fields are returned.
* <p>If this option is not provided all project fields are returned.
* {@code ProjectGetOption.fields} can be used to specify only the fields of interest. Project
* ID is always returned, even if not specified. {@link ProjectField} provides a list of fields
* that can be used.
Expand All @@ -106,17 +106,17 @@ private ProjectListOption(ResourceManagerRpc.Option option, Object value) {
/**
* Returns an option to specify a filter.
*
* Filter rules are case insensitive. The fields eligible for filtering are:
* <p>Filter rules are case insensitive. The fields eligible for filtering are:
* <ul>
* <li>name
* <li>project ID
* <li>labels.key, where key is the name of a label
* </ul>
*
* You can specify multiple filters by adding a space between each filter. Multiple filters
* <p>You can specify multiple filters by adding a space between each filter. Multiple filters
* are composed using "and".
*
* Some examples of filters:
* <p>Some examples of filters:
* <ul>
* <li> name:* The project has a name.
* <li> name:Howl The project's name is Howl or howl.
Expand All @@ -135,7 +135,7 @@ public static ProjectListOption filter(String filter) {
/**
* Returns an option to specify a page token.
*
* The page token (returned from a previous call to list) indicates from where listing should
* <p>The page token (returned from a previous call to list) indicates from where listing should
* continue.
*/
public static ProjectListOption pageToken(String pageToken) {
Expand All @@ -145,7 +145,7 @@ public static ProjectListOption pageToken(String pageToken) {
/**
* The maximum number of projects to return per RPC.
*
* The server can return fewer projects than requested. When there are more results than the
* <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.
Expand All @@ -157,7 +157,7 @@ public static ProjectListOption pageSize(int pageSize) {
/**
* Returns an option to specify the project's fields to be returned by the RPC call.
*
* If this option is not provided all project fields are returned.
* <p>If this option is not provided all project fields are returned.
* {@code ProjectListOption.fields} can be used to specify only the fields of interest. Project
* ID is always returned, even if not specified. {@link ProjectField} provides a list of fields
* that can be used.
Expand All @@ -172,7 +172,7 @@ public static ProjectListOption fields(ProjectField... fields) {
/**
* Create a new project.
*
* Initially, the project resource is owned by its creator exclusively. The creator can later
* <p>Initially, the project resource is owned by its creator exclusively. The creator can later
* grant permission to others to read or update the project. Several APIs are activated
* automatically for the project, including Google Cloud Storage.
*
Expand All @@ -189,7 +189,7 @@ public static ProjectListOption fields(ProjectField... fields) {
/**
* Marks the project identified by the specified project ID for deletion.
*
* This method will only affect the project if the following criteria are met:
* <p>This method will only affect the project if the following criteria are met:
* <ul>
* <li>The project does not have a billing account associated with it.
* <li>The project has a lifecycle state of {@link ProjectInfo.State#ACTIVE}.
Expand All @@ -213,7 +213,8 @@ public static ProjectListOption fields(ProjectField... fields) {
/**
* Retrieves the project identified by the specified project ID.
*
* The caller must have read permissions for this project.
* <p>The caller must have read permissions for this project. Returns {@code null} if project
* not found.
*
* @see <a
* href="https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects/get">Cloud
Expand All @@ -225,7 +226,8 @@ public static ProjectListOption fields(ProjectField... fields) {
/**
* Lists the projects visible to the current user.
*
* This method returns projects in an unspecified order. New projects do not necessarily appear at
* <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.
Expand All @@ -241,7 +243,7 @@ public static ProjectListOption fields(ProjectField... fields) {
/**
* Replaces the attributes of the project.
*
* The caller must have modify permissions for this project.
* <p>The caller must have modify permissions for this project.
*
* @see <a
* href="https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects/update">Cloud
Expand All @@ -254,7 +256,7 @@ public static ProjectListOption fields(ProjectField... fields) {
/**
* Restores the project identified by the specified project ID.
*
* You can only use this method for a project that has a lifecycle state of
* <p>You can only use this method for a project that has a lifecycle state of
* {@link ProjectInfo.State#DELETE_REQUESTED}. After deletion starts, as indicated by a lifecycle
* state of {@link ProjectInfo.State#DELETE_IN_PROGRESS}, the project cannot be restored. The
* caller must have modify permissions for this project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public class ResourceManagerImpl

private static final Interceptor EXCEPTION_HANDLER_INTERCEPTOR = new Interceptor() {

private static final long serialVersionUID = 2091576149969931704L;

@Override
public RetryResult afterEval(Exception exception, RetryResult retryResult) {
return Interceptor.RetryResult.CONTINUE_EVALUATION;
Expand Down Expand Up @@ -69,14 +71,13 @@ public RetryResult beforeEval(Exception exception) {
}

@Override
public ProjectInfo create(ProjectInfo project) {
final com.google.api.services.cloudresourcemanager.model.Project projectPb = project.toPb();
public ProjectInfo create(final ProjectInfo project) {
try {
return ProjectInfo.fromPb(runWithRetries(
new Callable<com.google.api.services.cloudresourcemanager.model.Project>() {
@Override
public com.google.api.services.cloudresourcemanager.model.Project call() {
return resourceManagerRpc.create(projectPb);
return resourceManagerRpc.create(project.toPb());
}
}, options().retryParams(), EXCEPTION_HANDLER));
} catch (RetryHelperException e) {
Expand All @@ -103,20 +104,24 @@ public Void call() {
public ProjectInfo get(final String projectId, ProjectGetOption... options) {
final Map<ResourceManagerRpc.Option, ?> optionsMap = optionMap(options);
try {
return ProjectInfo.fromPb(runWithRetries(
com.google.api.services.cloudresourcemanager.model.Project answer = runWithRetries(
new Callable<com.google.api.services.cloudresourcemanager.model.Project>() {
@Override
public com.google.api.services.cloudresourcemanager.model.Project call() {
return resourceManagerRpc.get(projectId, optionsMap);
}
}, options().retryParams(), EXCEPTION_HANDLER));
}, options().retryParams(), EXCEPTION_HANDLER);
return answer == null ? null : ProjectInfo.fromPb(answer);
} catch (RetryHelperException e) {
throw ResourceManagerException.translateAndThrow(e);
}
}

private abstract static class BasePageFetcher<T extends Serializable>
implements PageImpl.NextPageFetcher<T> {

private static final long serialVersionUID = -5560906434575940205L;

protected final Map<ResourceManagerRpc.Option, ?> requestOptions;
protected final ResourceManagerOptions serviceOptions;

Expand All @@ -137,6 +142,9 @@ private abstract static class BasePageFetcher<T extends Serializable>
}

private static class ProjectPageFetcher extends BasePageFetcher<ProjectInfo> {

private static final long serialVersionUID = -533306655445189098L;

ProjectPageFetcher(ResourceManagerOptions serviceOptions, String cursor,
Map<ResourceManagerRpc.Option, ?> optionMap) {
super(serviceOptions, cursor, optionMap);
Expand All @@ -153,18 +161,15 @@ public Page<ProjectInfo> list(ProjectListOption... options) {
return listProjects(options(), optionMap(options));
}

private static Page<ProjectInfo> listProjects(
final ResourceManagerOptions serviceOptions,
private static Page<ProjectInfo> listProjects(final ResourceManagerOptions serviceOptions,
final Map<ResourceManagerRpc.Option, ?> optionsMap) {
try {
Tuple<String, Iterable<com.google.api.services.cloudresourcemanager.model.Project>> result =
runWithRetries(
new Callable<Tuple<String, Iterable<com.google.api.services.cloudresourcemanager.model
.Project>>>() {
runWithRetries(new Callable<Tuple<String,
Iterable<com.google.api.services.cloudresourcemanager.model.Project>>>() {
@Override
public Tuple<String, Iterable<com.google.api.services.cloudresourcemanager.model
.Project>>
call() {
public Tuple<String,
Iterable<com.google.api.services.cloudresourcemanager.model.Project>> call() {
return serviceOptions.rpc().list(optionsMap);
}
},
Expand All @@ -190,14 +195,13 @@ public ProjectInfo apply(
}

@Override
public ProjectInfo replace(ProjectInfo newProject) {
final com.google.api.services.cloudresourcemanager.model.Project projectPb = newProject.toPb();
public ProjectInfo replace(final ProjectInfo newProject) {
try {
return ProjectInfo.fromPb(runWithRetries(
new Callable<com.google.api.services.cloudresourcemanager.model.Project>() {
@Override
public com.google.api.services.cloudresourcemanager.model.Project call() {
return resourceManagerRpc.replace(projectPb);
return resourceManagerRpc.replace(newProject.toPb());
}
}, options().retryParams(), EXCEPTION_HANDLER));
} catch (RetryHelperException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ public class ResourceManagerOptions

private static final long serialVersionUID = 538303101192527452L;
private static final String GCRM_SCOPE = "https://www.googleapis.com/auth/cloud-platform";
private static final String READ_ONLY_GCRM_SCOPE =
"https://www.googleapis.com/auth/cloud-platform.read-only";
private static final Set<String> SCOPES = ImmutableSet.of(GCRM_SCOPE, READ_ONLY_GCRM_SCOPE);
private static final Set<String> SCOPES = ImmutableSet.of(GCRM_SCOPE);
private static final String DEFAULT_HOST = "https://cloudresourcemanager.googleapis.com";

public static class DefaultResourceManagerFactory implements ResourceManagerFactory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ public Project get(String projectId, Map<Option, ?> options) throws ResourceMana
.setFields(FIELDS.getString(options))
.execute();
} catch (IOException ex) {
throw translate(ex);
ResourceManagerException translated = translate(ex);
if (translated.code() == 403) {
return null; // Project not found
} else {
throw translated;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,7 @@ public void testGet() {
rpc.get(COMPLETE_PROJECT.getProjectId(), EMPTY_RPC_OPTIONS);
compareReadWriteFields(COMPLETE_PROJECT, returnedProject);
RESOURCE_MANAGER_HELPER.removeProject(COMPLETE_PROJECT.getProjectId());
try {
rpc.get(COMPLETE_PROJECT.getProjectId(), EMPTY_RPC_OPTIONS);
fail("Should fail because the project doesn't exist.");
} catch (ResourceManagerException e) {
assertEquals(403, e.code());
assertTrue(e.getMessage().contains("not found"));
}
assertNull(rpc.get(COMPLETE_PROJECT.getProjectId(), EMPTY_RPC_OPTIONS));
}

@Test
Expand Down Expand Up @@ -534,13 +528,7 @@ public void testRemoveProject() {
assertFalse(RESOURCE_MANAGER_HELPER.removeProject(COMPLETE_PROJECT.getProjectId()));
rpc.create(COMPLETE_PROJECT);
assertTrue(RESOURCE_MANAGER_HELPER.removeProject(COMPLETE_PROJECT.getProjectId()));
try {
rpc.get(COMPLETE_PROJECT.getProjectId(), EMPTY_RPC_OPTIONS);
fail("Project shouldn't exist.");
} catch (ResourceManagerException e) {
assertEquals(403, e.code());
assertTrue(e.getMessage().contains("not found."));
}
assertNull(rpc.get(COMPLETE_PROJECT.getProjectId(), EMPTY_RPC_OPTIONS));
}

private void compareReadWriteFields(
Expand Down
Loading

0 comments on commit 6b9e941

Please sign in to comment.