diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Option.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Option.java
index 9900861b93cc..853b678a2ebe 100644
--- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Option.java
+++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Option.java
@@ -27,7 +27,7 @@
/**
* Base class for Resource Manager operation options
*/
-public class Option implements Serializable {
+class Option implements Serializable {
private static final long serialVersionUID = 2655177550880762967L;
@@ -70,4 +70,3 @@ public String toString() {
.toString();
}
}
-
diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Project.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Project.java
index b9abdabc9f87..a08d7e3714be 100644
--- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Project.java
+++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Project.java
@@ -21,8 +21,10 @@
/**
* A Google Cloud Resource Manager project object.
*
- * This class' member variables are immutable. Methods that change or update the underlying Project
- * information return a new Project instance.
+ * A Project is a high-level Google Cloud Platform entity. It is a container for ACLs, APIs,
+ * AppEngine Apps, VMs, and other Google Cloud Platform resources. This class' member variables are
+ * immutable. Methods that change or update the underlying Project information return a new Project
+ * instance.
*/
public class Project {
@@ -69,7 +71,7 @@ public ResourceManager resourceManager() {
* @throws ResourceManagerException upon failure
*/
public Project reload() {
- return new Project(resourceManager, resourceManager.get(info.id()));
+ return Project.load(resourceManager, info.projectId());
}
/**
@@ -89,13 +91,13 @@ public Project reload() {
* completes, the project is not retrievable by the {@link ResourceManager#get} and
* {@link ResourceManager#list} methods. The caller must have modify permissions for this project.
*
- * @see
- *
- * Cloud Resource Manager delete
+ * @see Cloud
+ * Resource Manager delete
* @throws ResourceManagerException upon failure
*/
public void delete() {
- resourceManager.delete(info.id());
+ resourceManager.delete(info.projectId());
}
/**
@@ -106,13 +108,13 @@ public void delete() {
* state of {@link ProjectInfo.State#DELETE_IN_PROGRESS}, the project cannot be restored. The
* caller must have modify permissions for this project.
*
- * @see
- * Cloud Resource Manager undelete
+ * @see Cloud
+ * Resource Manager undelete
* @throws ResourceManagerException upon failure (including when the project can't be restored)
*/
public void undelete() {
- resourceManager.undelete(info.id());
+ resourceManager.undelete(info.projectId());
}
/**
@@ -120,9 +122,9 @@ public void undelete() {
*
* The caller must have modify permissions for this project.
*
- * @see
- *
- * Cloud Resource Manager update
+ * @see Cloud
+ * Resource Manager update
* @return the ProjectInfo representing the new project metadata
* @throws ResourceManagerException upon failure
*/
diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ProjectInfo.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ProjectInfo.java
index 4e45e1274dbf..7b48e595ae0d 100644
--- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ProjectInfo.java
+++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ProjectInfo.java
@@ -14,11 +14,14 @@
package com.google.gcloud.resourcemanager;
+import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.api.client.util.Data;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
+import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
import java.io.Serializable;
@@ -28,26 +31,23 @@
/**
* A Google Cloud Resource Manager project metadata object.
+ *
+ * A Project is a high-level Google Cloud Platform entity. It is a container for ACLs, APIs,
+ * AppEngine Apps, VMs, and other Google Cloud Platform resources.
*/
public class ProjectInfo implements Serializable {
private static final long serialVersionUID = 9148970963697734236L;
private final String name;
- private final String id;
+ private final String projectId;
private final Map labels;
- private final Long number;
+ private final Long projectNumber;
private final State state;
private final Long createTimeMillis;
+ private final ResourceId parent;
/**
- * The project lifecycle state.
- *
- *
- *
LIFECYCLE_STATE_UNSPECIFIED:
- *
ACTIVE:
- *
DELETE_REQUESTED:
- *
DELETE_IN_PROGRESS:
- *
+ * The project lifecycle states.
*/
public enum State {
/**
@@ -72,16 +72,71 @@ public enum State {
DELETE_IN_PROGRESS
}
+ static class ResourceId implements Serializable {
+
+ private static final long serialVersionUID = -325199985993344726L;
+
+ private final String id;
+ private final String type;
+
+ ResourceId(String id, String type) {
+ this.id = checkNotNull(id);
+ this.type = checkNotNull(type);
+ }
+
+ String id() {
+ return id;
+ }
+
+ String type() {
+ return type;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof ResourceId && Objects.equals(toPb(), ((ResourceId) obj).toPb());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, type);
+ }
+
+ com.google.api.services.cloudresourcemanager.model.ResourceId toPb() {
+ com.google.api.services.cloudresourcemanager.model.ResourceId resourceIdPb =
+ new com.google.api.services.cloudresourcemanager.model.ResourceId();
+ resourceIdPb.setId(id);
+ resourceIdPb.setType(type.toString().toLowerCase());
+ return resourceIdPb;
+ }
+
+ static ResourceId fromPb(
+ com.google.api.services.cloudresourcemanager.model.ResourceId resourceIdPb) {
+ return new ResourceId(resourceIdPb.getId(), resourceIdPb.getType());
+ }
+ }
+
public static class Builder {
+
private String name;
- private String id;
- private Map labels;
- private Long number;
+ private String projectId;
+ private Map labels = new HashMap<>();
+ private Long projectNumber;
private State state;
private Long createTimeMillis;
+ private ResourceId parent;
- Builder() {
- labels = new HashMap<>();
+ private Builder() {
+ }
+
+ Builder(ProjectInfo info) {
+ this.name = info.name;
+ this.projectId = info.projectId;
+ this.labels = Maps.newHashMap(checkNotNull(info.labels));
+ this.projectNumber = info.projectNumber;
+ this.state = info.state;
+ this.createTimeMillis = info.createTimeMillis;
+ this.parent = info.parent;
}
/**
@@ -92,7 +147,7 @@ public static class Builder {
* field can be changed after project creation.
*/
public Builder name(String name) {
- this.name = name;
+ this.name = firstNonNull(name, Data.nullOf(String.class));
return this;
}
@@ -103,8 +158,8 @@ public Builder name(String name) {
* Trailing hyphens are prohibited. This field cannot be changed after the server creates the
* project.
*/
- public Builder id(String id) {
- this.id = id;
+ public Builder projectId(String projectId) {
+ this.projectId = projectId;
return this;
}
@@ -148,8 +203,8 @@ public Builder labels(Map labels) {
return this;
}
- Builder number(Long number) {
- this.number = number;
+ Builder projectNumber(Long projectNumber) {
+ this.projectNumber = projectNumber;
return this;
}
@@ -163,6 +218,11 @@ Builder createTimeMillis(Long createTimeMillis) {
return this;
}
+ Builder parent(ResourceId parent) {
+ this.parent = parent;
+ return this;
+ }
+
public ProjectInfo build() {
return new ProjectInfo(this);
}
@@ -170,11 +230,12 @@ public ProjectInfo build() {
ProjectInfo(Builder builder) {
this.name = builder.name;
- this.id = checkNotNull(builder.id);
+ this.projectId = checkNotNull(builder.projectId);
this.labels = ImmutableMap.copyOf(builder.labels);
- this.number = builder.number;
+ this.projectNumber = builder.projectNumber;
this.state = builder.state;
this.createTimeMillis = builder.createTimeMillis;
+ this.parent = builder.parent;
}
/**
@@ -182,8 +243,8 @@ public ProjectInfo build() {
*
* This field cannot be changed after the server creates the project.
*/
- public String id() {
- return id;
+ public String projectId() {
+ return projectId;
}
/**
@@ -192,7 +253,7 @@ public String id() {
* This field is optional, can remain unset, and can be changed after project creation.
*/
public String name() {
- return name;
+ return Data.isNull(name) ? null : name;
}
/**
@@ -200,8 +261,8 @@ public String name() {
*
* This field is set by the server and is read-only.
*/
- public Long number() {
- return number;
+ public Long projectNumber() {
+ return projectNumber;
}
/**
@@ -221,6 +282,10 @@ public State state() {
return state;
}
+ ResourceId parent() {
+ return parent;
+ }
+
/**
* Get the project's creation time (in milliseconds).
*
@@ -237,45 +302,54 @@ public boolean equals(Object obj) {
@Override
public int hashCode() {
- return Objects.hash(name, id, labels, number, state, createTimeMillis);
+ return Objects.hash(name, projectId, labels, projectNumber, state, createTimeMillis, parent);
}
public static Builder builder(String id) {
- return new Builder().id(id);
+ return new Builder().projectId(id);
}
public Builder toBuilder() {
- return new Builder()
- .name(name)
- .id(id)
- .labels(labels)
- .number(number)
- .state(state)
- .createTimeMillis(createTimeMillis);
+ return new Builder(this);
}
com.google.api.services.cloudresourcemanager.model.Project toPb() {
com.google.api.services.cloudresourcemanager.model.Project projectPb =
new com.google.api.services.cloudresourcemanager.model.Project();
projectPb.setName(name);
- projectPb.setProjectId(id);
+ projectPb.setProjectId(projectId);
projectPb.setLabels(labels);
- projectPb.setProjectNumber(number);
+ projectPb.setProjectNumber(projectNumber);
if (state != null) {
projectPb.setLifecycleState(state.toString());
}
if (createTimeMillis != null) {
projectPb.setCreateTime(ISODateTimeFormat.dateTime().print(createTimeMillis));
}
+ if (parent != null) {
+ projectPb.setParent(parent.toPb());
+ }
return projectPb;
}
static ProjectInfo fromPb(com.google.api.services.cloudresourcemanager.model.Project projectPb) {
ProjectInfo.Builder builder =
- ProjectInfo.builder(projectPb.getProjectId()).name(projectPb.getName());
+ ProjectInfo.builder(projectPb.getProjectId()).projectNumber(projectPb.getProjectNumber());
+ if (projectPb.getName() != null) {
+ builder.name(projectPb.getName());
+ }
if (projectPb.getLabels() != null) {
builder.labels(projectPb.getLabels());
}
+ if (projectPb.getLifecycleState() != null) {
+ builder.state(State.valueOf(projectPb.getLifecycleState()));
+ }
+ if (projectPb.getCreateTime() != null) {
+ builder.createTimeMillis(DateTime.parse(projectPb.getCreateTime()).getMillis());
+ }
+ if (projectPb.getParent() != null) {
+ builder.parent(ResourceId.fromPb(projectPb.getParent()));
+ }
return builder.build();
}
}
diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManager.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManager.java
index 46183bfc8188..8d57ec2e3610 100644
--- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManager.java
+++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManager.java
@@ -41,10 +41,10 @@ public interface ResourceManager extends Service {
* even if not specified.
*/
enum ProjectField {
- ID("projectId"),
+ PROJECT_ID("projectId"),
NAME("name"),
LABELS("labels"),
- NUMBER("projectNumber"),
+ PROJECT_NUMBER("projectNumber"),
STATE("lifecycleState"),
CREATE_TIME("createTime");
@@ -60,7 +60,7 @@ public String selector() {
static String selector(ProjectField... fields) {
HashSet fieldStrings = Sets.newHashSetWithExpectedSize(fields.length + 1);
- fieldStrings.add(ID.selector());
+ fieldStrings.add(PROJECT_ID.selector());
for (ProjectField field : fields) {
fieldStrings.add(field.selector());
}
@@ -68,6 +68,9 @@ static String selector(ProjectField... fields) {
}
}
+ /**
+ * Class for specifying project get options.
+ */
public class ProjectGetOption extends Option {
private static final long serialVersionUID = 270185129961146874L;
@@ -80,7 +83,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.
- * {@code ProjectListOption.fields} can be used to specify only the fields of interest. Project
+ * {@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.
*/
@@ -106,11 +109,16 @@ private ProjectListOption(ResourceManagerRpc.Option option, Object value) {
* Filter rules are case insensitive. The fields eligible for filtering are:
*
*
name
- *
id
+ *
project ID
*
labels.key, where key is the name of a label
*
*
- * Some examples of using labels as filters:
+ * You can specify multiple filters by adding a space between each filter. Multiple filters
+ * are composed using "and".
+ *
+ *
+ *
+ * Some examples of filters:
*
*
name:* The project has a name.
*
name:Howl The project's name is Howl or howl.
@@ -121,8 +129,6 @@ private ProjectListOption(ResourceManagerRpc.Option option, Object value) {
*
labels.color:red label.size:big The project's label color has the value red and its
* label size has the value big.
*
- *
- * Optional.
*/
public static ProjectListOption filter(String filter) {
return new ProjectListOption(ResourceManagerRpc.Option.FILTER, filter);
@@ -150,10 +156,9 @@ public static ProjectListOption fields(ProjectField... fields) {
* grant permission to others to read or update the project. Several APIs are activated
* automatically for the project, including Google Cloud Storage.
*
- * @see
- *
- * Cloud Resource Manager create
- *
+ * @see Cloud
+ * Resource Manager create
* @return ProjectInfo object representing the new project's metadata. The returned object will
* include the following read-only fields supplied by the server: project number, lifecycle
* state, and creation time.
@@ -178,9 +183,9 @@ public static ProjectListOption fields(ProjectField... fields) {
* completes, the project is not retrievable by the {@link ResourceManager#get} and
* {@link ResourceManager#list} methods. The caller must have modify permissions for this project.
*
- * @see
- *
- * Cloud Resource Manager delete
+ * @see Cloud
+ * Resource Manager delete
* @throws ResourceManagerException upon failure
*/
void delete(String projectId);
@@ -190,8 +195,9 @@ public static ProjectListOption fields(ProjectField... fields) {
*
* The caller must have read permissions for this project.
*
- * @see
- * Cloud Resource Manager get
+ * @see Cloud
+ * Resource Manager get
* @throws ResourceManagerException upon failure
*/
ProjectInfo get(String projectId, ProjectGetOption... options);
@@ -204,8 +210,9 @@ public static ProjectListOption fields(ProjectField... fields) {
* page tokens. Note that pagination is currently not implemented by the Cloud Resource Manager
* API.
*
- * @see
- * Cloud Resource Manager list
+ * @see Cloud
+ * Resource Manager list
* @return {@code Page}, a page of projects.
* @throws ResourceManagerException upon failure
*/
@@ -216,9 +223,9 @@ public static ProjectListOption fields(ProjectField... fields) {
*
* The caller must have modify permissions for this project.
*
- * @see
- *
- * Cloud Resource Manager update
+ * @see Cloud
+ * Resource Manager update
* @return the ProjectInfo representing the new project metadata
* @throws ResourceManagerException upon failure
*/
@@ -232,9 +239,9 @@ public static ProjectListOption fields(ProjectField... fields) {
* state of {@link ProjectInfo.State#DELETE_IN_PROGRESS}, the project cannot be restored. The
* caller must have modify permissions for this project.
*
- * @see
- * Cloud Resource Manager undelete
+ * @see Cloud
+ * Resource Manager undelete
* @throws ResourceManagerException
*/
void undelete(String projectId);
diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerException.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerException.java
index 8287ed167557..22b5e8bfed7c 100644
--- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerException.java
+++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerException.java
@@ -17,6 +17,7 @@
package com.google.gcloud.resourcemanager;
import com.google.gcloud.BaseServiceException;
+import com.google.gcloud.RetryHelper;
import com.google.gcloud.RetryHelper.RetryHelperException;
import com.google.gcloud.RetryHelper.RetryInterruptedException;
@@ -44,7 +45,12 @@ public ResourceManagerException(int code, String message, boolean retryable) {
* @throws RetryInterruptedException when {@code ex} is a {@code RetryInterruptedException}
*/
static ResourceManagerException translateAndThrow(RetryHelperException ex) {
+ if (ex.getCause() instanceof ResourceManagerException) {
+ throw (ResourceManagerException) ex.getCause();
+ }
+ if (ex instanceof RetryHelper.RetryInterruptedException) {
+ RetryHelper.RetryInterruptedException.propagate();
+ }
throw new ResourceManagerException(UNKNOWN_CODE, ex.getMessage(), false);
- // TODO(ajaykannan): Fix me!
}
}
diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/DefaultResourceManagerRpc.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/DefaultResourceManagerRpc.java
new file mode 100644
index 000000000000..45f8f9de75e9
--- /dev/null
+++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/DefaultResourceManagerRpc.java
@@ -0,0 +1,89 @@
+package com.google.gcloud.spi;
+
+import com.google.api.client.googleapis.json.GoogleJsonError;
+import com.google.api.client.googleapis.json.GoogleJsonResponseException;
+import com.google.api.client.http.HttpRequestInitializer;
+import com.google.api.client.http.HttpTransport;
+import com.google.api.client.json.jackson.JacksonFactory;
+import com.google.api.services.cloudresourcemanager.Cloudresourcemanager;
+import com.google.api.services.cloudresourcemanager.model.Project;
+import com.google.common.collect.ImmutableSet;
+import com.google.gcloud.resourcemanager.ResourceManagerException;
+import com.google.gcloud.resourcemanager.ResourceManagerOptions;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
+public class DefaultResourceManagerRpc implements ResourceManagerRpc {
+
+ private static final Set RETRYABLE_CODES = ImmutableSet.of(503, 500, 429, 417);
+
+ private final ResourceManagerOptions options;
+ private final Cloudresourcemanager resourceManager;
+
+ public DefaultResourceManagerRpc(ResourceManagerOptions options) {
+ HttpTransport transport = options.httpTransportFactory().create();
+ HttpRequestInitializer initializer = options.httpRequestInitializer();
+ this.options = options;
+ resourceManager =
+ new Cloudresourcemanager.Builder(transport, new JacksonFactory(), initializer)
+ .setRootUrl(options.host())
+ .setApplicationName(options.applicationName())
+ .build();
+ }
+
+ private static ResourceManagerException translate(IOException exception) {
+ ResourceManagerException translated;
+ if (exception instanceof GoogleJsonResponseException) {
+ translated = translate(((GoogleJsonResponseException) exception).getDetails());
+ } else {
+ translated = new ResourceManagerException(0, exception.getMessage(), false);
+ }
+ translated.initCause(exception);
+ return translated;
+ }
+
+ private static ResourceManagerException translate(GoogleJsonError exception) {
+ boolean retryable =
+ RETRYABLE_CODES.contains(exception.getCode())
+ || "InternalError".equals(exception.getMessage());
+ return new ResourceManagerException(exception.getCode(), exception.getMessage(), retryable);
+ }
+
+ @Override
+ public Project create(Project project) throws ResourceManagerException {
+ // TODO(ajaykannan): fix me!
+ return null;
+ }
+
+ @Override
+ public void delete(String projectId) throws ResourceManagerException {
+ // TODO(ajaykannan): fix me!
+ }
+
+ @Override
+ public Project get(String projectId) throws ResourceManagerException {
+ // TODO(ajaykannan): fix me!
+ return null;
+ }
+
+ @Override
+ public Tuple> list(Map