From 573f88c270f275e06ab3b8cfd38beed66b284d7d Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Thu, 12 Nov 2015 14:11:56 -0800 Subject: [PATCH 01/10] Project, ProjectInfo, Policy, and ResourceId classes added. --- .../google/gcloud/resourcemanager/Policy.java | 389 ++++++++++++++++++ .../gcloud/resourcemanager/Project.java | 96 +++++ .../gcloud/resourcemanager/ProjectInfo.java | 238 +++++++++++ .../gcloud/resourcemanager/ResourceId.java | 82 ++++ .../resourcemanager/ResourceManager.java | 80 +++- .../ResourceManagerException.java | 23 +- .../ResourceManagerOptions.java | 5 + .../google/gcloud/spi/ResourceManagerRpc.java | 27 +- .../gcloud/resourcemanager/PolicyTest.java | 108 +++++ .../resourcemanager/ProjectInfoTest.java | 73 ++++ .../gcloud/resourcemanager/ProjectTest.java | 214 ++++++++++ .../resourcemanager/ResourceIdTest.java | 42 ++ .../resourcemanager/SerializationTest.java | 126 ++++++ 13 files changed, 1475 insertions(+), 28 deletions(-) create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Project.java create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ProjectInfo.java create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java create mode 100644 gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java create mode 100644 gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java create mode 100644 gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java create mode 100644 gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java create mode 100644 gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java new file mode 100644 index 000000000000..765e38d3c2f8 --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java @@ -0,0 +1,389 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.collect.ImmutableList; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * A Google Cloud IAM Policy object + */ +public class Policy implements Serializable { + + private static final long serialVersionUID = 3493286111316914094L; + private final List bindings; + private final Integer version; + private final String etag; + + public static enum MemberType { + ALL_USERS("allUsers"), + ALL_AUTHENTICATED_USERS("allAuthenticatedUsers"), + USER("user:"), + SERVICE_ACCOUNT("serviceAccount:"), + GROUP("group:"), + DOMAIN("domain:"); + + private final String prefix; + + MemberType(String prefix) { + this.prefix = prefix; + } + + String prefix() { + return prefix; + } + } + + public enum RoleType { + OWNER, + EDITOR, + VIEWER; + } + + /** + * Represents a member belonging to an IAM policy binding + */ + public static final class Member implements Serializable { + + private static final long serialVersionUID = 6496912037577986137L; + private final MemberType memberType; + private final String emailOrDomain; + + Member(MemberType memberType, String emailOrDomain) { + this.memberType = memberType; + this.emailOrDomain = emailOrDomain; + } + + public static Member allUsers() { + throw new UnsupportedOperationException( + "Google Cloud Resource Manager does not support the \"all users\" member type yet."); + // return new Member(MemberType.ALL_USERS, null); + } + + public static Member allAuthenticatedUsers() { + throw new UnsupportedOperationException("Google Cloud Resource Manager does not support the " + + "\"all authenticated users\" member type yet."); + // return new Member(MemberType.ALL_AUTHENTICATED_USERS, null); + } + + public static Member user(String email) { + return new Member(MemberType.USER, email); + } + + public static Member serviceAccount(String email) { + return new Member(MemberType.SERVICE_ACCOUNT, email); + } + + public static Member group(String email) { + return new Member(MemberType.GROUP, email); + } + + public static Member domain(String domain) { + throw new UnsupportedOperationException( + "Google Cloud Resource Manager does not support domain members yet."); + // return new Member(MemberType.DOMAIN, domain); + } + + public MemberType type() { + return memberType; + } + + public String emailOrDomain() { + return emailOrDomain; + } + + @Override + public int hashCode() { + return Objects.hash(memberType, emailOrDomain); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Member && Objects.equals(this.memberType, ((Member) obj).memberType) + && Objects.equals(this.emailOrDomain, ((Member) obj).emailOrDomain); + } + } + + /** + * Represents an IAM policy binding + */ + public static class Binding implements Serializable { + + private static final long serialVersionUID = -8493421092718338925L; + private final RoleType role; + private final List members; + + public static class Builder { + private RoleType role; + private List members; + + Builder() { + members = new ArrayList(); + } + + public Builder role(RoleType role) { + this.role = role; + return this; + } + + public Builder members(List members) { + this.members = checkNotNull(members); + return this; + } + + public Builder clearMembers() { + this.members = new ArrayList<>(); + return this; + } + + public Builder addMember(Member member) { + this.members.add(member); + return this; + } + + public Builder removeMember(Member member) { + this.members.remove(member); + return this; + } + + public Binding build() { + return new Binding(role, members); + } + } + + private Binding(RoleType role, List members) { + this.role = role; + ImmutableList.Builder membersListBuilder = new ImmutableList.Builder<>(); + for (Member member : members) { + membersListBuilder.add(member); + } + this.members = membersListBuilder.build(); + } + + public static Binding binding(RoleType role, List members) { + return new Binding(role, members); + } + + public RoleType role() { + return role; + } + + public List members() { + return members; + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + List mutableMembers = new ArrayList<>(); + for (Member member : members) { + mutableMembers.add(member); + } + return new Builder().role(role).members(mutableMembers); + } + + com.google.api.services.cloudresourcemanager.model.Binding toPb() { + com.google.api.services.cloudresourcemanager.model.Binding bindingPb = + new com.google.api.services.cloudresourcemanager.model.Binding(); + if (role != null) { + bindingPb.setRole("roles/" + role.toString().toLowerCase()); + } + List membersPb = new ArrayList<>(members.size()); + for (Member member : members) { + if (member.emailOrDomain() != null) { + membersPb.add(member.type().prefix() + member.emailOrDomain()); + } else { + membersPb.add(member.type().prefix()); + } + } + bindingPb.setMembers(membersPb); + return bindingPb; + } + + static Binding fromPb(com.google.api.services.cloudresourcemanager.model.Binding bindingPb) { + RoleType role = + (bindingPb.getRole() == null) + ? null : RoleType.valueOf(bindingPb.getRole().split("/")[1].toUpperCase()); + List members = new ArrayList<>(); + if (bindingPb.getMembers() != null) { + for (String memberPb : bindingPb.getMembers()) { + String[] memberInfo = memberPb.split(":", 2); + String memberTypeStr = memberInfo[0]; + String emailOrDomain = (memberInfo.length > 1) ? emailOrDomain = memberInfo[1] : null; + switch (memberTypeStr) { + case "allUsers": + members.add(new Member(MemberType.ALL_USERS, null)); + break; + case "allAuthenticatedUsers": + members.add(new Member(MemberType.ALL_AUTHENTICATED_USERS, null)); + break; + case "user": + members.add(new Member(MemberType.USER, checkNotNull(emailOrDomain))); + break; + case "serviceAccount": + members.add(new Member(MemberType.SERVICE_ACCOUNT, checkNotNull(emailOrDomain))); + break; + case "group": + members.add(new Member(MemberType.GROUP, checkNotNull(emailOrDomain))); + break; + case "domain": + members.add(new Member(MemberType.DOMAIN, checkNotNull(emailOrDomain))); + break; + default: + throw new UnsupportedOperationException("Unsupported member type: " + memberTypeStr); + } + } + } + return new Binding(role, members); + } + + @Override + public int hashCode() { + return Objects.hash(role, members); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Binding && Objects.equals(this.role, ((Binding) obj).role) + && Objects.equals(this.members, ((Binding) obj).members); + } + } + + public static final class Builder { + private List bindings; + private String etag; + private Integer version; + + private Builder() { + bindings = new ArrayList<>(); + } + + public Builder addBinding(Binding binding) { + this.bindings.add(binding); + return this; + } + + public Builder removeBinding(Binding binding) { + this.bindings.remove(binding); + return this; + } + + public Builder clearBindings() { + this.bindings = new ArrayList<>(); + return this; + } + + public Builder bindings(List bindings) { + this.bindings = checkNotNull(bindings); + return this; + } + + public Builder etag(String etag) { + this.etag = etag; + return this; + } + + public Builder version(Integer version) { + this.version = version; + return this; + } + + public Policy build() { + return new Policy(this); + } + } + + Policy(Builder builder) { + ImmutableList.Builder bindingsListBuilder = new ImmutableList.Builder<>(); + for (Binding binding : builder.bindings) { + bindingsListBuilder.add(binding); + } + bindings = bindingsListBuilder.build(); + version = builder.version; + etag = builder.etag; + } + + public List bindings() { + return bindings; + } + + public Integer version() { + return version; + } + + public String etag() { + return etag; + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + List mutableBindings = new ArrayList<>(); + for (Binding binding : bindings) { + mutableBindings.add(binding); + } + return new Builder().bindings(mutableBindings).etag(etag).version(version); + } + + @Override + public int hashCode() { + return Objects.hash(bindings, etag, version); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Policy && Objects.equals(this.bindings, ((Policy) obj).bindings) + && Objects.equals(this.etag, ((Policy) obj).etag) + && Objects.equals(this.version, ((Policy) obj).version); + } + + com.google.api.services.cloudresourcemanager.model.Policy toPb() { + com.google.api.services.cloudresourcemanager.model.Policy policyPb = + new com.google.api.services.cloudresourcemanager.model.Policy(); + List bindingsPb = new ArrayList<>(); + for (Binding binding : bindings) { + bindingsPb.add(binding.toPb()); + } + policyPb.setBindings(bindingsPb); + policyPb.setVersion(version); + policyPb.setEtag(etag); + return policyPb; + } + + static Policy fromPb(com.google.api.services.cloudresourcemanager.model.Policy policyPb) { + Builder policyBuilder = Policy.builder(); + if (policyPb.getBindings() != null) { + for (com.google.api.services.cloudresourcemanager.model.Binding bindingPb : + policyPb.getBindings()) { + policyBuilder.addBinding(Binding.fromPb(bindingPb)); + } + } + policyBuilder.version(policyPb.getVersion()); + policyBuilder.etag(policyPb.getEtag()); + return policyBuilder.build(); + } +} 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 new file mode 100644 index 000000000000..1813d1083018 --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Project.java @@ -0,0 +1,96 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.gcloud.spi.ResourceManagerRpc.Permission; + +import java.util.ArrayList; +import java.util.List; + +/** + * 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. + */ +public class Project { + + private final ResourceManager resourceManager; + private final ProjectInfo info; + private final Policy policy; + + public Project(ResourceManager resourceManager, ProjectInfo projectInfo, Policy policy) { + this.resourceManager = checkNotNull(resourceManager); + this.info = checkNotNull(projectInfo); + this.policy = checkNotNull(policy); + } + + public static Project load(ResourceManager resourceManager, String projectId) { + ProjectInfo projectInfo = resourceManager.get(projectId); + Policy policy = resourceManager.getIamPolicy(projectId); + return new Project(resourceManager, projectInfo, policy); + } + + public ProjectInfo info() { + return info; + } + + public Policy policy() { + return policy; + } + + public ResourceManager resourceManager() { + return resourceManager; + } + + public Project reload() { + return new Project( + resourceManager, resourceManager.get(info.id()), resourceManager.getIamPolicy(info.id())); + } + + public void delete() { + resourceManager.delete(info.id()); + } + + public void undelete() { + resourceManager.undelete(info.id()); + } + + public Project replace(ProjectInfo projectInfo) { + return new Project(resourceManager, resourceManager.replace(checkNotNull(projectInfo)), policy); + } + + public Project replaceIamPolicy(Policy policy) { + return new Project( + resourceManager, info, resourceManager.replaceIamPolicy(info.id(), checkNotNull(policy))); + } + + public List hasPermissions(Permission first, Permission... others) { + List permissions = new ArrayList<>(); + permissions.add(first); + for (Permission other : others) { + permissions.add(other); + } + return resourceManager.hasPermissions(info.id(), permissions); + } + + public boolean hasAllPermissions(Permission first, Permission... others) { + return !(hasPermissions(first, others).contains(false)); + } +} 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 new file mode 100644 index 000000000000..d69f94c530d5 --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ProjectInfo.java @@ -0,0 +1,238 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.collect.ImmutableMap; + +import org.joda.time.DateTime; +import org.joda.time.format.ISODateTimeFormat; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * A Google Cloud Resource Manager project metadata object. + */ +public class ProjectInfo implements Serializable { + + private static final long serialVersionUID = 9148970963697734236L; + private final String name; + private final String id; + private final Map labels; + private final Long number; + private final State state; + private final Long createTimeMillis; + private final ResourceId parent; + + public enum State { + LIFECYCLE_STATE_UNSPECIFIED, + ACTIVE, + DELETE_REQUESTED, + DELETE_IN_PROGRESS; + } + + public static class Builder { + private String name; + private String id; + private Map labels; + private Long number; + private State state; + private Long createTimeMillis; + private ResourceId parent; + + Builder() { + labels = new HashMap(); + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder addLabel(String key, String value) { + this.labels.put(key, value); + return this; + } + + public Builder removeLabel(String key) { + this.labels.remove(key); + return this; + } + + public Builder clearLabels() { + this.labels.clear(); + return this; + } + + public Builder labels(Map labels) { + this.labels = checkNotNull(labels); + return this; + } + + Builder number(Long number) { + this.number = number; + return this; + } + + Builder state(State state) { + this.state = state; + return this; + } + + Builder createTimeMillis(Long createTimeMillis) { + this.createTimeMillis = createTimeMillis; + return this; + } + + public Builder parent(ResourceId parent) { + this.parent = parent; + return this; + } + + public ProjectInfo build() { + return new ProjectInfo(name, id, labels, number, state, createTimeMillis, parent); + } + } + + ProjectInfo(String name, String id, Map labels, Long number, State state, + Long createTimeMillis, ResourceId parent) { + this.name = name; + this.id = checkNotNull(id); + ImmutableMap.Builder labelsMapBuilder = ImmutableMap.builder(); + for (Map.Entry entry : labels.entrySet()) { + labelsMapBuilder.put(entry.getKey(), entry.getValue()); + } + this.labels = (labels == null) ? null : labelsMapBuilder.build(); + this.number = number; + this.state = state; + this.createTimeMillis = createTimeMillis; + this.parent = parent; + } + + public String id() { + return id; + } + + public String name() { + return name; + } + + public Long number() { + return number; + } + + public Map labels() { + return labels; + } + + public State state() { + return state; + } + + public Long createTimeMillis() { + return createTimeMillis; + } + + public ResourceId parent() { + return parent; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof ProjectInfo) { + ProjectInfo other = (ProjectInfo) obj; + return Objects.equals(this.name, other.name) && Objects.equals(this.id, other.id) + && Objects.equals(this.labels, other.labels) && Objects.equals(this.number, other.number) + && Objects.equals(this.state, other.state) + && Objects.equals(this.createTimeMillis, other.createTimeMillis) + && Objects.equals(this.parent, other.parent); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(name, id, labels, number, state, createTimeMillis, parent); + } + + public static Builder builder(String id) { + return new Builder().id(id); + } + + public Builder toBuilder() { + Map mutableLabels = new HashMap(); + for (Map.Entry entry : labels.entrySet()) { + mutableLabels.put(entry.getKey(), entry.getValue()); + } + return new Builder() + .name(name) + .id(id) + .labels(mutableLabels) + .number(number) + .state(state) + .createTimeMillis(createTimeMillis) + .parent(parent); + } + + 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.setLabels(labels); + projectPb.setProjectNumber(number); + 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()) + .number(projectPb.getProjectNumber()); + 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/ResourceId.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java new file mode 100644 index 000000000000..c640709d6faa --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java @@ -0,0 +1,82 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Represents a Google Cloud Resource Manager Resource ID + */ +public class ResourceId implements Serializable { + + private static final long serialVersionUID = 7928469304338358885L; + private final String id; + private final Type type; + + public enum Type { + ORGANIZATION("organization"), + UNKNOWN("unknown"); + + private final String strValue; + + Type(String strValue) { + this.strValue = strValue; + } + } + + private ResourceId(String id, Type type) { + this.id = checkNotNull(id); + this.type = checkNotNull(type); + } + + public String id() { + return id; + } + + public Type type() { + return type; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof ResourceId && Objects.equals(this.id, ((ResourceId) obj).id) + && Objects.equals(this.type, ((ResourceId) obj).type); + } + + @Override + public int hashCode() { + return Objects.hash(id, type); + } + + public static ResourceId of(String id, Type type) { + return new ResourceId(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.strValue); + return resourceIdPb; + } + + static ResourceId fromPb( + com.google.api.services.cloudresourcemanager.model.ResourceId resourceIdPb) { + return new ResourceId(resourceIdPb.getId(), Type.valueOf(resourceIdPb.getType().toUpperCase())); + } +} 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 8a9966faa653..29fddd409e8a 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 @@ -16,7 +16,12 @@ package com.google.gcloud.resourcemanager; +import com.google.gcloud.Page; import com.google.gcloud.Service; +import com.google.gcloud.spi.ResourceManagerRpc.ListOptions; +import com.google.gcloud.spi.ResourceManagerRpc.Permission; + +import java.util.List; /** * An interface for Google Cloud Resource Manager. @@ -27,5 +32,78 @@ public interface ResourceManager extends Service { public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; - // TODO(ajaykannan): Fix me! Add in missing methods. + /** + * Create a new project. + * + * @return ProjectInfo object representing the new project's metadata. The returned object will + * include additional read-only information, namely project number, lifecycle state, and creation + * time. + * @throws ResourceManagerException upon failure + */ + ProjectInfo create(ProjectInfo project); + + /** + * Delete the requested project. + * + * @throws ResourceManagerException upon failure + */ + void delete(String projectId); + + /** + * Return the requested project or {@code null} if not found. + * + * @throws ResourceManagerException upon failure + */ + ProjectInfo get(String projectId); + + /** + * List the projects viewable by the current user. Use {@link ListOptions} to filter this list, + * set page size, and set page tokens. Note that pagination is currently not implemented by the + * Cloud Resource Manager API. + * + * @return {@code Page}, a paginated list of projects. + * @throws ResourceManagerException upon failure + */ + Page list(ListOptions listOptions); + + /** + * Replace project metadata. + * + * @return the ProjectInfo representing the new project metadata + * @throws ResourceManagerException upon failure + */ + ProjectInfo replace(ProjectInfo newProject); + + /** + * Undo a delete request. This will only succeed if the project's lifecycle state is + * DELETE_REQUESTED. + * + * @throws ResourceManagerException + */ + void undelete(String projectId); + + /** + * Get the IAM policy for the project specified. + * + * @return IAM Policy + * @throws ResourceManagerException upon failure + */ + Policy getIamPolicy(String projectId); + + /** + * Replace the IAM Policy for a project with the policy given. + * + * @return the new IAM Policy + * @throws ResourceManagerException upon failure + */ + Policy replaceIamPolicy(String projectId, Policy policy); + + /** + * Test whether the caller of this function has the permissions provided as arguments. + * + * @return List of booleans representing whether the caller has the corresponding permission in + * the given permissions list. + * @throws ResourceManagerException upon failure + */ + List hasPermissions(String projectId, List permissions); } 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 e136db8fd339..8287ed167557 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 @@ -16,6 +16,7 @@ package com.google.gcloud.resourcemanager; +import com.google.gcloud.BaseServiceException; import com.google.gcloud.RetryHelper.RetryHelperException; import com.google.gcloud.RetryHelper.RetryInterruptedException; @@ -25,29 +26,13 @@ * @see Google Cloud * Resource Manager error codes */ -public class ResourceManagerException extends RuntimeException { +public class ResourceManagerException extends BaseServiceException { private static final long serialVersionUID = 6841689911565501705L; private static final int UNKNOWN_CODE = -1; - private final int code; - private final boolean retryable; - public ResourceManagerException(int code, String message, boolean retryable) { - super(message); - this.code = code; - this.retryable = retryable; - } - - /** - * Returns the code associated with this exception. - */ - public int code() { - return code; - } - - public boolean retryable() { - return retryable; + super(code, message, retryable); } /** @@ -60,6 +45,6 @@ public boolean retryable() { */ static ResourceManagerException translateAndThrow(RetryHelperException ex) { throw new ResourceManagerException(UNKNOWN_CODE, ex.getMessage(), false); - // TODO(ajaykannan): Fix me! + // TODO(ajaykannan): Fix me! } } diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java index e43609be95c1..51d8e5411212 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java @@ -70,6 +70,11 @@ private ResourceManagerOptions(Builder builder) { super(ResourceManagerFactory.class, ResourceManagerRpcFactory.class, builder); } + @Override + protected boolean projectIdRequired() { + return false; + } + @Override protected ResourceManagerFactory defaultServiceFactory() { return DefaultResourceManagerFactory.INSTANCE; diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java index 1223627bbfcb..9410891771c9 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java @@ -29,13 +29,24 @@ public interface ResourceManagerRpc { public enum Permission { - CREATE, - DELETE, - GET, - LIST, - REPLACE, - GET_IAM_POLICY, - REPLACE_IAM_POLICY + CREATE("resourcemanager.projects.create"), + DELETE("resourcemanager.projects.delete"), + GET("resourcemanager.projects.get"), + LIST("resourcemanager.projects.list"), + REPLACE("resourcemanager.projects.replace"), + UNDELETE("resourcemanager.projects.undelete"), + GET_IAM_POLICY("resourcemanager.projects.getIamPolicy"), + REPLACE_IAM_POLICY("resourcemanager.projects.setIamPolicy"); + + String permissionPb; + + Permission(String permissionPb) { + this.permissionPb = permissionPb; + } + + String toPb() { + return permissionPb; + } } class Tuple { @@ -110,7 +121,7 @@ public int pageSize() { Policy getIamPolicy(String projectId) throws ResourceManagerException; - boolean replaceIamPolicy(String projectId, Policy policy) throws ResourceManagerException; + Policy replaceIamPolicy(String projectId, Policy policy) throws ResourceManagerException; List hasPermissions(String projectId, List permissions) throws ResourceManagerException; diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java new file mode 100644 index 000000000000..77037d2996c6 --- /dev/null +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java @@ -0,0 +1,108 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import com.google.gcloud.resourcemanager.Policy.Binding; +import com.google.gcloud.resourcemanager.Policy.Member; +import com.google.gcloud.resourcemanager.Policy.RoleType; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class PolicyTest { + + private static final Binding OWNER_BINDING; + private static final Binding EDITOR_BINDING; + private static final Binding VIEWER_BINDING; + private static final Binding EMPTY_BINDING = Policy.Binding.builder().build(); + private static final List OWNER_MEMBER_LIST = new ArrayList<>(); + private static final List EDITOR_MEMBER_LIST = new ArrayList<>(); + private static final List VIEWER_MEMBER_LIST = new ArrayList<>(); + static { + OWNER_MEMBER_LIST.add(Member.user("first-owner@email.com")); + OWNER_MEMBER_LIST.add(Member.group("group-of-owners@email.com")); + OWNER_BINDING = + Policy.Binding.builder().role(RoleType.OWNER).members(OWNER_MEMBER_LIST).build(); + EDITOR_MEMBER_LIST.add(Member.serviceAccount("editor@someemail.com")); + EDITOR_BINDING = + Policy.Binding.builder().role(RoleType.EDITOR).members(EDITOR_MEMBER_LIST).build(); + VIEWER_MEMBER_LIST.add(Member.serviceAccount("app@someemail.com")); + VIEWER_MEMBER_LIST.add(Member.user("viewer@email.com")); + VIEWER_BINDING = + Policy.Binding.builder().role(RoleType.VIEWER).members(VIEWER_MEMBER_LIST).build(); + } + private static final Policy EMPTY_POLICY = Policy.builder().build(); + private static final Integer VERSION = 1; + private static final String ETAG = "some-etag-value"; + private static final Policy FULL_POLICY = + Policy.builder() + .addBinding(OWNER_BINDING) + .addBinding(EDITOR_BINDING) + .addBinding(VIEWER_BINDING) + .version(VERSION) + .etag(ETAG) + .build(); + + @Test + public void testBindingBuilder() { + assertEquals(OWNER_BINDING.role(), RoleType.OWNER); + assertEquals(OWNER_BINDING.members(), OWNER_MEMBER_LIST); + assertNull(EMPTY_BINDING.role()); + assertTrue(EMPTY_BINDING.members().isEmpty()); + } + + @Test + public void testBindingToBuilder() { + assertEquals(OWNER_BINDING, OWNER_BINDING.toBuilder().build()); + assertEquals(EMPTY_BINDING, EMPTY_BINDING.toBuilder().build()); + } + + @Test + public void testBindingToAndFromPb() { + assertEquals(OWNER_BINDING, Binding.fromPb(OWNER_BINDING.toPb())); + assertEquals(EDITOR_BINDING, Binding.fromPb(EDITOR_BINDING.toPb())); + assertEquals(VIEWER_BINDING, Binding.fromPb(VIEWER_BINDING.toPb())); + assertEquals(EMPTY_BINDING, Binding.fromPb(EMPTY_BINDING.toPb())); + } + + @Test + public void testPolicyBuilder() { + assertEquals(OWNER_BINDING, FULL_POLICY.bindings().get(0)); + assertEquals(EDITOR_BINDING, FULL_POLICY.bindings().get(1)); + assertEquals(VIEWER_BINDING, FULL_POLICY.bindings().get(2)); + assertEquals(VERSION, FULL_POLICY.version()); + assertEquals(ETAG, FULL_POLICY.etag()); + } + + @Test + public void testPolicyToBuilder() { + assertEquals(FULL_POLICY, FULL_POLICY.toBuilder().build()); + assertEquals(EMPTY_POLICY, EMPTY_POLICY.toBuilder().build()); + } + + @Test + public void testPolicyToAndFromPb() { + assertEquals(EMPTY_POLICY, Policy.fromPb(EMPTY_POLICY.toPb())); + assertEquals(FULL_POLICY, Policy.fromPb(FULL_POLICY.toPb())); + } +} diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java new file mode 100644 index 000000000000..d6e27aecd103 --- /dev/null +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class ProjectInfoTest { + + private static final String ID = "project-id"; + private static final String NAME = "myProj"; + private static final Map LABELS = new HashMap(); + static { + LABELS.put("k1", "v1"); + LABELS.put("k2", "k2"); + } + private static final Long NUMBER = 123L; + private static final Long CREATE_TIME_MILLIS = 123456789L; + private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; + private static final ResourceId PARENT = ResourceId.of("owner-id", ResourceId.Type.ORGANIZATION); + private static final ProjectInfo FULL_PROJECT_INFO = + ProjectInfo.builder(ID) + .name(NAME) + .labels(LABELS) + .number(NUMBER) + .createTimeMillis(CREATE_TIME_MILLIS) + .state(STATE) + .parent(PARENT) + .build(); + private static final ProjectInfo PARTIAL_PROJECT_INFO = ProjectInfo.builder(ID).build(); + + @Test + public void testBuilder() { + assertEquals(ID, FULL_PROJECT_INFO.id()); + assertEquals(NAME, FULL_PROJECT_INFO.name()); + assertEquals(LABELS, FULL_PROJECT_INFO.labels()); + assertEquals(NUMBER, FULL_PROJECT_INFO.number()); + assertEquals(CREATE_TIME_MILLIS, FULL_PROJECT_INFO.createTimeMillis()); + assertEquals(STATE, FULL_PROJECT_INFO.state()); + assertEquals(PARENT, FULL_PROJECT_INFO.parent()); + } + + @Test + public void testToBuilder() { + assertEquals(FULL_PROJECT_INFO, FULL_PROJECT_INFO.toBuilder().build()); + assertEquals(PARTIAL_PROJECT_INFO, PARTIAL_PROJECT_INFO.toBuilder().build()); + } + + @Test + public void testToAndFromPb() { + assertEquals(FULL_PROJECT_INFO, ProjectInfo.fromPb(FULL_PROJECT_INFO.toPb())); + assertEquals(PARTIAL_PROJECT_INFO, ProjectInfo.fromPb(PARTIAL_PROJECT_INFO.toPb())); + } +} + diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java new file mode 100644 index 000000000000..6d36c024d0d2 --- /dev/null +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java @@ -0,0 +1,214 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static org.easymock.EasyMock.createStrictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import com.google.gcloud.resourcemanager.Policy.Binding; +import com.google.gcloud.resourcemanager.Policy.Member; +import com.google.gcloud.resourcemanager.Policy.RoleType; +import com.google.gcloud.spi.ResourceManagerRpc.Permission; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ProjectTest { + private static final String ID = "project-id"; + private static final String NAME = "myProj"; + private static final Map LABELS = new HashMap(); + static { + LABELS.put("k1", "v1"); + LABELS.put("k2", "k2"); + } + private static final Long NUMBER = 123L; + private static final Long CREATE_TIME_MILLIS = 123456789L; + private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; + private static final ResourceId PARENT = ResourceId.of("owner-id", ResourceId.Type.ORGANIZATION); + private static final ProjectInfo PROJECT_INFO = + ProjectInfo.builder(ID) + .name(NAME) + .labels(LABELS) + .number(NUMBER) + .createTimeMillis(CREATE_TIME_MILLIS) + .state(STATE) + .parent(PARENT) + .build(); + private static final Binding OWNER_BINDING; + private static final Binding EDITOR_BINDING; + private static final Binding VIEWER_BINDING; + static { + List ownerMemberList = new ArrayList<>(); + List editorMemberList = new ArrayList<>(); + List viewerMemberList = new ArrayList<>(); + + ownerMemberList.add(Member.user("first-owner@email.com")); + ownerMemberList.add(Member.group("group-of-owners@email.com")); + OWNER_BINDING = Policy.Binding.builder().role(RoleType.OWNER).members(ownerMemberList).build(); + editorMemberList.add(Member.serviceAccount("editor@someemail.com")); + EDITOR_BINDING = + Policy.Binding.builder().role(RoleType.EDITOR).members(editorMemberList).build(); + viewerMemberList.add(Member.serviceAccount("app@someemail.com")); + viewerMemberList.add(Member.user("viewer@email.com")); + VIEWER_BINDING = + Policy.Binding.builder().role(RoleType.VIEWER).members(viewerMemberList).build(); + } + private static final Policy POLICY = + Policy.builder() + .addBinding(OWNER_BINDING) + .addBinding(EDITOR_BINDING) + .addBinding(VIEWER_BINDING) + .version(1) + .etag("some-etag-value") + .build(); + private static final List PERMISSIONS_REQUESTED = + Arrays.asList(new Permission[] {Permission.REPLACE, Permission.GET}); + private static final List PERMISSIONS_OWNED = Arrays.asList(new Boolean[] {false, true}); + + private ResourceManager resourceManager; + private Project project; + + @Before + public void setUp() throws Exception { + resourceManager = createStrictMock(ResourceManager.class); + project = new Project(resourceManager, PROJECT_INFO, POLICY); + } + + @After + public void tearDown() throws Exception { + verify(resourceManager); + } + + @Test + public void testLoad() { + expect(resourceManager.get(PROJECT_INFO.id())).andReturn(PROJECT_INFO); + expect(resourceManager.getIamPolicy(PROJECT_INFO.id())).andReturn(POLICY); + replay(resourceManager); + Project loadedProject = Project.load(resourceManager, PROJECT_INFO.id()); + assertEquals(PROJECT_INFO, loadedProject.info()); + assertEquals(POLICY, loadedProject.policy()); + } + + @Test + public void testReload() { + ProjectInfo newInfo = PROJECT_INFO.toBuilder().addLabel("k3", "v3").build(); + Policy newPolicy = POLICY.toBuilder().removeBinding(VIEWER_BINDING).build(); + expect(resourceManager.get(PROJECT_INFO.id())).andReturn(newInfo); + expect(resourceManager.getIamPolicy(PROJECT_INFO.id())).andReturn(newPolicy); + replay(resourceManager); + Project newProject = project.reload(); + assertSame(resourceManager, newProject.resourceManager()); + assertEquals(newInfo, newProject.info()); + assertEquals(newPolicy, newProject.policy()); + } + + @Test + public void testPolicy() { + assertEquals(project.policy(), POLICY); + replay(resourceManager); + } + + @Test + public void testInfo() { + assertEquals(project.info(), PROJECT_INFO); + replay(resourceManager); + } + + @Test + public void testResourceManager() { + assertEquals(project.resourceManager(), resourceManager); + replay(resourceManager); + } + + @Test + public void testDelete() { + resourceManager.delete(PROJECT_INFO.id()); + expectLastCall(); + replay(resourceManager); + project.delete(); + } + + @Test + public void testUndelete() { + resourceManager.undelete(PROJECT_INFO.id()); + expectLastCall(); + replay(resourceManager); + project.undelete(); + } + + @Test + public void testReplace() { + ProjectInfo newInfo = PROJECT_INFO.toBuilder().addLabel("k3", "v3").build(); + expect(resourceManager.replace(newInfo)).andReturn(newInfo); + replay(resourceManager); + Project newProject = project.replace(newInfo); + assertSame(newProject.resourceManager(), resourceManager); + assertEquals(newProject.info(), newInfo); + assertEquals(newProject.policy(), POLICY); + } + + @Test + public void testReplaceIamPolicy() { + Policy newPolicy = POLICY.toBuilder().removeBinding(VIEWER_BINDING).build(); + expect(resourceManager.replaceIamPolicy(PROJECT_INFO.id(), newPolicy)).andReturn(newPolicy); + replay(resourceManager); + Project newProject = project.replaceIamPolicy(newPolicy); + assertSame(newProject.resourceManager(), resourceManager); + assertEquals(newProject.info(), PROJECT_INFO); + assertEquals(newProject.policy(), newPolicy); + } + + @Test + public void testHasPermissions() { + expect(resourceManager.hasPermissions(PROJECT_INFO.id(), PERMISSIONS_REQUESTED)) + .andReturn(PERMISSIONS_OWNED); + replay(resourceManager); + List response = + project.hasPermissions(PERMISSIONS_REQUESTED.get(0), PERMISSIONS_REQUESTED.get(1)); + assertEquals(response, PERMISSIONS_OWNED); + } + + @Test + public void testHasAllPermissions() { + expect(resourceManager.hasPermissions(PROJECT_INFO.id(), PERMISSIONS_REQUESTED)) + .andReturn(PERMISSIONS_OWNED); + List permissionsRequested2 = + Arrays.asList(new Permission[] {Permission.UNDELETE, Permission.DELETE}); + List permissionsOwned2 = Arrays.asList(new Boolean[] {true, true}); + expect(resourceManager.hasPermissions(PROJECT_INFO.id(), permissionsRequested2)) + .andReturn(permissionsOwned2); + replay(resourceManager); + assertFalse( + project.hasAllPermissions(PERMISSIONS_REQUESTED.get(0), PERMISSIONS_REQUESTED.get(1))); + assertTrue( + project.hasAllPermissions(permissionsRequested2.get(0), permissionsRequested2.get(1))); + } +} diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java new file mode 100644 index 000000000000..1f66017312a6 --- /dev/null +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class ResourceIdTest { + +private static final ResourceId RESOURCE_ID = ResourceId.of("id", ResourceId.Type.ORGANIZATION); + + @Test + public void testOf() { + assertEquals(RESOURCE_ID.id(), "id"); + assertEquals(RESOURCE_ID.type(), ResourceId.Type.ORGANIZATION); + } + + @Test + public void testEquals() { + assertEquals(RESOURCE_ID, ResourceId.of("id", ResourceId.Type.ORGANIZATION)); + } + + @Test + public void testToAndFromPb() { + assertEquals(RESOURCE_ID, ResourceId.fromPb(RESOURCE_ID.toPb())); + } +} diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java new file mode 100644 index 000000000000..e848c3a61680 --- /dev/null +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java @@ -0,0 +1,126 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; + +import com.google.gcloud.AuthCredentials; +import com.google.gcloud.PageImpl; +import com.google.gcloud.RetryParams; +import com.google.gcloud.resourcemanager.Policy.Binding; +import com.google.gcloud.resourcemanager.Policy.Member; +import com.google.gcloud.resourcemanager.Policy.RoleType; + +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SerializationTest { + + private static final ResourceId RESOURCE_ID = + ResourceId.of("some id", ResourceId.Type.ORGANIZATION); + private static final Binding OWNER_BINDING; + private static final Binding EDITOR_BINDING; + private static final Binding VIEWER_BINDING; + private static final Binding EMPTY_BINDING = Policy.Binding.builder().build(); + static { + List ownerMemberList = new ArrayList<>(); + List editorMemberList = new ArrayList<>(); + List viewerMemberList = new ArrayList<>(); + ownerMemberList.add(Member.user("first-owner@email.com")); + ownerMemberList.add(Member.group("group-of-owners@email.com")); + OWNER_BINDING = Policy.Binding.builder().role(RoleType.OWNER).members(ownerMemberList).build(); + editorMemberList.add(Member.serviceAccount("editor@someemail.com")); + EDITOR_BINDING = + Policy.Binding.builder().role(RoleType.EDITOR).members(editorMemberList).build(); + viewerMemberList.add(Member.serviceAccount("app@someemail.com")); + viewerMemberList.add(Member.user("viewer@email.com")); + VIEWER_BINDING = + Policy.Binding.builder().role(RoleType.VIEWER).members(viewerMemberList).build(); + } + private static final Policy POLICY = + Policy.builder() + .addBinding(OWNER_BINDING) + .addBinding(EDITOR_BINDING) + .addBinding(VIEWER_BINDING) + .version(1) + .etag("some-etag-value") + .build(); + private static final Policy EMPTY_POLICY = Policy.builder().build(); + private static final ProjectInfo PROJECT_INFO1 = ProjectInfo.builder("id1").build(); + private static final ProjectInfo PROJECT_INFO2; + static { + Map labels = new HashMap(); + labels.put("key", "value"); + PROJECT_INFO2 = + new ProjectInfo("name", "id", labels, 123L, ProjectInfo.State.ACTIVE, 1234L, RESOURCE_ID); + } + private static final PageImpl PAGE_RESULT = + new PageImpl<>(null, "c", Collections.singletonList(PROJECT_INFO1)); + + @Test + public void testServiceOptions() throws Exception { + ResourceManagerOptions options = ResourceManagerOptions.builder().build(); + ResourceManagerOptions serializedCopy = serializeAndDeserialize(options); + assertEquals(options, serializedCopy); + options = + options.toBuilder() + .projectId("some-unnecessary-project-ID") + .retryParams(RetryParams.defaultInstance()) + .authCredentials(AuthCredentials.noCredentials()) + .build(); + serializedCopy = serializeAndDeserialize(options); + assertEquals(options, serializedCopy); + } + + @Test + public void testModelAndRequests() throws Exception { + Serializable[] objects = {RESOURCE_ID, OWNER_BINDING.members().get(0), OWNER_BINDING, + EDITOR_BINDING, VIEWER_BINDING, EMPTY_BINDING, POLICY, EMPTY_POLICY, PROJECT_INFO1, + PROJECT_INFO2, PAGE_RESULT}; + for (Serializable obj : objects) { + Object copy = serializeAndDeserialize(obj); + assertEquals(obj, obj); + assertEquals(obj, copy); + assertNotSame(obj, copy); + assertEquals(copy, copy); + } + } + + @SuppressWarnings("unchecked") + private T serializeAndDeserialize(T obj) throws IOException, ClassNotFoundException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + try (ObjectOutputStream output = new ObjectOutputStream(bytes)) { + output.writeObject(obj); + } + try (ObjectInputStream input = + new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) { + return (T) input.readObject(); + } + } +} From 8efaa54f2d32d84d18a8b1817c484ea5dacc1004 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Mon, 16 Nov 2015 17:18:12 -0800 Subject: [PATCH 02/10] Fix style, simplify equals methods, fix tests, and add Project javadocs --- .../google/gcloud/resourcemanager/Policy.java | 102 +++++++----------- .../gcloud/resourcemanager/Project.java | 65 +++++++++-- .../gcloud/resourcemanager/ProjectInfo.java | 44 +++----- .../gcloud/resourcemanager/ResourceId.java | 15 +-- .../resourcemanager/ResourceManager.java | 21 ++-- .../ResourceManagerOptions.java | 7 ++ .../gcloud/resourcemanager/PolicyTest.java | 75 +++++++------ .../resourcemanager/ProjectInfoTest.java | 54 ++++++++-- .../gcloud/resourcemanager/ProjectTest.java | 84 ++++++--------- .../resourcemanager/ResourceIdTest.java | 20 +++- .../resourcemanager/SerializationTest.java | 64 +++++------ 11 files changed, 295 insertions(+), 256 deletions(-) diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java index 765e38d3c2f8..efa95d9f7c73 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import java.io.Serializable; import java.util.ArrayList; @@ -122,6 +123,32 @@ public boolean equals(Object obj) { return obj instanceof Member && Objects.equals(this.memberType, ((Member) obj).memberType) && Objects.equals(this.emailOrDomain, ((Member) obj).emailOrDomain); } + + String toPb() { + return emailOrDomain != null ? memberType.prefix() + emailOrDomain : memberType.prefix(); + } + + static Member fromPb(String memberPb) { + String[] memberInfo = memberPb.split(":", 2); + String memberStr = memberInfo[0]; + String emailOrDomain = (memberInfo.length > 1) ? memberInfo[1] : null; + switch (memberStr) { + case "allUsers": + return new Member(MemberType.ALL_USERS, null); + case "allAuthenticatedUsers": + return new Member(MemberType.ALL_AUTHENTICATED_USERS, null); + case "user": + return new Member(MemberType.USER, checkNotNull(emailOrDomain)); + case "serviceAccount": + return new Member(MemberType.SERVICE_ACCOUNT, checkNotNull(emailOrDomain)); + case "group": + return new Member(MemberType.GROUP, checkNotNull(emailOrDomain)); + case "domain": + return new Member(MemberType.DOMAIN, checkNotNull(emailOrDomain)); + default: + throw new UnsupportedOperationException("Unsupported member type: " + memberStr); + } + } } /** @@ -147,7 +174,7 @@ public Builder role(RoleType role) { } public Builder members(List members) { - this.members = checkNotNull(members); + this.members = Lists.newArrayList(checkNotNull(members)); return this; } @@ -172,15 +199,11 @@ public Binding build() { } private Binding(RoleType role, List members) { - this.role = role; - ImmutableList.Builder membersListBuilder = new ImmutableList.Builder<>(); - for (Member member : members) { - membersListBuilder.add(member); - } - this.members = membersListBuilder.build(); + this.role = checkNotNull(role); + this.members = ImmutableList.copyOf(members); } - public static Binding binding(RoleType role, List members) { + public static Binding of(RoleType role, List members) { return new Binding(role, members); } @@ -197,26 +220,16 @@ public static Builder builder() { } public Builder toBuilder() { - List mutableMembers = new ArrayList<>(); - for (Member member : members) { - mutableMembers.add(member); - } - return new Builder().role(role).members(mutableMembers); + return new Builder().role(role).members(members); } com.google.api.services.cloudresourcemanager.model.Binding toPb() { com.google.api.services.cloudresourcemanager.model.Binding bindingPb = new com.google.api.services.cloudresourcemanager.model.Binding(); - if (role != null) { - bindingPb.setRole("roles/" + role.toString().toLowerCase()); - } + bindingPb.setRole("roles/" + role.toString().toLowerCase()); List membersPb = new ArrayList<>(members.size()); for (Member member : members) { - if (member.emailOrDomain() != null) { - membersPb.add(member.type().prefix() + member.emailOrDomain()); - } else { - membersPb.add(member.type().prefix()); - } + membersPb.add(member.toPb()); } bindingPb.setMembers(membersPb); return bindingPb; @@ -229,31 +242,7 @@ static Binding fromPb(com.google.api.services.cloudresourcemanager.model.Binding List members = new ArrayList<>(); if (bindingPb.getMembers() != null) { for (String memberPb : bindingPb.getMembers()) { - String[] memberInfo = memberPb.split(":", 2); - String memberTypeStr = memberInfo[0]; - String emailOrDomain = (memberInfo.length > 1) ? emailOrDomain = memberInfo[1] : null; - switch (memberTypeStr) { - case "allUsers": - members.add(new Member(MemberType.ALL_USERS, null)); - break; - case "allAuthenticatedUsers": - members.add(new Member(MemberType.ALL_AUTHENTICATED_USERS, null)); - break; - case "user": - members.add(new Member(MemberType.USER, checkNotNull(emailOrDomain))); - break; - case "serviceAccount": - members.add(new Member(MemberType.SERVICE_ACCOUNT, checkNotNull(emailOrDomain))); - break; - case "group": - members.add(new Member(MemberType.GROUP, checkNotNull(emailOrDomain))); - break; - case "domain": - members.add(new Member(MemberType.DOMAIN, checkNotNull(emailOrDomain))); - break; - default: - throw new UnsupportedOperationException("Unsupported member type: " + memberTypeStr); - } + members.add(Member.fromPb(memberPb)); } } return new Binding(role, members); @@ -266,8 +255,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { - return obj instanceof Binding && Objects.equals(this.role, ((Binding) obj).role) - && Objects.equals(this.members, ((Binding) obj).members); + return obj instanceof Binding && Objects.equals(toPb(), ((Binding) obj).toPb()); } } @@ -296,7 +284,7 @@ public Builder clearBindings() { } public Builder bindings(List bindings) { - this.bindings = checkNotNull(bindings); + this.bindings = new ArrayList<>(checkNotNull(bindings)); return this; } @@ -316,11 +304,7 @@ public Policy build() { } Policy(Builder builder) { - ImmutableList.Builder bindingsListBuilder = new ImmutableList.Builder<>(); - for (Binding binding : builder.bindings) { - bindingsListBuilder.add(binding); - } - bindings = bindingsListBuilder.build(); + bindings = ImmutableList.copyOf(builder.bindings); version = builder.version; etag = builder.etag; } @@ -342,11 +326,7 @@ public static Builder builder() { } public Builder toBuilder() { - List mutableBindings = new ArrayList<>(); - for (Binding binding : bindings) { - mutableBindings.add(binding); - } - return new Builder().bindings(mutableBindings).etag(etag).version(version); + return new Builder().bindings(bindings).etag(etag).version(version); } @Override @@ -356,9 +336,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { - return obj instanceof Policy && Objects.equals(this.bindings, ((Policy) obj).bindings) - && Objects.equals(this.etag, ((Policy) obj).etag) - && Objects.equals(this.version, ((Policy) obj).version); + return obj instanceof Policy && Objects.equals(toPb(), ((Policy) obj).toPb()); } com.google.api.services.cloudresourcemanager.model.Policy toPb() { 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 1813d1083018..74296a0be773 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 @@ -20,7 +20,6 @@ import com.google.gcloud.spi.ResourceManagerRpc.Permission; -import java.util.ArrayList; import java.util.List; /** @@ -35,12 +34,22 @@ public class Project { private final ProjectInfo info; private final Policy policy; + /** + * Constructs a Project object that contains the ProjectInfo and Policy given. + */ public Project(ResourceManager resourceManager, ProjectInfo projectInfo, Policy policy) { this.resourceManager = checkNotNull(resourceManager); this.info = checkNotNull(projectInfo); this.policy = checkNotNull(policy); } + /** + * Constructs a Project object that contains project and policy information loaded from the + * server. + * + * @return Project object containing the project's metadata and IAM policy + * @throws ResourceManagerException upon failure + */ public static Project load(ResourceManager resourceManager, String projectId) { ProjectInfo projectInfo = resourceManager.get(projectId); Policy policy = resourceManager.getIamPolicy(projectId); @@ -59,38 +68,76 @@ public ResourceManager resourceManager() { return resourceManager; } + /** + * Returns a Project object with updated project and policy information. + * + * @return Project object containing the project's updated metadata and IAM policy + * @throws ResourceManagerException upon failure + */ public Project reload() { return new Project( resourceManager, resourceManager.get(info.id()), resourceManager.getIamPolicy(info.id())); } + /** + * Requests that this project be deleted. For an unspecified amount of time, this action can be + * undone by calling {@link #undelete}. + * + * @throws ResourceManagerException upon failure + */ public void delete() { resourceManager.delete(info.id()); } + /** + * Requests that a project's lifecycle status be changed from {@code DELETE_REQUESTED} to + * {@code ACTIVE}. + * + * @throws ResourceManagerException upon failure + */ public void undelete() { resourceManager.undelete(info.id()); } + /** + * Replaces the project metadata (not including the IAM policy) using the given ProjectInfo. + * + * @return Project object containing the project's updated metadata + * @throws ResourceManagerException upon failure + */ public Project replace(ProjectInfo projectInfo) { return new Project(resourceManager, resourceManager.replace(checkNotNull(projectInfo)), policy); } + /** + * Replaces the project's IAM policy using the given policy. + * + * @return Project object containing the project's updated IAM policy + * @throws ResourceManagerException upon failure + */ public Project replaceIamPolicy(Policy policy) { return new Project( resourceManager, info, resourceManager.replaceIamPolicy(info.id(), checkNotNull(policy))); } - public List hasPermissions(Permission first, Permission... others) { - List permissions = new ArrayList<>(); - permissions.add(first); - for (Permission other : others) { - permissions.add(other); - } + /** + * Returns whether the caller has the permissions specified in the parameters. + * + * @return List of booleans representing whether the user has the corresponding permission + * provided as a parameter + * @throws ResourceManagerException upon failure + */ + public List hasPermissions(Permission... permissions) { return resourceManager.hasPermissions(info.id(), permissions); } - public boolean hasAllPermissions(Permission first, Permission... others) { - return !(hasPermissions(first, others).contains(false)); + /** + * Returns whether the caller has all the permissions specified in the parameters. + * + * @return true if the caller has all the permissions specified, otherwise false. + * @throws ResourceManagerException upon failure + */ + public boolean hasAllPermissions(Permission... permissions) { + return !(hasPermissions(permissions).contains(false)); } } 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 d69f94c530d5..4e3aed325db7 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 @@ -17,6 +17,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import org.joda.time.DateTime; import org.joda.time.format.ISODateTimeFormat; @@ -86,7 +87,7 @@ public Builder clearLabels() { } public Builder labels(Map labels) { - this.labels = checkNotNull(labels); + this.labels = Maps.newHashMap(checkNotNull(labels)); return this; } @@ -111,23 +112,18 @@ public Builder parent(ResourceId parent) { } public ProjectInfo build() { - return new ProjectInfo(name, id, labels, number, state, createTimeMillis, parent); + return new ProjectInfo(this); } } - ProjectInfo(String name, String id, Map labels, Long number, State state, - Long createTimeMillis, ResourceId parent) { - this.name = name; - this.id = checkNotNull(id); - ImmutableMap.Builder labelsMapBuilder = ImmutableMap.builder(); - for (Map.Entry entry : labels.entrySet()) { - labelsMapBuilder.put(entry.getKey(), entry.getValue()); - } - this.labels = (labels == null) ? null : labelsMapBuilder.build(); - this.number = number; - this.state = state; - this.createTimeMillis = createTimeMillis; - this.parent = parent; + ProjectInfo(Builder builder) { + this.name = builder.name; + this.id = checkNotNull(builder.id); + this.labels = ImmutableMap.copyOf(builder.labels); + this.number = builder.number; + this.state = builder.state; + this.createTimeMillis = builder.createTimeMillis; + this.parent = builder.parent; } public String id() { @@ -160,17 +156,7 @@ public ResourceId parent() { @Override public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (obj instanceof ProjectInfo) { - ProjectInfo other = (ProjectInfo) obj; - return Objects.equals(this.name, other.name) && Objects.equals(this.id, other.id) - && Objects.equals(this.labels, other.labels) && Objects.equals(this.number, other.number) - && Objects.equals(this.state, other.state) - && Objects.equals(this.createTimeMillis, other.createTimeMillis) - && Objects.equals(this.parent, other.parent); - } - return false; + return obj instanceof ProjectInfo && Objects.equals(toPb(), ((ProjectInfo) obj).toPb()); } @Override @@ -183,14 +169,10 @@ public static Builder builder(String id) { } public Builder toBuilder() { - Map mutableLabels = new HashMap(); - for (Map.Entry entry : labels.entrySet()) { - mutableLabels.put(entry.getKey(), entry.getValue()); - } return new Builder() .name(name) .id(id) - .labels(mutableLabels) + .labels(labels) .number(number) .state(state) .createTimeMillis(createTimeMillis) diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java index c640709d6faa..6e6022460e04 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java @@ -29,14 +29,8 @@ public class ResourceId implements Serializable { private final Type type; public enum Type { - ORGANIZATION("organization"), - UNKNOWN("unknown"); - - private final String strValue; - - Type(String strValue) { - this.strValue = strValue; - } + ORGANIZATION, + UNKNOWN; } private ResourceId(String id, Type type) { @@ -54,8 +48,7 @@ public Type type() { @Override public boolean equals(Object obj) { - return obj instanceof ResourceId && Objects.equals(this.id, ((ResourceId) obj).id) - && Objects.equals(this.type, ((ResourceId) obj).type); + return obj instanceof ResourceId && Objects.equals(toPb(), ((ResourceId) obj).toPb()); } @Override @@ -71,7 +64,7 @@ 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.strValue); + resourceIdPb.setType(type.toString().toLowerCase()); return resourceIdPb; } 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 29fddd409e8a..ca6a1cb24b27 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 @@ -35,15 +35,16 @@ public interface ResourceManager extends Service { /** * Create a new project. * - * @return ProjectInfo object representing the new project's metadata. The returned object will - * include additional read-only information, namely project number, lifecycle state, and creation - * time. + * @return ProjectInfo object representing the new project's metadata. The returned object will + * include additional read-only information, namely project number, lifecycle state, and + * creation time. * @throws ResourceManagerException upon failure */ ProjectInfo create(ProjectInfo project); /** - * Delete the requested project. + * Sends a request to delete a project. For an unspecified amount of time, this action can be + * undone using {@link #undelete}. * * @throws ResourceManagerException upon failure */ @@ -57,8 +58,8 @@ public interface ResourceManager extends Service { ProjectInfo get(String projectId); /** - * List the projects viewable by the current user. Use {@link ListOptions} to filter this list, - * set page size, and set page tokens. Note that pagination is currently not implemented by the + * List the projects viewable by the current user. Use {@link ListOptions} to filter this list, + * set page size, and set page tokens. Note that pagination is currently not implemented by the * Cloud Resource Manager API. * * @return {@code Page}, a paginated list of projects. @@ -75,8 +76,8 @@ public interface ResourceManager extends Service { ProjectInfo replace(ProjectInfo newProject); /** - * Undo a delete request. This will only succeed if the project's lifecycle state is - * DELETE_REQUESTED. + * Undo a delete request. This will only succeed if the server processes the undelete request + * while the project's state is {@code DELETE_REQUESTED}. * * @throws ResourceManagerException */ @@ -102,8 +103,8 @@ public interface ResourceManager extends Service { * Test whether the caller of this function has the permissions provided as arguments. * * @return List of booleans representing whether the caller has the corresponding permission in - * the given permissions list. + * the given permissions array. * @throws ResourceManagerException upon failure */ - List hasPermissions(String projectId, List permissions); + List hasPermissions(String projectId, Permission... permissions); } diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java index 51d8e5411212..990163c459da 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java @@ -40,6 +40,13 @@ public ResourceManager create(ResourceManagerOptions options) { } } + /** + * Returns a default {@code ResourceManagerOptions} instance. + */ + public static ResourceManagerOptions defaultInstance() { + return builder().build(); + } + public static class DefaultResourceManagerRpcFactory implements ResourceManagerRpcFactory { private static final ResourceManagerRpcFactory INSTANCE = new DefaultResourceManagerRpcFactory(); diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java index 77037d2996c6..6b52f20f3fae 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java @@ -17,40 +17,31 @@ package com.google.gcloud.resourcemanager; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotEquals; +import com.google.common.collect.ImmutableList; import com.google.gcloud.resourcemanager.Policy.Binding; import com.google.gcloud.resourcemanager.Policy.Member; import com.google.gcloud.resourcemanager.Policy.RoleType; import org.junit.Test; -import java.util.ArrayList; import java.util.List; public class PolicyTest { - private static final Binding OWNER_BINDING; - private static final Binding EDITOR_BINDING; - private static final Binding VIEWER_BINDING; - private static final Binding EMPTY_BINDING = Policy.Binding.builder().build(); - private static final List OWNER_MEMBER_LIST = new ArrayList<>(); - private static final List EDITOR_MEMBER_LIST = new ArrayList<>(); - private static final List VIEWER_MEMBER_LIST = new ArrayList<>(); - static { - OWNER_MEMBER_LIST.add(Member.user("first-owner@email.com")); - OWNER_MEMBER_LIST.add(Member.group("group-of-owners@email.com")); - OWNER_BINDING = - Policy.Binding.builder().role(RoleType.OWNER).members(OWNER_MEMBER_LIST).build(); - EDITOR_MEMBER_LIST.add(Member.serviceAccount("editor@someemail.com")); - EDITOR_BINDING = - Policy.Binding.builder().role(RoleType.EDITOR).members(EDITOR_MEMBER_LIST).build(); - VIEWER_MEMBER_LIST.add(Member.serviceAccount("app@someemail.com")); - VIEWER_MEMBER_LIST.add(Member.user("viewer@email.com")); - VIEWER_BINDING = - Policy.Binding.builder().role(RoleType.VIEWER).members(VIEWER_MEMBER_LIST).build(); - } + private static final List OWNER_MEMBER_LIST = ImmutableList.of( + Member.user("first-owner@email.com"), Member.group("group-of-owners@email.com")); + private static final List EDITOR_MEMBER_LIST = + ImmutableList.of(Member.serviceAccount("editor@someemail.com")); + private static final List VIEWER_MEMBER_LIST = + ImmutableList.of(Member.serviceAccount("app@someemail.com"), Member.user("viewer@email.com")); + private static final Binding OWNER_BINDING = + Policy.Binding.builder().role(RoleType.OWNER).members(OWNER_MEMBER_LIST).build(); + private static final Binding EDITOR_BINDING = + Policy.Binding.builder().role(RoleType.EDITOR).members(EDITOR_MEMBER_LIST).build(); + private static final Binding VIEWER_BINDING = + Policy.Binding.builder().role(RoleType.VIEWER).members(VIEWER_MEMBER_LIST).build(); private static final Policy EMPTY_POLICY = Policy.builder().build(); private static final Integer VERSION = 1; private static final String ETAG = "some-etag-value"; @@ -65,16 +56,13 @@ public class PolicyTest { @Test public void testBindingBuilder() { - assertEquals(OWNER_BINDING.role(), RoleType.OWNER); - assertEquals(OWNER_BINDING.members(), OWNER_MEMBER_LIST); - assertNull(EMPTY_BINDING.role()); - assertTrue(EMPTY_BINDING.members().isEmpty()); + assertEquals(RoleType.OWNER, OWNER_BINDING.role()); + assertEquals(OWNER_MEMBER_LIST, OWNER_BINDING.members()); } @Test public void testBindingToBuilder() { assertEquals(OWNER_BINDING, OWNER_BINDING.toBuilder().build()); - assertEquals(EMPTY_BINDING, EMPTY_BINDING.toBuilder().build()); } @Test @@ -82,7 +70,6 @@ public void testBindingToAndFromPb() { assertEquals(OWNER_BINDING, Binding.fromPb(OWNER_BINDING.toPb())); assertEquals(EDITOR_BINDING, Binding.fromPb(EDITOR_BINDING.toPb())); assertEquals(VIEWER_BINDING, Binding.fromPb(VIEWER_BINDING.toPb())); - assertEquals(EMPTY_BINDING, Binding.fromPb(EMPTY_BINDING.toPb())); } @Test @@ -96,13 +83,35 @@ public void testPolicyBuilder() { @Test public void testPolicyToBuilder() { - assertEquals(FULL_POLICY, FULL_POLICY.toBuilder().build()); - assertEquals(EMPTY_POLICY, EMPTY_POLICY.toBuilder().build()); + comparePolicies(FULL_POLICY, FULL_POLICY.toBuilder().build()); + comparePolicies(EMPTY_POLICY, EMPTY_POLICY.toBuilder().build()); } @Test public void testPolicyToAndFromPb() { - assertEquals(EMPTY_POLICY, Policy.fromPb(EMPTY_POLICY.toPb())); - assertEquals(FULL_POLICY, Policy.fromPb(FULL_POLICY.toPb())); + comparePolicies(FULL_POLICY, Policy.fromPb(FULL_POLICY.toPb())); + comparePolicies(EMPTY_POLICY, Policy.fromPb(EMPTY_POLICY.toPb())); + } + + @Test + public void testEquals() { + comparePolicies( + FULL_POLICY, + Policy.builder() + .addBinding(OWNER_BINDING) + .addBinding(EDITOR_BINDING) + .addBinding(VIEWER_BINDING) + .version(VERSION) + .etag(ETAG) + .build()); + comparePolicies(EMPTY_POLICY, Policy.builder().build()); + assertNotEquals(FULL_POLICY, EMPTY_POLICY); + } + + private void comparePolicies(Policy expected, Policy value) { + assertEquals(expected, value); + assertEquals(expected.bindings(), value.bindings()); + assertEquals(expected.version(), value.version()); + assertEquals(expected.etag(), value.etag()); } } diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java index d6e27aecd103..c0bfb73af3fd 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java @@ -17,21 +17,20 @@ package com.google.gcloud.resourcemanager; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import com.google.common.collect.ImmutableMap; import org.junit.Test; -import java.util.HashMap; import java.util.Map; public class ProjectInfoTest { private static final String ID = "project-id"; private static final String NAME = "myProj"; - private static final Map LABELS = new HashMap(); - static { - LABELS.put("k1", "v1"); - LABELS.put("k2", "k2"); - } + private static final Map LABELS = ImmutableMap.of("k1", "v1", "k2", "v2"); private static final Long NUMBER = 123L; private static final Long CREATE_TIME_MILLIS = 123456789L; private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; @@ -56,18 +55,53 @@ public void testBuilder() { assertEquals(CREATE_TIME_MILLIS, FULL_PROJECT_INFO.createTimeMillis()); assertEquals(STATE, FULL_PROJECT_INFO.state()); assertEquals(PARENT, FULL_PROJECT_INFO.parent()); + + assertEquals(ID, PARTIAL_PROJECT_INFO.id()); + assertEquals(null, PARTIAL_PROJECT_INFO.name()); + assertTrue(PARTIAL_PROJECT_INFO.labels().isEmpty()); + assertEquals(null, PARTIAL_PROJECT_INFO.number()); + assertEquals(null, PARTIAL_PROJECT_INFO.createTimeMillis()); + assertEquals(null, PARTIAL_PROJECT_INFO.state()); + assertEquals(null, PARTIAL_PROJECT_INFO.parent()); } @Test public void testToBuilder() { - assertEquals(FULL_PROJECT_INFO, FULL_PROJECT_INFO.toBuilder().build()); - assertEquals(PARTIAL_PROJECT_INFO, PARTIAL_PROJECT_INFO.toBuilder().build()); + compareProjects(FULL_PROJECT_INFO, FULL_PROJECT_INFO.toBuilder().build()); + compareProjects(PARTIAL_PROJECT_INFO, PARTIAL_PROJECT_INFO.toBuilder().build()); } @Test public void testToAndFromPb() { - assertEquals(FULL_PROJECT_INFO, ProjectInfo.fromPb(FULL_PROJECT_INFO.toPb())); - assertEquals(PARTIAL_PROJECT_INFO, ProjectInfo.fromPb(PARTIAL_PROJECT_INFO.toPb())); + compareProjects(FULL_PROJECT_INFO, ProjectInfo.fromPb(FULL_PROJECT_INFO.toPb())); + compareProjects(PARTIAL_PROJECT_INFO, ProjectInfo.fromPb(PARTIAL_PROJECT_INFO.toPb())); + } + + @Test + public void testEquals() { + compareProjects( + FULL_PROJECT_INFO, + ProjectInfo.builder(ID) + .name(NAME) + .labels(LABELS) + .number(NUMBER) + .createTimeMillis(CREATE_TIME_MILLIS) + .state(STATE) + .parent(PARENT) + .build()); + compareProjects(PARTIAL_PROJECT_INFO, ProjectInfo.builder(ID).build()); + assertNotEquals(FULL_PROJECT_INFO, PARTIAL_PROJECT_INFO); + } + + private void compareProjects(ProjectInfo expected, ProjectInfo value) { + assertEquals(expected, value); + assertEquals(expected.id(), value.id()); + assertEquals(expected.name(), value.name()); + assertEquals(expected.labels(), value.labels()); + assertEquals(expected.number(), value.number()); + assertEquals(expected.createTimeMillis(), value.createTimeMillis()); + assertEquals(expected.state(), value.state()); + assertEquals(expected.parent(), value.parent()); } } diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java index 6d36c024d0d2..a4388d8a725e 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java @@ -26,6 +26,8 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.gcloud.resourcemanager.Policy.Binding; import com.google.gcloud.resourcemanager.Policy.Member; import com.google.gcloud.resourcemanager.Policy.RoleType; @@ -35,20 +37,13 @@ import org.junit.Before; import org.junit.Test; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; public class ProjectTest { private static final String ID = "project-id"; private static final String NAME = "myProj"; - private static final Map LABELS = new HashMap(); - static { - LABELS.put("k1", "v1"); - LABELS.put("k2", "k2"); - } + private static final Map LABELS = ImmutableMap.of("k1", "v1", "k2", "v2"); private static final Long NUMBER = 123L; private static final Long CREATE_TIME_MILLIS = 123456789L; private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; @@ -62,25 +57,18 @@ public class ProjectTest { .state(STATE) .parent(PARENT) .build(); - private static final Binding OWNER_BINDING; - private static final Binding EDITOR_BINDING; - private static final Binding VIEWER_BINDING; - static { - List ownerMemberList = new ArrayList<>(); - List editorMemberList = new ArrayList<>(); - List viewerMemberList = new ArrayList<>(); - - ownerMemberList.add(Member.user("first-owner@email.com")); - ownerMemberList.add(Member.group("group-of-owners@email.com")); - OWNER_BINDING = Policy.Binding.builder().role(RoleType.OWNER).members(ownerMemberList).build(); - editorMemberList.add(Member.serviceAccount("editor@someemail.com")); - EDITOR_BINDING = - Policy.Binding.builder().role(RoleType.EDITOR).members(editorMemberList).build(); - viewerMemberList.add(Member.serviceAccount("app@someemail.com")); - viewerMemberList.add(Member.user("viewer@email.com")); - VIEWER_BINDING = - Policy.Binding.builder().role(RoleType.VIEWER).members(viewerMemberList).build(); - } + private static final List OWNER_MEMBER_LIST = ImmutableList.of( + Member.user("first-owner@email.com"), Member.group("group-of-owners@email.com")); + private static final List EDITOR_MEMBER_LIST = + ImmutableList.of(Member.serviceAccount("editor@someemail.com")); + private static final List VIEWER_MEMBER_LIST = + ImmutableList.of(Member.serviceAccount("app@someemail.com"), Member.user("viewer@email.com")); + private static final Binding OWNER_BINDING = + Policy.Binding.builder().role(RoleType.OWNER).members(OWNER_MEMBER_LIST).build(); + private static final Binding EDITOR_BINDING = + Policy.Binding.builder().role(RoleType.EDITOR).members(EDITOR_MEMBER_LIST).build(); + private static final Binding VIEWER_BINDING = + Policy.Binding.builder().role(RoleType.VIEWER).members(VIEWER_MEMBER_LIST).build(); private static final Policy POLICY = Policy.builder() .addBinding(OWNER_BINDING) @@ -89,9 +77,8 @@ public class ProjectTest { .version(1) .etag("some-etag-value") .build(); - private static final List PERMISSIONS_REQUESTED = - Arrays.asList(new Permission[] {Permission.REPLACE, Permission.GET}); - private static final List PERMISSIONS_OWNED = Arrays.asList(new Boolean[] {false, true}); + private static final Permission[] PERMISSIONS_REQUESTED = {Permission.REPLACE, Permission.GET}; + private static final List PERMISSIONS_OWNED = ImmutableList.of(false, true); private ResourceManager resourceManager; private Project project; @@ -132,20 +119,20 @@ public void testReload() { @Test public void testPolicy() { - assertEquals(project.policy(), POLICY); replay(resourceManager); + assertEquals(POLICY, project.policy()); } @Test public void testInfo() { - assertEquals(project.info(), PROJECT_INFO); replay(resourceManager); + assertEquals(PROJECT_INFO, project.info()); } @Test public void testResourceManager() { - assertEquals(project.resourceManager(), resourceManager); replay(resourceManager); + assertEquals(resourceManager, project.resourceManager()); } @Test @@ -170,9 +157,9 @@ public void testReplace() { expect(resourceManager.replace(newInfo)).andReturn(newInfo); replay(resourceManager); Project newProject = project.replace(newInfo); - assertSame(newProject.resourceManager(), resourceManager); - assertEquals(newProject.info(), newInfo); - assertEquals(newProject.policy(), POLICY); + assertSame(resourceManager, newProject.resourceManager()); + assertEquals(newInfo, newProject.info()); + assertEquals(POLICY, newProject.policy()); } @Test @@ -181,9 +168,9 @@ public void testReplaceIamPolicy() { expect(resourceManager.replaceIamPolicy(PROJECT_INFO.id(), newPolicy)).andReturn(newPolicy); replay(resourceManager); Project newProject = project.replaceIamPolicy(newPolicy); - assertSame(newProject.resourceManager(), resourceManager); - assertEquals(newProject.info(), PROJECT_INFO); - assertEquals(newProject.policy(), newPolicy); + assertSame(resourceManager, newProject.resourceManager()); + assertEquals(PROJECT_INFO, newProject.info()); + assertEquals(newPolicy, newProject.policy()); } @Test @@ -192,23 +179,20 @@ public void testHasPermissions() { .andReturn(PERMISSIONS_OWNED); replay(resourceManager); List response = - project.hasPermissions(PERMISSIONS_REQUESTED.get(0), PERMISSIONS_REQUESTED.get(1)); - assertEquals(response, PERMISSIONS_OWNED); + project.hasPermissions(PERMISSIONS_REQUESTED[0], PERMISSIONS_REQUESTED[1]); + assertEquals(PERMISSIONS_OWNED, response); } @Test public void testHasAllPermissions() { expect(resourceManager.hasPermissions(PROJECT_INFO.id(), PERMISSIONS_REQUESTED)) .andReturn(PERMISSIONS_OWNED); - List permissionsRequested2 = - Arrays.asList(new Permission[] {Permission.UNDELETE, Permission.DELETE}); - List permissionsOwned2 = Arrays.asList(new Boolean[] {true, true}); - expect(resourceManager.hasPermissions(PROJECT_INFO.id(), permissionsRequested2)) - .andReturn(permissionsOwned2); + Permission[] permissionsRequestAllOwned = {Permission.UNDELETE, Permission.DELETE}; + List permissionsResponseAllOwned = ImmutableList.of(true, true); + expect(resourceManager.hasPermissions(PROJECT_INFO.id(), permissionsRequestAllOwned)) + .andReturn(permissionsResponseAllOwned); replay(resourceManager); - assertFalse( - project.hasAllPermissions(PERMISSIONS_REQUESTED.get(0), PERMISSIONS_REQUESTED.get(1))); - assertTrue( - project.hasAllPermissions(permissionsRequested2.get(0), permissionsRequested2.get(1))); + assertFalse(project.hasAllPermissions(PERMISSIONS_REQUESTED)); + assertTrue(project.hasAllPermissions(permissionsRequestAllOwned)); } } diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java index 1f66017312a6..3879a38457fc 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java @@ -17,26 +17,36 @@ package com.google.gcloud.resourcemanager; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import org.junit.Test; public class ResourceIdTest { -private static final ResourceId RESOURCE_ID = ResourceId.of("id", ResourceId.Type.ORGANIZATION); + private static final String ID = "id"; + private static final ResourceId.Type TYPE = ResourceId.Type.ORGANIZATION; + private static final ResourceId RESOURCE_ID = ResourceId.of(ID, TYPE); @Test public void testOf() { - assertEquals(RESOURCE_ID.id(), "id"); - assertEquals(RESOURCE_ID.type(), ResourceId.Type.ORGANIZATION); + assertEquals(ID, RESOURCE_ID.id()); + assertEquals(TYPE, RESOURCE_ID.type()); } @Test public void testEquals() { - assertEquals(RESOURCE_ID, ResourceId.of("id", ResourceId.Type.ORGANIZATION)); + assertEquals(RESOURCE_ID, ResourceId.of(ID, TYPE)); + assertEquals(ID, RESOURCE_ID.id()); + assertEquals(TYPE, RESOURCE_ID.type()); + assertNotEquals(ResourceId.of("another-ID", TYPE), RESOURCE_ID); + assertNotEquals(ResourceId.of(ID, ResourceId.Type.UNKNOWN), RESOURCE_ID); } @Test public void testToAndFromPb() { - assertEquals(RESOURCE_ID, ResourceId.fromPb(RESOURCE_ID.toPb())); + ResourceId copy = ResourceId.fromPb(RESOURCE_ID.toPb()); + assertEquals(RESOURCE_ID, copy); + assertEquals(ID, copy.id()); + assertEquals(TYPE, copy.type()); } } diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java index e848c3a61680..72c8de7e9527 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java @@ -19,6 +19,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.gcloud.AuthCredentials; import com.google.gcloud.PageImpl; import com.google.gcloud.RetryParams; @@ -34,36 +36,27 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class SerializationTest { private static final ResourceId RESOURCE_ID = ResourceId.of("some id", ResourceId.Type.ORGANIZATION); - private static final Binding OWNER_BINDING; - private static final Binding EDITOR_BINDING; - private static final Binding VIEWER_BINDING; - private static final Binding EMPTY_BINDING = Policy.Binding.builder().build(); - static { - List ownerMemberList = new ArrayList<>(); - List editorMemberList = new ArrayList<>(); - List viewerMemberList = new ArrayList<>(); - ownerMemberList.add(Member.user("first-owner@email.com")); - ownerMemberList.add(Member.group("group-of-owners@email.com")); - OWNER_BINDING = Policy.Binding.builder().role(RoleType.OWNER).members(ownerMemberList).build(); - editorMemberList.add(Member.serviceAccount("editor@someemail.com")); - EDITOR_BINDING = - Policy.Binding.builder().role(RoleType.EDITOR).members(editorMemberList).build(); - viewerMemberList.add(Member.serviceAccount("app@someemail.com")); - viewerMemberList.add(Member.user("viewer@email.com")); - VIEWER_BINDING = - Policy.Binding.builder().role(RoleType.VIEWER).members(viewerMemberList).build(); - } - private static final Policy POLICY = + private static final List OWNER_MEMBER_LIST = ImmutableList.of( + Member.user("first-owner@email.com"), Member.group("group-of-owners@email.com")); + private static final List EDITOR_MEMBER_LIST = + ImmutableList.of(Member.serviceAccount("editor@someemail.com")); + private static final List VIEWER_MEMBER_LIST = + ImmutableList.of(Member.serviceAccount("app@someemail.com"), Member.user("viewer@email.com")); + private static final Binding OWNER_BINDING = + Policy.Binding.builder().role(RoleType.OWNER).members(OWNER_MEMBER_LIST).build(); + private static final Binding EDITOR_BINDING = + Policy.Binding.builder().role(RoleType.EDITOR).members(EDITOR_MEMBER_LIST).build(); + private static final Binding VIEWER_BINDING = + Policy.Binding.builder().role(RoleType.VIEWER).members(VIEWER_MEMBER_LIST).build(); + private static final Policy EMPTY_POLICY = Policy.builder().build(); + private static final Policy FULL_POLICY = Policy.builder() .addBinding(OWNER_BINDING) .addBinding(EDITOR_BINDING) @@ -71,17 +64,18 @@ public class SerializationTest { .version(1) .etag("some-etag-value") .build(); - private static final Policy EMPTY_POLICY = Policy.builder().build(); - private static final ProjectInfo PROJECT_INFO1 = ProjectInfo.builder("id1").build(); - private static final ProjectInfo PROJECT_INFO2; - static { - Map labels = new HashMap(); - labels.put("key", "value"); - PROJECT_INFO2 = - new ProjectInfo("name", "id", labels, 123L, ProjectInfo.State.ACTIVE, 1234L, RESOURCE_ID); - } + private static final ProjectInfo PARTIAL_PROJECT_INFO = ProjectInfo.builder("id1").build(); + private static final ProjectInfo FULL_PROJECT_INFO = + ProjectInfo.builder("id") + .name("name") + .labels(ImmutableMap.of("key", "value")) + .number(123L) + .state(ProjectInfo.State.ACTIVE) + .createTimeMillis(1234L) + .parent(RESOURCE_ID) + .build(); private static final PageImpl PAGE_RESULT = - new PageImpl<>(null, "c", Collections.singletonList(PROJECT_INFO1)); + new PageImpl<>(null, "c", Collections.singletonList(PARTIAL_PROJECT_INFO)); @Test public void testServiceOptions() throws Exception { @@ -101,8 +95,8 @@ public void testServiceOptions() throws Exception { @Test public void testModelAndRequests() throws Exception { Serializable[] objects = {RESOURCE_ID, OWNER_BINDING.members().get(0), OWNER_BINDING, - EDITOR_BINDING, VIEWER_BINDING, EMPTY_BINDING, POLICY, EMPTY_POLICY, PROJECT_INFO1, - PROJECT_INFO2, PAGE_RESULT}; + EDITOR_BINDING, VIEWER_BINDING, EMPTY_POLICY, FULL_POLICY, PARTIAL_PROJECT_INFO, + FULL_PROJECT_INFO, PAGE_RESULT}; for (Serializable obj : objects) { Object copy = serializeAndDeserialize(obj); assertEquals(obj, obj); From 9e48ecf8bfbdd5d1298981e8ed6266f6c08882ab Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Fri, 20 Nov 2015 10:41:07 -0800 Subject: [PATCH 03/10] Add documentation and make resource ID type string --- .../gcloud/resourcemanager/ProjectInfo.java | 94 ++++++++++++++++++- .../gcloud/resourcemanager/ResourceId.java | 15 +-- .../resourcemanager/ProjectInfoTest.java | 2 +- .../gcloud/resourcemanager/ProjectTest.java | 2 +- .../resourcemanager/ResourceIdTest.java | 3 +- .../resourcemanager/SerializationTest.java | 3 +- 6 files changed, 101 insertions(+), 18 deletions(-) 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 4e3aed325db7..b5913b763ea0 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 @@ -41,11 +41,24 @@ public class ProjectInfo implements Serializable { private final Long createTimeMillis; private final ResourceId parent; + /** + * The project lifecycle state. + * + *
    + *
  • LIFECYCLE_STATE_UNSPECIFIED: only used/useful for distinguishing unset values + *
  • ACTIVE: the normal and active state + *
  • DELETE_REQUESTED: the project has been marked for deletion by the user or by the system + * (Google Cloud Platform). This can generally be reversed by calling + * {@link ResourceManager#undelete}. + *
  • DELETE_IN_PROGRESS: the process of deleting the project has begun. Reversing the deletion + * is no longer possible. + *
      + */ public enum State { LIFECYCLE_STATE_UNSPECIFIED, ACTIVE, DELETE_REQUESTED, - DELETE_IN_PROGRESS; + DELETE_IN_PROGRESS } public static class Builder { @@ -58,34 +71,68 @@ public static class Builder { private ResourceId parent; Builder() { - labels = new HashMap(); + labels = new HashMap<>(); } + /** + * Set the user-assigned name of the project. + * + * This field is optional and can remain unset. Allowed characters are: lowercase and uppercase + * letters, numbers, hyphen, single-quote, double-quote, space, and exclamation point. This + * field can be changed after project creation. + */ public Builder name(String name) { this.name = name; return this; } + /** + * Set the unique, user-assigned ID of the project. + * + * The ID must be 6 to 30 lowercase letters, digits, or hyphens. It must start with a letter. + * Trailing hyphens are prohibited. This field cannot be changed after the server creates the + * project. + */ public Builder id(String id) { this.id = id; return this; } + /** + * Add a label associated with this project. + * + * See {@link #labels} for label restrictions. + */ public Builder addLabel(String key, String value) { this.labels.put(key, value); return this; } + /** + * Remove a label associated with this project. + */ public Builder removeLabel(String key) { this.labels.remove(key); return this; } + /** + * Clear the labels associated with this project. + */ public Builder clearLabels() { this.labels.clear(); return this; } + /** + * Set the labels associated with this project. + * + * Label keys must be between 1 and 63 characters long and must conform to the following regular + * expression: [a-z]([-a-z0-9]*[a-z0-9])?. Label values must be between 0 and 63 characters long + * and must conform to the regular expression ([a-z]([-a-z0-9]*[a-z0-9])?)?. No more than 256 + * labels can be associated with a given resource. This field can be changed after project + * creation. + */ public Builder labels(Map labels) { this.labels = Maps.newHashMap(checkNotNull(labels)); return this; @@ -106,6 +153,15 @@ Builder createTimeMillis(Long createTimeMillis) { return this; } + /** + * Set the parent of the project. + * + * If this field is left unset in a project creation request, the server will set this field by + * default to the creator of the project. The parent cannot be changed after the server creates + * the project. When calling {@link ResourceManager#replace}, be sure to set the parent of the + * new ProjectInfo instance. Leaving the parent unset or setting it to null in a replace request + * will cause an error. + */ public Builder parent(ResourceId parent) { this.parent = parent; return this; @@ -126,30 +182,64 @@ public ProjectInfo build() { this.parent = builder.parent; } + /** + * Get the unique, user-assigned ID of the project. + * + * This field cannot be changed after the server creates the project. + */ public String id() { return id; } + /** + * Get the user-assigned name of the project. + * + * This field is optional, can remain unset, and can be changed after project creation. + */ public String name() { return name; } + /** + * Get number uniquely identifying the project. + * + * This field is set by the server and is read-only. + */ public Long number() { return number; } + /** + * Get the immutable map of labels associated with this project. + */ public Map labels() { return labels; } + /** + * Get the project's lifecycle state. + * + * This is a read-only field. To change the lifecycle state of your project, use the + * {@code delete} or {@code undelete} method. + */ public State state() { return state; } + /** + * Get the project's creation time (in milliseconds). + * + * This field is set by the server and is read-only. + */ public Long createTimeMillis() { return createTimeMillis; } + /** + * Get the parent of the project. + * + * The parent cannot be changed after the server creates the project. + */ public ResourceId parent() { return parent; } diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java index 6e6022460e04..f2907b9dca6a 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java @@ -26,14 +26,9 @@ public class ResourceId implements Serializable { private static final long serialVersionUID = 7928469304338358885L; private final String id; - private final Type type; + private final String type; - public enum Type { - ORGANIZATION, - UNKNOWN; - } - - private ResourceId(String id, Type type) { + private ResourceId(String id, String type) { this.id = checkNotNull(id); this.type = checkNotNull(type); } @@ -42,7 +37,7 @@ public String id() { return id; } - public Type type() { + public String type() { return type; } @@ -56,7 +51,7 @@ public int hashCode() { return Objects.hash(id, type); } - public static ResourceId of(String id, Type type) { + public static ResourceId of(String id, String type) { return new ResourceId(id, type); } @@ -70,6 +65,6 @@ com.google.api.services.cloudresourcemanager.model.ResourceId toPb() { static ResourceId fromPb( com.google.api.services.cloudresourcemanager.model.ResourceId resourceIdPb) { - return new ResourceId(resourceIdPb.getId(), Type.valueOf(resourceIdPb.getType().toUpperCase())); + return new ResourceId(resourceIdPb.getId(), resourceIdPb.getType()); } } diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java index c0bfb73af3fd..ef4d213721de 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java @@ -34,7 +34,7 @@ public class ProjectInfoTest { private static final Long NUMBER = 123L; private static final Long CREATE_TIME_MILLIS = 123456789L; private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; - private static final ResourceId PARENT = ResourceId.of("owner-id", ResourceId.Type.ORGANIZATION); + private static final ResourceId PARENT = ResourceId.of("owner-id", "organization"); private static final ProjectInfo FULL_PROJECT_INFO = ProjectInfo.builder(ID) .name(NAME) diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java index a4388d8a725e..99bc534d952c 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java @@ -47,7 +47,7 @@ public class ProjectTest { private static final Long NUMBER = 123L; private static final Long CREATE_TIME_MILLIS = 123456789L; private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; - private static final ResourceId PARENT = ResourceId.of("owner-id", ResourceId.Type.ORGANIZATION); + private static final ResourceId PARENT = ResourceId.of("owner-id", "organization"); private static final ProjectInfo PROJECT_INFO = ProjectInfo.builder(ID) .name(NAME) diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java index 3879a38457fc..9fed10759931 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java @@ -24,7 +24,7 @@ public class ResourceIdTest { private static final String ID = "id"; - private static final ResourceId.Type TYPE = ResourceId.Type.ORGANIZATION; + private static final String TYPE = "organization"; private static final ResourceId RESOURCE_ID = ResourceId.of(ID, TYPE); @Test @@ -39,7 +39,6 @@ public void testEquals() { assertEquals(ID, RESOURCE_ID.id()); assertEquals(TYPE, RESOURCE_ID.type()); assertNotEquals(ResourceId.of("another-ID", TYPE), RESOURCE_ID); - assertNotEquals(ResourceId.of(ID, ResourceId.Type.UNKNOWN), RESOURCE_ID); } @Test diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java index 72c8de7e9527..0d035af52f6f 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java @@ -41,8 +41,7 @@ public class SerializationTest { - private static final ResourceId RESOURCE_ID = - ResourceId.of("some id", ResourceId.Type.ORGANIZATION); + private static final ResourceId RESOURCE_ID = ResourceId.of("some id", "organization"); private static final List OWNER_MEMBER_LIST = ImmutableList.of( Member.user("first-owner@email.com"), Member.group("group-of-owners@email.com")); private static final List EDITOR_MEMBER_LIST = From 01f8b6cfe4a563f581df01d86963df8176afdacf Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Mon, 23 Nov 2015 17:51:41 -0800 Subject: [PATCH 04/10] Remove Policy and add docs --- .../google/gcloud/resourcemanager/Policy.java | 367 ------------------ .../gcloud/resourcemanager/Project.java | 111 +++--- .../resourcemanager/ResourceManager.java | 135 +++++-- .../google/gcloud/spi/ResourceManagerRpc.java | 72 ++-- .../gcloud/resourcemanager/PolicyTest.java | 117 ------ .../gcloud/resourcemanager/ProjectTest.java | 73 +--- .../resourcemanager/SerializationTest.java | 30 +- 7 files changed, 179 insertions(+), 726 deletions(-) delete mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java delete mode 100644 gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java deleted file mode 100644 index efa95d9f7c73..000000000000 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Policy.java +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed 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 com.google.gcloud.resourcemanager; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * A Google Cloud IAM Policy object - */ -public class Policy implements Serializable { - - private static final long serialVersionUID = 3493286111316914094L; - private final List bindings; - private final Integer version; - private final String etag; - - public static enum MemberType { - ALL_USERS("allUsers"), - ALL_AUTHENTICATED_USERS("allAuthenticatedUsers"), - USER("user:"), - SERVICE_ACCOUNT("serviceAccount:"), - GROUP("group:"), - DOMAIN("domain:"); - - private final String prefix; - - MemberType(String prefix) { - this.prefix = prefix; - } - - String prefix() { - return prefix; - } - } - - public enum RoleType { - OWNER, - EDITOR, - VIEWER; - } - - /** - * Represents a member belonging to an IAM policy binding - */ - public static final class Member implements Serializable { - - private static final long serialVersionUID = 6496912037577986137L; - private final MemberType memberType; - private final String emailOrDomain; - - Member(MemberType memberType, String emailOrDomain) { - this.memberType = memberType; - this.emailOrDomain = emailOrDomain; - } - - public static Member allUsers() { - throw new UnsupportedOperationException( - "Google Cloud Resource Manager does not support the \"all users\" member type yet."); - // return new Member(MemberType.ALL_USERS, null); - } - - public static Member allAuthenticatedUsers() { - throw new UnsupportedOperationException("Google Cloud Resource Manager does not support the " - + "\"all authenticated users\" member type yet."); - // return new Member(MemberType.ALL_AUTHENTICATED_USERS, null); - } - - public static Member user(String email) { - return new Member(MemberType.USER, email); - } - - public static Member serviceAccount(String email) { - return new Member(MemberType.SERVICE_ACCOUNT, email); - } - - public static Member group(String email) { - return new Member(MemberType.GROUP, email); - } - - public static Member domain(String domain) { - throw new UnsupportedOperationException( - "Google Cloud Resource Manager does not support domain members yet."); - // return new Member(MemberType.DOMAIN, domain); - } - - public MemberType type() { - return memberType; - } - - public String emailOrDomain() { - return emailOrDomain; - } - - @Override - public int hashCode() { - return Objects.hash(memberType, emailOrDomain); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof Member && Objects.equals(this.memberType, ((Member) obj).memberType) - && Objects.equals(this.emailOrDomain, ((Member) obj).emailOrDomain); - } - - String toPb() { - return emailOrDomain != null ? memberType.prefix() + emailOrDomain : memberType.prefix(); - } - - static Member fromPb(String memberPb) { - String[] memberInfo = memberPb.split(":", 2); - String memberStr = memberInfo[0]; - String emailOrDomain = (memberInfo.length > 1) ? memberInfo[1] : null; - switch (memberStr) { - case "allUsers": - return new Member(MemberType.ALL_USERS, null); - case "allAuthenticatedUsers": - return new Member(MemberType.ALL_AUTHENTICATED_USERS, null); - case "user": - return new Member(MemberType.USER, checkNotNull(emailOrDomain)); - case "serviceAccount": - return new Member(MemberType.SERVICE_ACCOUNT, checkNotNull(emailOrDomain)); - case "group": - return new Member(MemberType.GROUP, checkNotNull(emailOrDomain)); - case "domain": - return new Member(MemberType.DOMAIN, checkNotNull(emailOrDomain)); - default: - throw new UnsupportedOperationException("Unsupported member type: " + memberStr); - } - } - } - - /** - * Represents an IAM policy binding - */ - public static class Binding implements Serializable { - - private static final long serialVersionUID = -8493421092718338925L; - private final RoleType role; - private final List members; - - public static class Builder { - private RoleType role; - private List members; - - Builder() { - members = new ArrayList(); - } - - public Builder role(RoleType role) { - this.role = role; - return this; - } - - public Builder members(List members) { - this.members = Lists.newArrayList(checkNotNull(members)); - return this; - } - - public Builder clearMembers() { - this.members = new ArrayList<>(); - return this; - } - - public Builder addMember(Member member) { - this.members.add(member); - return this; - } - - public Builder removeMember(Member member) { - this.members.remove(member); - return this; - } - - public Binding build() { - return new Binding(role, members); - } - } - - private Binding(RoleType role, List members) { - this.role = checkNotNull(role); - this.members = ImmutableList.copyOf(members); - } - - public static Binding of(RoleType role, List members) { - return new Binding(role, members); - } - - public RoleType role() { - return role; - } - - public List members() { - return members; - } - - public static Builder builder() { - return new Builder(); - } - - public Builder toBuilder() { - return new Builder().role(role).members(members); - } - - com.google.api.services.cloudresourcemanager.model.Binding toPb() { - com.google.api.services.cloudresourcemanager.model.Binding bindingPb = - new com.google.api.services.cloudresourcemanager.model.Binding(); - bindingPb.setRole("roles/" + role.toString().toLowerCase()); - List membersPb = new ArrayList<>(members.size()); - for (Member member : members) { - membersPb.add(member.toPb()); - } - bindingPb.setMembers(membersPb); - return bindingPb; - } - - static Binding fromPb(com.google.api.services.cloudresourcemanager.model.Binding bindingPb) { - RoleType role = - (bindingPb.getRole() == null) - ? null : RoleType.valueOf(bindingPb.getRole().split("/")[1].toUpperCase()); - List members = new ArrayList<>(); - if (bindingPb.getMembers() != null) { - for (String memberPb : bindingPb.getMembers()) { - members.add(Member.fromPb(memberPb)); - } - } - return new Binding(role, members); - } - - @Override - public int hashCode() { - return Objects.hash(role, members); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof Binding && Objects.equals(toPb(), ((Binding) obj).toPb()); - } - } - - public static final class Builder { - private List bindings; - private String etag; - private Integer version; - - private Builder() { - bindings = new ArrayList<>(); - } - - public Builder addBinding(Binding binding) { - this.bindings.add(binding); - return this; - } - - public Builder removeBinding(Binding binding) { - this.bindings.remove(binding); - return this; - } - - public Builder clearBindings() { - this.bindings = new ArrayList<>(); - return this; - } - - public Builder bindings(List bindings) { - this.bindings = new ArrayList<>(checkNotNull(bindings)); - return this; - } - - public Builder etag(String etag) { - this.etag = etag; - return this; - } - - public Builder version(Integer version) { - this.version = version; - return this; - } - - public Policy build() { - return new Policy(this); - } - } - - Policy(Builder builder) { - bindings = ImmutableList.copyOf(builder.bindings); - version = builder.version; - etag = builder.etag; - } - - public List bindings() { - return bindings; - } - - public Integer version() { - return version; - } - - public String etag() { - return etag; - } - - public static Builder builder() { - return new Builder(); - } - - public Builder toBuilder() { - return new Builder().bindings(bindings).etag(etag).version(version); - } - - @Override - public int hashCode() { - return Objects.hash(bindings, etag, version); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof Policy && Objects.equals(toPb(), ((Policy) obj).toPb()); - } - - com.google.api.services.cloudresourcemanager.model.Policy toPb() { - com.google.api.services.cloudresourcemanager.model.Policy policyPb = - new com.google.api.services.cloudresourcemanager.model.Policy(); - List bindingsPb = new ArrayList<>(); - for (Binding binding : bindings) { - bindingsPb.add(binding.toPb()); - } - policyPb.setBindings(bindingsPb); - policyPb.setVersion(version); - policyPb.setEtag(etag); - return policyPb; - } - - static Policy fromPb(com.google.api.services.cloudresourcemanager.model.Policy policyPb) { - Builder policyBuilder = Policy.builder(); - if (policyPb.getBindings() != null) { - for (com.google.api.services.cloudresourcemanager.model.Binding bindingPb : - policyPb.getBindings()) { - policyBuilder.addBinding(Binding.fromPb(bindingPb)); - } - } - policyBuilder.version(policyPb.getVersion()); - policyBuilder.etag(policyPb.getEtag()); - return policyBuilder.build(); - } -} 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 74296a0be773..5f17bd48336e 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 @@ -18,10 +18,6 @@ import static com.google.common.base.Preconditions.checkNotNull; -import com.google.gcloud.spi.ResourceManagerRpc.Permission; - -import java.util.List; - /** * A Google Cloud Resource Manager project object. * @@ -32,57 +28,70 @@ public class Project { private final ResourceManager resourceManager; private final ProjectInfo info; - private final Policy policy; /** - * Constructs a Project object that contains the ProjectInfo and Policy given. + * Constructs a Project object that contains the ProjectInfo given. */ - public Project(ResourceManager resourceManager, ProjectInfo projectInfo, Policy policy) { + public Project(ResourceManager resourceManager, ProjectInfo projectInfo) { this.resourceManager = checkNotNull(resourceManager); this.info = checkNotNull(projectInfo); - this.policy = checkNotNull(policy); } /** - * Constructs a Project object that contains project and policy information loaded from the - * server. + * Constructs a Project object that contains project information loaded from the server. * - * @return Project object containing the project's metadata and IAM policy + * @return Project object containing the project's metadata * @throws ResourceManagerException upon failure */ public static Project load(ResourceManager resourceManager, String projectId) { ProjectInfo projectInfo = resourceManager.get(projectId); - Policy policy = resourceManager.getIamPolicy(projectId); - return new Project(resourceManager, projectInfo, policy); + return new Project(resourceManager, projectInfo); } + /** + * Returns the {@link ProjectInfo} object associated with this Project. + */ public ProjectInfo info() { return info; } - public Policy policy() { - return policy; - } - + /** + * Returns the {@link ResourceManager} service object associated with this Project. + */ public ResourceManager resourceManager() { return resourceManager; } /** - * Returns a Project object with updated project and policy information. + * Returns a Project object with updated project information. * - * @return Project object containing the project's updated metadata and IAM policy + * @return Project object containing the project's updated metadata * @throws ResourceManagerException upon failure */ public Project reload() { - return new Project( - resourceManager, resourceManager.get(info.id()), resourceManager.getIamPolicy(info.id())); + return new Project(resourceManager, resourceManager.get(info.id())); } /** - * Requests that this project be deleted. For an unspecified amount of time, this action can be - * undone by calling {@link #undelete}. + * Marks the project identified by the specified project ID for deletion. + * + * This method will only affect the project if the following criteria are met: + *
        + *
      • The project does not have a billing account associated with it. + *
      • The project has a lifecycle state of {@link ProjectInfo.State#ACTIVE}. + *
      + * This method changes the project's lifecycle state from {@link ProjectInfo.State#ACTIVE} to + * {@link ProjectInfo.State#DELETE_REQUESTED}. The deletion starts at an unspecified time, at + * which point the lifecycle state changes to {@link ProjectInfo.State#DELETE_IN_PROGRESS}. Until + * the deletion completes, you can check the lifecycle state checked by retrieving the project + * with {@link ResourceManager#get}, and the project remains visible to + * {@link ResourceManager#list}. However, you cannot update the project. After the deletion + * 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 * @throws ResourceManagerException upon failure */ public void delete() { @@ -90,54 +99,34 @@ public void delete() { } /** - * Requests that a project's lifecycle status be changed from {@code DELETE_REQUESTED} to - * {@code ACTIVE}. + * Restores the project identified by the specified project ID. * - * @throws ResourceManagerException upon failure + * 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. + * + * @see + * Cloud Resource Manager undelete + * @throws ResourceManagerException */ public void undelete() { resourceManager.undelete(info.id()); } /** - * Replaces the project metadata (not including the IAM policy) using the given ProjectInfo. - * - * @return Project object containing the project's updated metadata - * @throws ResourceManagerException upon failure - */ - public Project replace(ProjectInfo projectInfo) { - return new Project(resourceManager, resourceManager.replace(checkNotNull(projectInfo)), policy); - } - - /** - * Replaces the project's IAM policy using the given policy. - * - * @return Project object containing the project's updated IAM policy - * @throws ResourceManagerException upon failure - */ - public Project replaceIamPolicy(Policy policy) { - return new Project( - resourceManager, info, resourceManager.replaceIamPolicy(info.id(), checkNotNull(policy))); - } - - /** - * Returns whether the caller has the permissions specified in the parameters. + * Replaces the attributes of the project. * - * @return List of booleans representing whether the user has the corresponding permission - * provided as a parameter - * @throws ResourceManagerException upon failure - */ - public List hasPermissions(Permission... permissions) { - return resourceManager.hasPermissions(info.id(), permissions); - } - - /** - * Returns whether the caller has all the permissions specified in the parameters. + * The caller must have modify permissions for this project. * - * @return true if the caller has all the permissions specified, otherwise false. + * @see + * + * Cloud Resource Manager update + * @return the ProjectInfo representing the new project metadata * @throws ResourceManagerException upon failure */ - public boolean hasAllPermissions(Permission... permissions) { - return !(hasPermissions(permissions).contains(false)); + public Project replace(ProjectInfo projectInfo) { + return new Project(resourceManager, resourceManager.replace(checkNotNull(projectInfo))); } } 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 ca6a1cb24b27..2f999b7ca4e6 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 @@ -16,11 +16,13 @@ package com.google.gcloud.resourcemanager; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.collect.ImmutableList; import com.google.gcloud.Page; import com.google.gcloud.Service; -import com.google.gcloud.spi.ResourceManagerRpc.ListOptions; -import com.google.gcloud.spi.ResourceManagerRpc.Permission; +import java.util.Collections; import java.util.List; /** @@ -32,79 +34,134 @@ public interface ResourceManager extends Service { public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; + public class ListOptions { + private List filters; + private String pageToken; + private int pageSize; + + private static final ListOptions DEFAULT_INSTANCE = + new ListOptions(Collections.emptyList(), null, -1); + + ListOptions(List filters, String pageToken, int pageSize) { + this.filters = checkNotNull(ImmutableList.copyOf(filters)); + this.pageToken = pageToken; + this.pageSize = pageSize; + } + + public static ListOptions getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + public static ListOptions createListOption( + List filters, String pageToken, int pageSize) { + return new ListOptions(filters, pageToken, pageSize); + } + + public String pageToken() { + return pageToken; + } + + public List filters() { + return filters; + } + + public int pageSize() { + return pageSize; + } + } + /** * Create a new project. * + * 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. + * + * @see + * + * Cloud Resource Manager create + * * @return ProjectInfo object representing the new project's metadata. The returned object will - * include additional read-only information, namely project number, lifecycle state, and - * creation time. + * include the following read-only fields supplied by the server: project number, lifecycle + * state, and creation time. * @throws ResourceManagerException upon failure */ ProjectInfo create(ProjectInfo project); /** - * Sends a request to delete a project. For an unspecified amount of time, this action can be - * undone using {@link #undelete}. + * Marks the project identified by the specified project ID for deletion. + * + * This method will only affect the project if the following criteria are met: + *
        + *
      • The project does not have a billing account associated with it. + *
      • The project has a lifecycle state of {@link ProjectInfo.State#ACTIVE}. + *
      + * This method changes the project's lifecycle state from {@link ProjectInfo.State#ACTIVE} to + * {@link ProjectInfo.State#DELETE_REQUESTED}. The deletion starts at an unspecified time, at + * which point the lifecycle state changes to {@link ProjectInfo.State#DELETE_IN_PROGRESS}. Until + * the deletion completes, you can check the lifecycle state checked by retrieving the project + * with {@link ResourceManager#get}, and the project remains visible to + * {@link ResourceManager#list}. However, you cannot update the project. After the deletion + * 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 * @throws ResourceManagerException upon failure */ void delete(String projectId); /** - * Return the requested project or {@code null} if not found. + * Retrieves the project identified by the specified project ID. * + * The caller must have read permissions for this project. + * + * @see + * Cloud Resource Manager get * @throws ResourceManagerException upon failure */ ProjectInfo get(String projectId); /** - * List the projects viewable by the current user. Use {@link ListOptions} to filter this list, - * set page size, and set page tokens. Note that pagination is currently not implemented by the - * Cloud Resource Manager API. + * Lists the projects visible to the current user. + * + * This method returns projects in an unspecified order. New projects do not necessarily appear at + * the end of the list. Use {@link ListOptions} to filter this list, set page size, and set page + * tokens. Note that pagination is currently not implemented by the Cloud Resource Manager API. * - * @return {@code Page}, a paginated list of projects. + * @see + * Cloud Resource Manager list + * @return {@code Page}, a page of projects. * @throws ResourceManagerException upon failure */ Page list(ListOptions listOptions); /** - * Replace project metadata. + * Replaces the attributes of the project. * + * The caller must have modify permissions for this project. + * + * @see + * + * Cloud Resource Manager update * @return the ProjectInfo representing the new project metadata * @throws ResourceManagerException upon failure */ ProjectInfo replace(ProjectInfo newProject); /** - * Undo a delete request. This will only succeed if the server processes the undelete request - * while the project's state is {@code DELETE_REQUESTED}. + * Restores the project identified by the specified project ID. + * + * 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. * + * @see + * Cloud Resource Manager undelete * @throws ResourceManagerException */ void undelete(String projectId); - - /** - * Get the IAM policy for the project specified. - * - * @return IAM Policy - * @throws ResourceManagerException upon failure - */ - Policy getIamPolicy(String projectId); - - /** - * Replace the IAM Policy for a project with the policy given. - * - * @return the new IAM Policy - * @throws ResourceManagerException upon failure - */ - Policy replaceIamPolicy(String projectId, Policy policy); - - /** - * Test whether the caller of this function has the permissions provided as arguments. - * - * @return List of booleans representing whether the caller has the corresponding permission in - * the given permissions array. - * @throws ResourceManagerException upon failure - */ - List hasPermissions(String projectId, Permission... permissions); } diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java index 9410891771c9..6f07b53d7df2 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java @@ -16,18 +16,44 @@ package com.google.gcloud.spi; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.api.services.cloudresourcemanager.model.Policy; import com.google.api.services.cloudresourcemanager.model.Project; -import com.google.common.collect.ImmutableList; import com.google.gcloud.resourcemanager.ResourceManagerException; -import java.util.Collections; import java.util.List; +import java.util.Map; public interface ResourceManagerRpc { + enum Option { + FILTER("filter"), + PAGE_SIZE("maxResults"), + PAGE_TOKEN("pageToken"); + + private final String value; + + Option(String value) { + this.value = value; + } + + public String value() { + return value; + } + + @SuppressWarnings("unchecked") + T get(Map options) { + return (T) options.get(this); + } + + String getString(Map options) { + return get(options); + } + + Long getInt(Map options) { + return get(options); + } + } + public enum Permission { CREATE("resourcemanager.projects.create"), DELETE("resourcemanager.projects.delete"), @@ -71,49 +97,13 @@ public Y y() { } } - public class ListOptions { - private List filters; - private String pageToken; - private int pageSize; - - private static final ListOptions DEFAULT_INSTANCE = - new ListOptions(Collections.emptyList(), null, -1); - - ListOptions(List filters, String pageToken, int pageSize) { - this.filters = checkNotNull(ImmutableList.copyOf(filters)); - this.pageToken = pageToken; - this.pageSize = pageSize; - } - - public static ListOptions getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - public static ListOptions createListOption( - List filters, String pageToken, int pageSize) { - return new ListOptions(filters, pageToken, pageSize); - } - - public String pageToken() { - return pageToken; - } - - public List filters() { - return filters; - } - - public int pageSize() { - return pageSize; - } - } - Project create(Project project) throws ResourceManagerException; void delete(String projectId) throws ResourceManagerException; Project get(String projectId) throws ResourceManagerException; - Tuple> list(ListOptions listOptions) throws ResourceManagerException; + Tuple> list(Map options) throws ResourceManagerException; void undelete(String projectId) throws ResourceManagerException; diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java deleted file mode 100644 index 6b52f20f3fae..000000000000 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/PolicyTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed 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 com.google.gcloud.resourcemanager; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import com.google.common.collect.ImmutableList; -import com.google.gcloud.resourcemanager.Policy.Binding; -import com.google.gcloud.resourcemanager.Policy.Member; -import com.google.gcloud.resourcemanager.Policy.RoleType; - -import org.junit.Test; - -import java.util.List; - -public class PolicyTest { - - private static final List OWNER_MEMBER_LIST = ImmutableList.of( - Member.user("first-owner@email.com"), Member.group("group-of-owners@email.com")); - private static final List EDITOR_MEMBER_LIST = - ImmutableList.of(Member.serviceAccount("editor@someemail.com")); - private static final List VIEWER_MEMBER_LIST = - ImmutableList.of(Member.serviceAccount("app@someemail.com"), Member.user("viewer@email.com")); - private static final Binding OWNER_BINDING = - Policy.Binding.builder().role(RoleType.OWNER).members(OWNER_MEMBER_LIST).build(); - private static final Binding EDITOR_BINDING = - Policy.Binding.builder().role(RoleType.EDITOR).members(EDITOR_MEMBER_LIST).build(); - private static final Binding VIEWER_BINDING = - Policy.Binding.builder().role(RoleType.VIEWER).members(VIEWER_MEMBER_LIST).build(); - private static final Policy EMPTY_POLICY = Policy.builder().build(); - private static final Integer VERSION = 1; - private static final String ETAG = "some-etag-value"; - private static final Policy FULL_POLICY = - Policy.builder() - .addBinding(OWNER_BINDING) - .addBinding(EDITOR_BINDING) - .addBinding(VIEWER_BINDING) - .version(VERSION) - .etag(ETAG) - .build(); - - @Test - public void testBindingBuilder() { - assertEquals(RoleType.OWNER, OWNER_BINDING.role()); - assertEquals(OWNER_MEMBER_LIST, OWNER_BINDING.members()); - } - - @Test - public void testBindingToBuilder() { - assertEquals(OWNER_BINDING, OWNER_BINDING.toBuilder().build()); - } - - @Test - public void testBindingToAndFromPb() { - assertEquals(OWNER_BINDING, Binding.fromPb(OWNER_BINDING.toPb())); - assertEquals(EDITOR_BINDING, Binding.fromPb(EDITOR_BINDING.toPb())); - assertEquals(VIEWER_BINDING, Binding.fromPb(VIEWER_BINDING.toPb())); - } - - @Test - public void testPolicyBuilder() { - assertEquals(OWNER_BINDING, FULL_POLICY.bindings().get(0)); - assertEquals(EDITOR_BINDING, FULL_POLICY.bindings().get(1)); - assertEquals(VIEWER_BINDING, FULL_POLICY.bindings().get(2)); - assertEquals(VERSION, FULL_POLICY.version()); - assertEquals(ETAG, FULL_POLICY.etag()); - } - - @Test - public void testPolicyToBuilder() { - comparePolicies(FULL_POLICY, FULL_POLICY.toBuilder().build()); - comparePolicies(EMPTY_POLICY, EMPTY_POLICY.toBuilder().build()); - } - - @Test - public void testPolicyToAndFromPb() { - comparePolicies(FULL_POLICY, Policy.fromPb(FULL_POLICY.toPb())); - comparePolicies(EMPTY_POLICY, Policy.fromPb(EMPTY_POLICY.toPb())); - } - - @Test - public void testEquals() { - comparePolicies( - FULL_POLICY, - Policy.builder() - .addBinding(OWNER_BINDING) - .addBinding(EDITOR_BINDING) - .addBinding(VIEWER_BINDING) - .version(VERSION) - .etag(ETAG) - .build()); - comparePolicies(EMPTY_POLICY, Policy.builder().build()); - assertNotEquals(FULL_POLICY, EMPTY_POLICY); - } - - private void comparePolicies(Policy expected, Policy value) { - assertEquals(expected, value); - assertEquals(expected.bindings(), value.bindings()); - assertEquals(expected.version(), value.version()); - assertEquals(expected.etag(), value.etag()); - } -} diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java index 99bc534d952c..9201448f60f8 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java @@ -22,22 +22,14 @@ import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.gcloud.resourcemanager.Policy.Binding; -import com.google.gcloud.resourcemanager.Policy.Member; -import com.google.gcloud.resourcemanager.Policy.RoleType; -import com.google.gcloud.spi.ResourceManagerRpc.Permission; import org.junit.After; import org.junit.Before; import org.junit.Test; -import java.util.List; import java.util.Map; public class ProjectTest { @@ -57,28 +49,6 @@ public class ProjectTest { .state(STATE) .parent(PARENT) .build(); - private static final List OWNER_MEMBER_LIST = ImmutableList.of( - Member.user("first-owner@email.com"), Member.group("group-of-owners@email.com")); - private static final List EDITOR_MEMBER_LIST = - ImmutableList.of(Member.serviceAccount("editor@someemail.com")); - private static final List VIEWER_MEMBER_LIST = - ImmutableList.of(Member.serviceAccount("app@someemail.com"), Member.user("viewer@email.com")); - private static final Binding OWNER_BINDING = - Policy.Binding.builder().role(RoleType.OWNER).members(OWNER_MEMBER_LIST).build(); - private static final Binding EDITOR_BINDING = - Policy.Binding.builder().role(RoleType.EDITOR).members(EDITOR_MEMBER_LIST).build(); - private static final Binding VIEWER_BINDING = - Policy.Binding.builder().role(RoleType.VIEWER).members(VIEWER_MEMBER_LIST).build(); - private static final Policy POLICY = - Policy.builder() - .addBinding(OWNER_BINDING) - .addBinding(EDITOR_BINDING) - .addBinding(VIEWER_BINDING) - .version(1) - .etag("some-etag-value") - .build(); - private static final Permission[] PERMISSIONS_REQUESTED = {Permission.REPLACE, Permission.GET}; - private static final List PERMISSIONS_OWNED = ImmutableList.of(false, true); private ResourceManager resourceManager; private Project project; @@ -86,7 +56,7 @@ public class ProjectTest { @Before public void setUp() throws Exception { resourceManager = createStrictMock(ResourceManager.class); - project = new Project(resourceManager, PROJECT_INFO, POLICY); + project = new Project(resourceManager, PROJECT_INFO); } @After @@ -97,30 +67,24 @@ public void tearDown() throws Exception { @Test public void testLoad() { expect(resourceManager.get(PROJECT_INFO.id())).andReturn(PROJECT_INFO); - expect(resourceManager.getIamPolicy(PROJECT_INFO.id())).andReturn(POLICY); replay(resourceManager); Project loadedProject = Project.load(resourceManager, PROJECT_INFO.id()); assertEquals(PROJECT_INFO, loadedProject.info()); - assertEquals(POLICY, loadedProject.policy()); } @Test public void testReload() { ProjectInfo newInfo = PROJECT_INFO.toBuilder().addLabel("k3", "v3").build(); - Policy newPolicy = POLICY.toBuilder().removeBinding(VIEWER_BINDING).build(); expect(resourceManager.get(PROJECT_INFO.id())).andReturn(newInfo); - expect(resourceManager.getIamPolicy(PROJECT_INFO.id())).andReturn(newPolicy); replay(resourceManager); Project newProject = project.reload(); assertSame(resourceManager, newProject.resourceManager()); assertEquals(newInfo, newProject.info()); - assertEquals(newPolicy, newProject.policy()); } @Test public void testPolicy() { replay(resourceManager); - assertEquals(POLICY, project.policy()); } @Test @@ -159,40 +123,5 @@ public void testReplace() { Project newProject = project.replace(newInfo); assertSame(resourceManager, newProject.resourceManager()); assertEquals(newInfo, newProject.info()); - assertEquals(POLICY, newProject.policy()); - } - - @Test - public void testReplaceIamPolicy() { - Policy newPolicy = POLICY.toBuilder().removeBinding(VIEWER_BINDING).build(); - expect(resourceManager.replaceIamPolicy(PROJECT_INFO.id(), newPolicy)).andReturn(newPolicy); - replay(resourceManager); - Project newProject = project.replaceIamPolicy(newPolicy); - assertSame(resourceManager, newProject.resourceManager()); - assertEquals(PROJECT_INFO, newProject.info()); - assertEquals(newPolicy, newProject.policy()); - } - - @Test - public void testHasPermissions() { - expect(resourceManager.hasPermissions(PROJECT_INFO.id(), PERMISSIONS_REQUESTED)) - .andReturn(PERMISSIONS_OWNED); - replay(resourceManager); - List response = - project.hasPermissions(PERMISSIONS_REQUESTED[0], PERMISSIONS_REQUESTED[1]); - assertEquals(PERMISSIONS_OWNED, response); - } - - @Test - public void testHasAllPermissions() { - expect(resourceManager.hasPermissions(PROJECT_INFO.id(), PERMISSIONS_REQUESTED)) - .andReturn(PERMISSIONS_OWNED); - Permission[] permissionsRequestAllOwned = {Permission.UNDELETE, Permission.DELETE}; - List permissionsResponseAllOwned = ImmutableList.of(true, true); - expect(resourceManager.hasPermissions(PROJECT_INFO.id(), permissionsRequestAllOwned)) - .andReturn(permissionsResponseAllOwned); - replay(resourceManager); - assertFalse(project.hasAllPermissions(PERMISSIONS_REQUESTED)); - assertTrue(project.hasAllPermissions(permissionsRequestAllOwned)); } } diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java index 0d035af52f6f..0929ea18c94a 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java @@ -19,14 +19,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.gcloud.AuthCredentials; import com.google.gcloud.PageImpl; import com.google.gcloud.RetryParams; -import com.google.gcloud.resourcemanager.Policy.Binding; -import com.google.gcloud.resourcemanager.Policy.Member; -import com.google.gcloud.resourcemanager.Policy.RoleType; import org.junit.Test; @@ -37,32 +33,10 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Collections; -import java.util.List; public class SerializationTest { private static final ResourceId RESOURCE_ID = ResourceId.of("some id", "organization"); - private static final List OWNER_MEMBER_LIST = ImmutableList.of( - Member.user("first-owner@email.com"), Member.group("group-of-owners@email.com")); - private static final List EDITOR_MEMBER_LIST = - ImmutableList.of(Member.serviceAccount("editor@someemail.com")); - private static final List VIEWER_MEMBER_LIST = - ImmutableList.of(Member.serviceAccount("app@someemail.com"), Member.user("viewer@email.com")); - private static final Binding OWNER_BINDING = - Policy.Binding.builder().role(RoleType.OWNER).members(OWNER_MEMBER_LIST).build(); - private static final Binding EDITOR_BINDING = - Policy.Binding.builder().role(RoleType.EDITOR).members(EDITOR_MEMBER_LIST).build(); - private static final Binding VIEWER_BINDING = - Policy.Binding.builder().role(RoleType.VIEWER).members(VIEWER_MEMBER_LIST).build(); - private static final Policy EMPTY_POLICY = Policy.builder().build(); - private static final Policy FULL_POLICY = - Policy.builder() - .addBinding(OWNER_BINDING) - .addBinding(EDITOR_BINDING) - .addBinding(VIEWER_BINDING) - .version(1) - .etag("some-etag-value") - .build(); private static final ProjectInfo PARTIAL_PROJECT_INFO = ProjectInfo.builder("id1").build(); private static final ProjectInfo FULL_PROJECT_INFO = ProjectInfo.builder("id") @@ -93,9 +67,7 @@ public void testServiceOptions() throws Exception { @Test public void testModelAndRequests() throws Exception { - Serializable[] objects = {RESOURCE_ID, OWNER_BINDING.members().get(0), OWNER_BINDING, - EDITOR_BINDING, VIEWER_BINDING, EMPTY_POLICY, FULL_POLICY, PARTIAL_PROJECT_INFO, - FULL_PROJECT_INFO, PAGE_RESULT}; + Serializable[] objects = {RESOURCE_ID, PARTIAL_PROJECT_INFO, FULL_PROJECT_INFO, PAGE_RESULT}; for (Serializable obj : objects) { Object copy = serializeAndDeserialize(obj); assertEquals(obj, obj); From 9f7fc1a7cb8c67beec23cef4a8c36e08b223b9b1 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 24 Nov 2015 17:21:09 -0800 Subject: [PATCH 05/10] Added docs, removed policy-related methods from spi layer, fixed list options --- .../google/gcloud/resourcemanager/Option.java | 73 +++++++++++++++ .../gcloud/resourcemanager/Project.java | 2 +- .../gcloud/resourcemanager/ProjectInfo.java | 40 ++++---- .../gcloud/resourcemanager/ResourceId.java | 22 ++++- .../resourcemanager/ResourceManager.java | 91 ++++++++++++------- .../google/gcloud/spi/ResourceManagerRpc.java | 30 ------ 6 files changed, 174 insertions(+), 84 deletions(-) create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Option.java 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 new file mode 100644 index 000000000000..9900861b93cc --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/Option.java @@ -0,0 +1,73 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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 com.google.gcloud.resourcemanager; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; +import com.google.gcloud.spi.ResourceManagerRpc; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Base class for Resource Manager operation options + */ +public class Option implements Serializable { + + private static final long serialVersionUID = 2655177550880762967L; + + private final ResourceManagerRpc.Option rpcOption; + private final Object value; + + Option(ResourceManagerRpc.Option rpcOption, Object value) { + this.rpcOption = checkNotNull(rpcOption); + this.value = value; + } + + ResourceManagerRpc.Option rpcOption() { + return rpcOption; + } + + Object value() { + return value; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Option)) { + return false; + } + Option other = (Option) obj; + return Objects.equals(rpcOption, other.rpcOption) + && Objects.equals(value, other.value); + } + + @Override + public int hashCode() { + return Objects.hash(rpcOption, value); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", rpcOption.value()) + .add("value", value) + .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 5f17bd48336e..b9abdabc9f87 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 @@ -109,7 +109,7 @@ public void delete() { * @see * Cloud Resource Manager undelete - * @throws ResourceManagerException + * @throws ResourceManagerException upon failure (including when the project can't be restored) */ public void undelete() { resourceManager.undelete(info.id()); 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 b5913b763ea0..8dbc41d691a4 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 @@ -19,7 +19,6 @@ 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; @@ -45,19 +44,32 @@ public class ProjectInfo implements Serializable { * The project lifecycle state. * *
        - *
      • LIFECYCLE_STATE_UNSPECIFIED: only used/useful for distinguishing unset values - *
      • ACTIVE: the normal and active state - *
      • DELETE_REQUESTED: the project has been marked for deletion by the user or by the system - * (Google Cloud Platform). This can generally be reversed by calling - * {@link ResourceManager#undelete}. - *
      • DELETE_IN_PROGRESS: the process of deleting the project has begun. Reversing the deletion - * is no longer possible. + *
      • LIFECYCLE_STATE_UNSPECIFIED: + *
      • ACTIVE: + *
      • DELETE_REQUESTED: + *
      • DELETE_IN_PROGRESS: *
          */ public enum State { + /** + * Only used/useful for distinguishing unset values + */ LIFECYCLE_STATE_UNSPECIFIED, + + /** + * The normal and active state + */ ACTIVE, + + /** + * The project has been marked for deletion by the user or by the system (Google Cloud + * Platform). This can generally be reversed by calling {@link ResourceManager#undelete}. + */ DELETE_REQUESTED, + + /** + * the process of deleting the project has begun. Reversing the deletion is no longer possible. + */ DELETE_IN_PROGRESS } @@ -289,19 +301,11 @@ com.google.api.services.cloudresourcemanager.model.Project toPb() { } static ProjectInfo fromPb(com.google.api.services.cloudresourcemanager.model.Project projectPb) { - ProjectInfo.Builder builder = - ProjectInfo.builder(projectPb.getProjectId()) - .name(projectPb.getName()) - .number(projectPb.getProjectNumber()); + ProjectInfo.Builder builder = + ProjectInfo.builder(projectPb.getProjectId()).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())); } diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java index f2907b9dca6a..77d0cfe58866 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java @@ -20,7 +20,11 @@ import java.util.Objects; /** - * Represents a Google Cloud Resource Manager Resource ID + * Represents a Google Cloud Resource Manager Resource ID. + * + * A 'resource' in Google Cloud Platform is a generic term for something you (a developer) may want + * to interact with through one of our API's. Some examples are an AppEngine app, a Compute Engine + * instance, and Cloud SQL database. */ public class ResourceId implements Serializable { @@ -33,10 +37,20 @@ private ResourceId(String id, String type) { this.type = checkNotNull(type); } + /** + * Required field for the type-specific ID. + * + * This should correspond to the ID used in the type-specific APIs. + */ public String id() { return id; } + /** + * Required field representing the resource type this ID is for. + * + * At present, the only valid type is "organization". + */ public String type() { return type; } @@ -51,6 +65,12 @@ public int hashCode() { return Objects.hash(id, type); } + /** + * Create a new Resource ID with the given ID and resource type. + * + * The ID should correspond to the ID used in the type-specific APIs. At present, the only valid + * type is "organization". + */ public static ResourceId of(String id, String type) { return new ResourceId(id, type); } 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 2f999b7ca4e6..a0405ef5117e 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 @@ -16,14 +16,9 @@ package com.google.gcloud.resourcemanager; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.collect.ImmutableList; import com.google.gcloud.Page; import com.google.gcloud.Service; - -import java.util.Collections; -import java.util.List; +import com.google.gcloud.spi.ResourceManagerRpc; /** * An interface for Google Cloud Resource Manager. @@ -34,39 +29,66 @@ public interface ResourceManager extends Service { public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; - public class ListOptions { - private List filters; - private String pageToken; - private int pageSize; - - private static final ListOptions DEFAULT_INSTANCE = - new ListOptions(Collections.emptyList(), null, -1); - - ListOptions(List filters, String pageToken, int pageSize) { - this.filters = checkNotNull(ImmutableList.copyOf(filters)); - this.pageToken = pageToken; - this.pageSize = pageSize; - } + /** + * Class for specifying project list options. + */ + public class ProjectListOption extends Option { - public static ListOptions getDefaultInstance() { - return DEFAULT_INSTANCE; - } + private static final long serialVersionUID = 7888768979702012328L; - public static ListOptions createListOption( - List filters, String pageToken, int pageSize) { - return new ListOptions(filters, pageToken, pageSize); + private ProjectListOption(ResourceManagerRpc.Option option, Object value) { + super(option, value); } - public String pageToken() { - return pageToken; + /** + * Returns an option to specify a page token. + * + * The page token (returned from a previous call to list) indicates from where listing should + * continue. Pagination is not yet supported; the server ignores this field. Optional. + */ + public static ProjectListOption pageToken(String pageToken) { + // return new ProjectListOption(ResourceManagerRpc.Option.PAGE_TOKEN, pageToken); + throw new UnsupportedOperationException("paging for project lists is not implemented yet."); } - public List filters() { - return filters; + /** + * Returns an option to specify a filter. + * + * Filter rules are case insensitive. The fields eligible for filtering are: + *
            + *
          • name + *
          • id + *
          • labels.key, where key is the name of a label + *
          + * + * Some examples of using labels as filters: + *
            + *
          • name:* The project has a name. + *
          • name:Howl The project's name is Howl or howl. + *
          • name:HOWL Equivalent to above. + *
          • NAME:howl Equivalent to above. + *
          • labels.color:* The project has the label color. + *
          • labels.color:red The project's label color has the value red. + *
          • 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); } - public int pageSize() { - return pageSize; + /** + * The maximum number of projects to return in the response. + * + * The server can return fewer projects than requested. If unspecified, server picks an + * appropriate default. Note: pagination is not yet supported; the server ignores this field. + * Optional. + */ + public static ProjectListOption pageSize(int pageSize) { + // return new ProjectListOption(ResourceManagerRpc.Option.PAGE_SIZE, pageSize); + throw new UnsupportedOperationException("paging for project lists is not implemented yet."); } } @@ -127,15 +149,16 @@ public int pageSize() { * Lists the projects visible to the current user. * * This method returns projects in an unspecified order. New projects do not necessarily appear at - * the end of the list. Use {@link ListOptions} to filter this list, set page size, and set page - * tokens. Note that pagination is currently not implemented by the Cloud Resource Manager API. + * 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. * * @see * Cloud Resource Manager list * @return {@code Page}, a page of projects. * @throws ResourceManagerException upon failure */ - Page list(ListOptions listOptions); + Page list(ProjectListOption... options); /** * Replaces the attributes of the project. diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java index 6f07b53d7df2..854994109e3d 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java @@ -16,11 +16,9 @@ package com.google.gcloud.spi; -import com.google.api.services.cloudresourcemanager.model.Policy; import com.google.api.services.cloudresourcemanager.model.Project; import com.google.gcloud.resourcemanager.ResourceManagerException; -import java.util.List; import java.util.Map; public interface ResourceManagerRpc { @@ -54,27 +52,6 @@ Long getInt(Map options) { } } - public enum Permission { - CREATE("resourcemanager.projects.create"), - DELETE("resourcemanager.projects.delete"), - GET("resourcemanager.projects.get"), - LIST("resourcemanager.projects.list"), - REPLACE("resourcemanager.projects.replace"), - UNDELETE("resourcemanager.projects.undelete"), - GET_IAM_POLICY("resourcemanager.projects.getIamPolicy"), - REPLACE_IAM_POLICY("resourcemanager.projects.setIamPolicy"); - - String permissionPb; - - Permission(String permissionPb) { - this.permissionPb = permissionPb; - } - - String toPb() { - return permissionPb; - } - } - class Tuple { private final X x; private final Y y; @@ -109,12 +86,5 @@ public Y y() { Project replace(Project project) throws ResourceManagerException; - Policy getIamPolicy(String projectId) throws ResourceManagerException; - - Policy replaceIamPolicy(String projectId, Policy policy) throws ResourceManagerException; - - List hasPermissions(String projectId, List permissions) - throws ResourceManagerException; - // TODO(ajaykannan): implement "Organization" functionality when available (issue #319) } From 0ec9f500dba1969f407baa8e87353475e815ee6a Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Wed, 25 Nov 2015 15:42:06 -0800 Subject: [PATCH 06/10] Remove parent and resource ID, add fields options --- .../gcloud/resourcemanager/ProjectInfo.java | 37 +------- .../gcloud/resourcemanager/ResourceId.java | 90 ------------------- .../resourcemanager/ResourceManager.java | 87 ++++++++++++++---- .../google/gcloud/spi/ResourceManagerRpc.java | 3 +- .../resourcemanager/ProjectInfoTest.java | 6 -- .../gcloud/resourcemanager/ProjectTest.java | 2 - .../resourcemanager/ResourceIdTest.java | 51 ----------- .../resourcemanager/SerializationTest.java | 4 +- 8 files changed, 73 insertions(+), 207 deletions(-) delete mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java delete mode 100644 gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java 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 8dbc41d691a4..4e45e1274dbf 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 @@ -38,7 +38,6 @@ public class ProjectInfo implements Serializable { private final Long number; private final State state; private final Long createTimeMillis; - private final ResourceId parent; /** * The project lifecycle state. @@ -80,7 +79,6 @@ public static class Builder { private Long number; private State state; private Long createTimeMillis; - private ResourceId parent; Builder() { labels = new HashMap<>(); @@ -165,20 +163,6 @@ Builder createTimeMillis(Long createTimeMillis) { return this; } - /** - * Set the parent of the project. - * - * If this field is left unset in a project creation request, the server will set this field by - * default to the creator of the project. The parent cannot be changed after the server creates - * the project. When calling {@link ResourceManager#replace}, be sure to set the parent of the - * new ProjectInfo instance. Leaving the parent unset or setting it to null in a replace request - * will cause an error. - */ - public Builder parent(ResourceId parent) { - this.parent = parent; - return this; - } - public ProjectInfo build() { return new ProjectInfo(this); } @@ -191,7 +175,6 @@ public ProjectInfo build() { this.number = builder.number; this.state = builder.state; this.createTimeMillis = builder.createTimeMillis; - this.parent = builder.parent; } /** @@ -247,15 +230,6 @@ public Long createTimeMillis() { return createTimeMillis; } - /** - * Get the parent of the project. - * - * The parent cannot be changed after the server creates the project. - */ - public ResourceId parent() { - return parent; - } - @Override public boolean equals(Object obj) { return obj instanceof ProjectInfo && Objects.equals(toPb(), ((ProjectInfo) obj).toPb()); @@ -263,7 +237,7 @@ public boolean equals(Object obj) { @Override public int hashCode() { - return Objects.hash(name, id, labels, number, state, createTimeMillis, parent); + return Objects.hash(name, id, labels, number, state, createTimeMillis); } public static Builder builder(String id) { @@ -277,8 +251,7 @@ public Builder toBuilder() { .labels(labels) .number(number) .state(state) - .createTimeMillis(createTimeMillis) - .parent(parent); + .createTimeMillis(createTimeMillis); } com.google.api.services.cloudresourcemanager.model.Project toPb() { @@ -294,9 +267,6 @@ com.google.api.services.cloudresourcemanager.model.Project toPb() { if (createTimeMillis != null) { projectPb.setCreateTime(ISODateTimeFormat.dateTime().print(createTimeMillis)); } - if (parent != null) { - projectPb.setParent(parent.toPb()); - } return projectPb; } @@ -306,9 +276,6 @@ static ProjectInfo fromPb(com.google.api.services.cloudresourcemanager.model.Pro if (projectPb.getLabels() != null) { builder.labels(projectPb.getLabels()); } - 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/ResourceId.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java deleted file mode 100644 index 77d0cfe58866..000000000000 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceId.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed 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 com.google.gcloud.resourcemanager; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.io.Serializable; -import java.util.Objects; - -/** - * Represents a Google Cloud Resource Manager Resource ID. - * - * A 'resource' in Google Cloud Platform is a generic term for something you (a developer) may want - * to interact with through one of our API's. Some examples are an AppEngine app, a Compute Engine - * instance, and Cloud SQL database. - */ -public class ResourceId implements Serializable { - - private static final long serialVersionUID = 7928469304338358885L; - private final String id; - private final String type; - - private ResourceId(String id, String type) { - this.id = checkNotNull(id); - this.type = checkNotNull(type); - } - - /** - * Required field for the type-specific ID. - * - * This should correspond to the ID used in the type-specific APIs. - */ - public String id() { - return id; - } - - /** - * Required field representing the resource type this ID is for. - * - * At present, the only valid type is "organization". - */ - public 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); - } - - /** - * Create a new Resource ID with the given ID and resource type. - * - * The ID should correspond to the ID used in the type-specific APIs. At present, the only valid - * type is "organization". - */ - public static ResourceId of(String id, String type) { - return new ResourceId(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()); - } -} 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 a0405ef5117e..46183bfc8188 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 @@ -16,10 +16,14 @@ package com.google.gcloud.resourcemanager; +import com.google.common.base.Joiner; +import com.google.common.collect.Sets; import com.google.gcloud.Page; import com.google.gcloud.Service; import com.google.gcloud.spi.ResourceManagerRpc; +import java.util.HashSet; + /** * An interface for Google Cloud Resource Manager. * @@ -30,25 +34,70 @@ public interface ResourceManager extends Service { public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; /** - * Class for specifying project list options. + * The fields of a project. + * + * These values can be used to specify the fields to include of in a partial response when calling + * {@link ResourceManager#get} or {@link ResourceManager#list}. Project ID is always returned, + * even if not specified. */ - public class ProjectListOption extends Option { + enum ProjectField { + ID("projectId"), + NAME("name"), + LABELS("labels"), + NUMBER("projectNumber"), + STATE("lifecycleState"), + CREATE_TIME("createTime"); + + private final String selector; + + ProjectField(String selector) { + this.selector = selector; + } - private static final long serialVersionUID = 7888768979702012328L; + public String selector() { + return selector; + } - private ProjectListOption(ResourceManagerRpc.Option option, Object value) { + static String selector(ProjectField... fields) { + HashSet fieldStrings = Sets.newHashSetWithExpectedSize(fields.length + 1); + fieldStrings.add(ID.selector()); + for (ProjectField field : fields) { + fieldStrings.add(field.selector()); + } + return Joiner.on(',').join(fieldStrings); + } + } + + public class ProjectGetOption extends Option { + + private static final long serialVersionUID = 270185129961146874L; + + private ProjectGetOption(ResourceManagerRpc.Option option, Object value) { super(option, value); } /** - * Returns an option to specify a page token. + * Returns an option to specify the project's fields to be returned by the RPC call. * - * The page token (returned from a previous call to list) indicates from where listing should - * continue. Pagination is not yet supported; the server ignores this field. Optional. + * 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. */ - public static ProjectListOption pageToken(String pageToken) { - // return new ProjectListOption(ResourceManagerRpc.Option.PAGE_TOKEN, pageToken); - throw new UnsupportedOperationException("paging for project lists is not implemented yet."); + public static ProjectGetOption fields(ProjectField... fields) { + return new ProjectGetOption(ResourceManagerRpc.Option.FIELDS, ProjectField.selector(fields)); + } + } + + /** + * Class for specifying project list options. + */ + public class ProjectListOption extends Option { + + private static final long serialVersionUID = 7888768979702012328L; + + private ProjectListOption(ResourceManagerRpc.Option option, Object value) { + super(option, value); } /** @@ -80,15 +129,17 @@ public static ProjectListOption filter(String filter) { } /** - * The maximum number of projects to return in the response. + * Returns an option to specify the project's fields to be returned by the RPC call. * - * The server can return fewer projects than requested. If unspecified, server picks an - * appropriate default. Note: pagination is not yet supported; the server ignores this field. - * Optional. + * 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. */ - public static ProjectListOption pageSize(int pageSize) { - // return new ProjectListOption(ResourceManagerRpc.Option.PAGE_SIZE, pageSize); - throw new UnsupportedOperationException("paging for project lists is not implemented yet."); + public static ProjectListOption fields(ProjectField... fields) { + StringBuilder builder = new StringBuilder(); + builder.append("projects(").append(ProjectField.selector(fields)).append(")"); + return new ProjectListOption(ResourceManagerRpc.Option.FIELDS, builder.toString()); } } @@ -143,7 +194,7 @@ public static ProjectListOption pageSize(int pageSize) { * Cloud Resource Manager get * @throws ResourceManagerException upon failure */ - ProjectInfo get(String projectId); + ProjectInfo get(String projectId, ProjectGetOption... options); /** * Lists the projects visible to the current user. diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java index 854994109e3d..f7e330639399 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java @@ -25,8 +25,7 @@ public interface ResourceManagerRpc { enum Option { FILTER("filter"), - PAGE_SIZE("maxResults"), - PAGE_TOKEN("pageToken"); + FIELDS("fields"); private final String value; diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java index ef4d213721de..e11962d94273 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java @@ -34,7 +34,6 @@ public class ProjectInfoTest { private static final Long NUMBER = 123L; private static final Long CREATE_TIME_MILLIS = 123456789L; private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; - private static final ResourceId PARENT = ResourceId.of("owner-id", "organization"); private static final ProjectInfo FULL_PROJECT_INFO = ProjectInfo.builder(ID) .name(NAME) @@ -42,7 +41,6 @@ public class ProjectInfoTest { .number(NUMBER) .createTimeMillis(CREATE_TIME_MILLIS) .state(STATE) - .parent(PARENT) .build(); private static final ProjectInfo PARTIAL_PROJECT_INFO = ProjectInfo.builder(ID).build(); @@ -54,7 +52,6 @@ public void testBuilder() { assertEquals(NUMBER, FULL_PROJECT_INFO.number()); assertEquals(CREATE_TIME_MILLIS, FULL_PROJECT_INFO.createTimeMillis()); assertEquals(STATE, FULL_PROJECT_INFO.state()); - assertEquals(PARENT, FULL_PROJECT_INFO.parent()); assertEquals(ID, PARTIAL_PROJECT_INFO.id()); assertEquals(null, PARTIAL_PROJECT_INFO.name()); @@ -62,7 +59,6 @@ public void testBuilder() { assertEquals(null, PARTIAL_PROJECT_INFO.number()); assertEquals(null, PARTIAL_PROJECT_INFO.createTimeMillis()); assertEquals(null, PARTIAL_PROJECT_INFO.state()); - assertEquals(null, PARTIAL_PROJECT_INFO.parent()); } @Test @@ -87,7 +83,6 @@ public void testEquals() { .number(NUMBER) .createTimeMillis(CREATE_TIME_MILLIS) .state(STATE) - .parent(PARENT) .build()); compareProjects(PARTIAL_PROJECT_INFO, ProjectInfo.builder(ID).build()); assertNotEquals(FULL_PROJECT_INFO, PARTIAL_PROJECT_INFO); @@ -101,7 +96,6 @@ private void compareProjects(ProjectInfo expected, ProjectInfo value) { assertEquals(expected.number(), value.number()); assertEquals(expected.createTimeMillis(), value.createTimeMillis()); assertEquals(expected.state(), value.state()); - assertEquals(expected.parent(), value.parent()); } } diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java index 9201448f60f8..ddb543752ac7 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java @@ -39,7 +39,6 @@ public class ProjectTest { private static final Long NUMBER = 123L; private static final Long CREATE_TIME_MILLIS = 123456789L; private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; - private static final ResourceId PARENT = ResourceId.of("owner-id", "organization"); private static final ProjectInfo PROJECT_INFO = ProjectInfo.builder(ID) .name(NAME) @@ -47,7 +46,6 @@ public class ProjectTest { .number(NUMBER) .createTimeMillis(CREATE_TIME_MILLIS) .state(STATE) - .parent(PARENT) .build(); private ResourceManager resourceManager; diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java deleted file mode 100644 index 9fed10759931..000000000000 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ResourceIdTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 Google Inc. All Rights Reserved. - * - * Licensed 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 com.google.gcloud.resourcemanager; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import org.junit.Test; - -public class ResourceIdTest { - - private static final String ID = "id"; - private static final String TYPE = "organization"; - private static final ResourceId RESOURCE_ID = ResourceId.of(ID, TYPE); - - @Test - public void testOf() { - assertEquals(ID, RESOURCE_ID.id()); - assertEquals(TYPE, RESOURCE_ID.type()); - } - - @Test - public void testEquals() { - assertEquals(RESOURCE_ID, ResourceId.of(ID, TYPE)); - assertEquals(ID, RESOURCE_ID.id()); - assertEquals(TYPE, RESOURCE_ID.type()); - assertNotEquals(ResourceId.of("another-ID", TYPE), RESOURCE_ID); - } - - @Test - public void testToAndFromPb() { - ResourceId copy = ResourceId.fromPb(RESOURCE_ID.toPb()); - assertEquals(RESOURCE_ID, copy); - assertEquals(ID, copy.id()); - assertEquals(TYPE, copy.type()); - } -} diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java index 0929ea18c94a..5b981ce4c77a 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java @@ -36,7 +36,6 @@ public class SerializationTest { - private static final ResourceId RESOURCE_ID = ResourceId.of("some id", "organization"); private static final ProjectInfo PARTIAL_PROJECT_INFO = ProjectInfo.builder("id1").build(); private static final ProjectInfo FULL_PROJECT_INFO = ProjectInfo.builder("id") @@ -45,7 +44,6 @@ public class SerializationTest { .number(123L) .state(ProjectInfo.State.ACTIVE) .createTimeMillis(1234L) - .parent(RESOURCE_ID) .build(); private static final PageImpl PAGE_RESULT = new PageImpl<>(null, "c", Collections.singletonList(PARTIAL_PROJECT_INFO)); @@ -67,7 +65,7 @@ public void testServiceOptions() throws Exception { @Test public void testModelAndRequests() throws Exception { - Serializable[] objects = {RESOURCE_ID, PARTIAL_PROJECT_INFO, FULL_PROJECT_INFO, PAGE_RESULT}; + Serializable[] objects = {PARTIAL_PROJECT_INFO, FULL_PROJECT_INFO, PAGE_RESULT}; for (Serializable obj : objects) { Object copy = serializeAndDeserialize(obj); assertEquals(obj, obj); From 4107bbe83851b75aacb054a944bf76683b6d8552 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Fri, 27 Nov 2015 13:19:01 -0800 Subject: [PATCH 07/10] Add exception handling, add back resource ID, and other cleanup --- .../google/gcloud/resourcemanager/Option.java | 3 +- .../gcloud/resourcemanager/Project.java | 30 ++-- .../gcloud/resourcemanager/ProjectInfo.java | 152 +++++++++++++----- .../resourcemanager/ResourceManager.java | 55 ++++--- .../ResourceManagerException.java | 8 +- .../gcloud/spi/DefaultResourceManagerRpc.java | 89 ++++++++++ .../resourcemanager/ProjectInfoTest.java | 44 ++--- .../gcloud/resourcemanager/ProjectTest.java | 34 ++-- .../resourcemanager/SerializationTest.java | 26 ++- 9 files changed, 306 insertions(+), 135 deletions(-) create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/DefaultResourceManagerRpc.java 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..b8631a9ae881 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,14 @@ 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 +127,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 +154,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 +181,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 +193,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 +208,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 +221,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 +237,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 options) + throws ResourceManagerException { + // TODO(ajaykannan): fix me! + return null; + } + + @Override + public void undelete(String projectId) throws ResourceManagerException { + // TODO(ajaykannan): fix me! + } + + @Override + public Project replace(Project project) throws ResourceManagerException { + // TODO(ajaykannan): fix me! + return null; + } +} + diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java index e11962d94273..c066ccf39ca4 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectInfoTest.java @@ -28,35 +28,37 @@ public class ProjectInfoTest { - private static final String ID = "project-id"; + private static final String PROJECT_ID = "project-id"; private static final String NAME = "myProj"; private static final Map LABELS = ImmutableMap.of("k1", "v1", "k2", "v2"); - private static final Long NUMBER = 123L; + private static final Long PROJECT_NUMBER = 123L; private static final Long CREATE_TIME_MILLIS = 123456789L; private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; - private static final ProjectInfo FULL_PROJECT_INFO = - ProjectInfo.builder(ID) - .name(NAME) - .labels(LABELS) - .number(NUMBER) - .createTimeMillis(CREATE_TIME_MILLIS) - .state(STATE) - .build(); - private static final ProjectInfo PARTIAL_PROJECT_INFO = ProjectInfo.builder(ID).build(); + private static final ProjectInfo.ResourceId PARENT = + new ProjectInfo.ResourceId("id", "organization"); + private static final ProjectInfo FULL_PROJECT_INFO = ProjectInfo.builder(PROJECT_ID) + .name(NAME) + .labels(LABELS) + .projectNumber(PROJECT_NUMBER) + .createTimeMillis(CREATE_TIME_MILLIS) + .state(STATE) + .parent(PARENT) + .build(); + private static final ProjectInfo PARTIAL_PROJECT_INFO = ProjectInfo.builder(PROJECT_ID).build(); @Test public void testBuilder() { - assertEquals(ID, FULL_PROJECT_INFO.id()); + assertEquals(PROJECT_ID, FULL_PROJECT_INFO.projectId()); assertEquals(NAME, FULL_PROJECT_INFO.name()); assertEquals(LABELS, FULL_PROJECT_INFO.labels()); - assertEquals(NUMBER, FULL_PROJECT_INFO.number()); + assertEquals(PROJECT_NUMBER, FULL_PROJECT_INFO.projectNumber()); assertEquals(CREATE_TIME_MILLIS, FULL_PROJECT_INFO.createTimeMillis()); assertEquals(STATE, FULL_PROJECT_INFO.state()); - assertEquals(ID, PARTIAL_PROJECT_INFO.id()); + assertEquals(PROJECT_ID, PARTIAL_PROJECT_INFO.projectId()); assertEquals(null, PARTIAL_PROJECT_INFO.name()); assertTrue(PARTIAL_PROJECT_INFO.labels().isEmpty()); - assertEquals(null, PARTIAL_PROJECT_INFO.number()); + assertEquals(null, PARTIAL_PROJECT_INFO.projectNumber()); assertEquals(null, PARTIAL_PROJECT_INFO.createTimeMillis()); assertEquals(null, PARTIAL_PROJECT_INFO.state()); } @@ -77,25 +79,27 @@ public void testToAndFromPb() { public void testEquals() { compareProjects( FULL_PROJECT_INFO, - ProjectInfo.builder(ID) + ProjectInfo.builder(PROJECT_ID) .name(NAME) .labels(LABELS) - .number(NUMBER) + .projectNumber(PROJECT_NUMBER) .createTimeMillis(CREATE_TIME_MILLIS) .state(STATE) + .parent(PARENT) .build()); - compareProjects(PARTIAL_PROJECT_INFO, ProjectInfo.builder(ID).build()); + compareProjects(PARTIAL_PROJECT_INFO, ProjectInfo.builder(PROJECT_ID).build()); assertNotEquals(FULL_PROJECT_INFO, PARTIAL_PROJECT_INFO); } private void compareProjects(ProjectInfo expected, ProjectInfo value) { assertEquals(expected, value); - assertEquals(expected.id(), value.id()); + assertEquals(expected.projectId(), value.projectId()); assertEquals(expected.name(), value.name()); assertEquals(expected.labels(), value.labels()); - assertEquals(expected.number(), value.number()); + assertEquals(expected.projectNumber(), value.projectNumber()); assertEquals(expected.createTimeMillis(), value.createTimeMillis()); assertEquals(expected.state(), value.state()); + assertEquals(expected.parent(), value.parent()); } } diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java index ddb543752ac7..223dd5b14289 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java @@ -33,20 +33,19 @@ import java.util.Map; public class ProjectTest { - private static final String ID = "project-id"; + private static final String PROJECT_ID = "project-id"; private static final String NAME = "myProj"; private static final Map LABELS = ImmutableMap.of("k1", "v1", "k2", "v2"); - private static final Long NUMBER = 123L; + private static final Long PROJECT_NUMBER = 123L; private static final Long CREATE_TIME_MILLIS = 123456789L; private static final ProjectInfo.State STATE = ProjectInfo.State.DELETE_REQUESTED; - private static final ProjectInfo PROJECT_INFO = - ProjectInfo.builder(ID) - .name(NAME) - .labels(LABELS) - .number(NUMBER) - .createTimeMillis(CREATE_TIME_MILLIS) - .state(STATE) - .build(); + private static final ProjectInfo PROJECT_INFO = ProjectInfo.builder(PROJECT_ID) + .name(NAME) + .labels(LABELS) + .projectNumber(PROJECT_NUMBER) + .createTimeMillis(CREATE_TIME_MILLIS) + .state(STATE) + .build(); private ResourceManager resourceManager; private Project project; @@ -64,27 +63,22 @@ public void tearDown() throws Exception { @Test public void testLoad() { - expect(resourceManager.get(PROJECT_INFO.id())).andReturn(PROJECT_INFO); + expect(resourceManager.get(PROJECT_INFO.projectId())).andReturn(PROJECT_INFO); replay(resourceManager); - Project loadedProject = Project.load(resourceManager, PROJECT_INFO.id()); + Project loadedProject = Project.load(resourceManager, PROJECT_INFO.projectId()); assertEquals(PROJECT_INFO, loadedProject.info()); } @Test public void testReload() { ProjectInfo newInfo = PROJECT_INFO.toBuilder().addLabel("k3", "v3").build(); - expect(resourceManager.get(PROJECT_INFO.id())).andReturn(newInfo); + expect(resourceManager.get(PROJECT_INFO.projectId())).andReturn(newInfo); replay(resourceManager); Project newProject = project.reload(); assertSame(resourceManager, newProject.resourceManager()); assertEquals(newInfo, newProject.info()); } - @Test - public void testPolicy() { - replay(resourceManager); - } - @Test public void testInfo() { replay(resourceManager); @@ -99,7 +93,7 @@ public void testResourceManager() { @Test public void testDelete() { - resourceManager.delete(PROJECT_INFO.id()); + resourceManager.delete(PROJECT_INFO.projectId()); expectLastCall(); replay(resourceManager); project.delete(); @@ -107,7 +101,7 @@ public void testDelete() { @Test public void testUndelete() { - resourceManager.undelete(PROJECT_INFO.id()); + resourceManager.undelete(PROJECT_INFO.projectId()); expectLastCall(); replay(resourceManager); project.undelete(); diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java index 5b981ce4c77a..dd8fb8014bf0 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java @@ -37,14 +37,13 @@ public class SerializationTest { private static final ProjectInfo PARTIAL_PROJECT_INFO = ProjectInfo.builder("id1").build(); - private static final ProjectInfo FULL_PROJECT_INFO = - ProjectInfo.builder("id") - .name("name") - .labels(ImmutableMap.of("key", "value")) - .number(123L) - .state(ProjectInfo.State.ACTIVE) - .createTimeMillis(1234L) - .build(); + private static final ProjectInfo FULL_PROJECT_INFO = ProjectInfo.builder("id") + .name("name") + .labels(ImmutableMap.of("key", "value")) + .projectNumber(123L) + .state(ProjectInfo.State.ACTIVE) + .createTimeMillis(1234L) + .build(); private static final PageImpl PAGE_RESULT = new PageImpl<>(null, "c", Collections.singletonList(PARTIAL_PROJECT_INFO)); @@ -53,12 +52,11 @@ public void testServiceOptions() throws Exception { ResourceManagerOptions options = ResourceManagerOptions.builder().build(); ResourceManagerOptions serializedCopy = serializeAndDeserialize(options); assertEquals(options, serializedCopy); - options = - options.toBuilder() - .projectId("some-unnecessary-project-ID") - .retryParams(RetryParams.defaultInstance()) - .authCredentials(AuthCredentials.noCredentials()) - .build(); + options = options.toBuilder() + .projectId("some-unnecessary-project-ID") + .retryParams(RetryParams.defaultInstance()) + .authCredentials(AuthCredentials.noCredentials()) + .build(); serializedCopy = serializeAndDeserialize(options); assertEquals(options, serializedCopy); } From d67f94bebb5d20de04800387aa530653f1c7102c Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Mon, 30 Nov 2015 09:27:35 -0800 Subject: [PATCH 08/10] Add list/get options serialization tests + other small fixes --- .../com/google/gcloud/resourcemanager/ProjectInfo.java | 6 +++--- .../com/google/gcloud/resourcemanager/ResourceManager.java | 2 +- .../com/google/gcloud/spi/DefaultResourceManagerRpc.java | 7 +++---- .../java/com/google/gcloud/spi/ResourceManagerRpc.java | 2 +- .../com/google/gcloud/resourcemanager/ProjectTest.java | 3 --- .../google/gcloud/resourcemanager/SerializationTest.java | 7 ++++++- 6 files changed, 14 insertions(+), 13 deletions(-) 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 7b48e595ae0d..5d490e662df0 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 @@ -132,7 +132,7 @@ private Builder() { Builder(ProjectInfo info) { this.name = info.name; this.projectId = info.projectId; - this.labels = Maps.newHashMap(checkNotNull(info.labels)); + this.labels.putAll(info.labels); this.projectNumber = info.projectNumber; this.state = info.state; this.createTimeMillis = info.createTimeMillis; @@ -159,7 +159,7 @@ public Builder name(String name) { * project. */ public Builder projectId(String projectId) { - this.projectId = projectId; + this.projectId = checkNotNull(projectId); return this; } @@ -230,7 +230,7 @@ public ProjectInfo build() { ProjectInfo(Builder builder) { this.name = builder.name; - this.projectId = checkNotNull(builder.projectId); + this.projectId = builder.projectId; this.labels = ImmutableMap.copyOf(builder.labels); this.projectNumber = builder.projectNumber; this.state = builder.state; 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 b8631a9ae881..9aabd640b018 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 @@ -36,7 +36,7 @@ public interface ResourceManager extends Service { /** * The fields of a project. * - * These values can be used to specify the fields to include of in a partial response when calling + * 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. */ 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 index 45f8f9de75e9..d73c6ae4015c 100644 --- 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 @@ -17,6 +17,7 @@ public class DefaultResourceManagerRpc implements ResourceManagerRpc { + // see https://cloud.google.com/resource-manager/v1/errors/core_errors private static final Set RETRYABLE_CODES = ImmutableSet.of(503, 500, 429, 417); private final ResourceManagerOptions options; @@ -45,9 +46,7 @@ private static ResourceManagerException translate(IOException exception) { } private static ResourceManagerException translate(GoogleJsonError exception) { - boolean retryable = - RETRYABLE_CODES.contains(exception.getCode()) - || "InternalError".equals(exception.getMessage()); + boolean retryable = RETRYABLE_CODES.contains(exception.getCode()); return new ResourceManagerException(exception.getCode(), exception.getMessage(), retryable); } @@ -63,7 +62,7 @@ public void delete(String projectId) throws ResourceManagerException { } @Override - public Project get(String projectId) throws ResourceManagerException { + public Project get(String projectId, Map options) throws ResourceManagerException { // TODO(ajaykannan): fix me! return null; } diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java index f7e330639399..ec96e26e0be5 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java @@ -77,7 +77,7 @@ public Y y() { void delete(String projectId) throws ResourceManagerException; - Project get(String projectId) throws ResourceManagerException; + Project get(String projectId, Map options) throws ResourceManagerException; Tuple> list(Map options) throws ResourceManagerException; diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java index 223dd5b14289..65bb37dbccf9 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/ProjectTest.java @@ -18,7 +18,6 @@ import static org.easymock.EasyMock.createStrictMock; import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; @@ -94,7 +93,6 @@ public void testResourceManager() { @Test public void testDelete() { resourceManager.delete(PROJECT_INFO.projectId()); - expectLastCall(); replay(resourceManager); project.delete(); } @@ -102,7 +100,6 @@ public void testDelete() { @Test public void testUndelete() { resourceManager.undelete(PROJECT_INFO.projectId()); - expectLastCall(); replay(resourceManager); project.undelete(); } diff --git a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java index dd8fb8014bf0..8b61519fc106 100644 --- a/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java +++ b/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/SerializationTest.java @@ -46,6 +46,10 @@ public class SerializationTest { .build(); private static final PageImpl PAGE_RESULT = new PageImpl<>(null, "c", Collections.singletonList(PARTIAL_PROJECT_INFO)); + private static final ResourceManager.ProjectGetOption PROJECT_GET_OPTION = + ResourceManager.ProjectGetOption.fields(ResourceManager.ProjectField.NAME); + private static final ResourceManager.ProjectListOption PROJECT_LIST_OPTION = + ResourceManager.ProjectListOption.filter("name:*"); @Test public void testServiceOptions() throws Exception { @@ -63,7 +67,8 @@ public void testServiceOptions() throws Exception { @Test public void testModelAndRequests() throws Exception { - Serializable[] objects = {PARTIAL_PROJECT_INFO, FULL_PROJECT_INFO, PAGE_RESULT}; + Serializable[] objects = {PARTIAL_PROJECT_INFO, FULL_PROJECT_INFO, PAGE_RESULT, + PROJECT_GET_OPTION, PROJECT_LIST_OPTION}; for (Serializable obj : objects) { Object copy = serializeAndDeserialize(obj); assertEquals(obj, obj); From 3408d7aacaf19d9a13f1dba506784832c06c2304 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Mon, 30 Nov 2015 12:55:02 -0800 Subject: [PATCH 09/10] Add page size and page token options --- .../resourcemanager/ResourceManager.java | 20 +++++++++++++++++++ .../google/gcloud/spi/ResourceManagerRpc.java | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) 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 9aabd640b018..8f27ff182b48 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 @@ -132,6 +132,26 @@ public static ProjectListOption filter(String filter) { return new ProjectListOption(ResourceManagerRpc.Option.FILTER, filter); } + /** + * Returns an option to specify a page token. + * + * The page token (returned from a previous call to list) indicates from where listing should + * continue. Pagination is not yet supported; the server ignores this field. + */ + public static ProjectListOption pageToken(String pageToken) { + return new ProjectListOption(ResourceManagerRpc.Option.PAGE_TOKEN, pageToken); + } + + /** + * The maximum number of projects to return in the response. + * + * The server can return fewer projects than requested. If unspecified, server picks an + * appropriate default. Note: pagination is not yet supported; the server ignores this field. + */ + public static ProjectListOption pageSize(int pageSize) { + return new ProjectListOption(ResourceManagerRpc.Option.PAGE_SIZE, pageSize); + } + /** * Returns an option to specify the project's fields to be returned by the RPC call. * diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java index ec96e26e0be5..3302b3571efa 100644 --- a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java @@ -25,7 +25,9 @@ public interface ResourceManagerRpc { enum Option { FILTER("filter"), - FIELDS("fields"); + FIELDS("fields"), + PAGE_SIZE("pageSize"), + PAGE_TOKEN("pageToken"); private final String value; From 55c60b1323104eb3678b77d2f11f420343a105bc Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Mon, 30 Nov 2015 13:57:54 -0800 Subject: [PATCH 10/10] fix paging docs --- .../google/gcloud/resourcemanager/ResourceManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 8f27ff182b48..1562fe51dad1 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 @@ -136,17 +136,19 @@ 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 - * continue. Pagination is not yet supported; the server ignores this field. + * continue. */ public static ProjectListOption pageToken(String pageToken) { return new ProjectListOption(ResourceManagerRpc.Option.PAGE_TOKEN, pageToken); } /** - * The maximum number of projects to return in the response. + * The maximum number of projects to return per RPC. * - * The server can return fewer projects than requested. If unspecified, server picks an - * appropriate default. Note: pagination is not yet supported; the server ignores this field. + * 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);