From 4899c2711fc266d41c9f4f7535b6919cb5afc5a4 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Mon, 2 Nov 2015 08:02:55 -0800 Subject: [PATCH 01/42] Create packages for resource manager and outline spi layer. --- gcloud-java-resourcemanager/README.md | 79 ++++++++++++++ gcloud-java-resourcemanager/pom.xml | 44 ++++++++ .../resourcemanager/ResourceManager.java | 31 ++++++ .../ResourceManagerException.java | 65 +++++++++++ .../ResourceManagerFactory.java | 25 +++++ .../ResourceManagerOptions.java | 101 ++++++++++++++++++ .../gcloud/resourcemanager/package-info.java | 23 ++++ .../google/gcloud/spi/ResourceManagerRpc.java | 69 ++++++++++++ .../gcloud/spi/ResourceManagerRpcFactory.java | 27 +++++ 9 files changed, 464 insertions(+) create mode 100644 gcloud-java-resourcemanager/README.md create mode 100644 gcloud-java-resourcemanager/pom.xml create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManager.java create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerException.java create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerFactory.java create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/package-info.java create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java create mode 100644 gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpcFactory.java diff --git a/gcloud-java-resourcemanager/README.md b/gcloud-java-resourcemanager/README.md new file mode 100644 index 000000000000..11c505c14920 --- /dev/null +++ b/gcloud-java-resourcemanager/README.md @@ -0,0 +1,79 @@ +Google Cloud Java Client for Resource Manager +============================================= + +Java idiomatic client for [Google Cloud Resource Manager] (https://cloud.google.com/resource-manager/). + +[![Build Status](https://travis-ci.org/GoogleCloudPlatform/gcloud-java.svg?branch=master)](https://travis-ci.org/GoogleCloudPlatform/gcloud-java) +[![Coverage Status](https://coveralls.io/repos/GoogleCloudPlatform/gcloud-java/badge.svg?branch=master)](https://coveralls.io/r/GoogleCloudPlatform/gcloud-java?branch=master) + + + +- [Homepage] (https://googlecloudplatform.github.io/gcloud-java/) + + + +> Note: This client is a work-in-progress, and may occasionally +> make backwards-incompatible changes. + +Quickstart +---------- +This library is currently under development and will be available soon! + + + + +Authentication +-------------- + +See the [Authentication](https://github.com/GoogleCloudPlatform/gcloud-java#authentication) section in the base directory's README. + +About Google Cloud Resource Manager +----------------------------------- + +Google [Cloud Resource Manager][cloud-resourcemanager] provides a programmatic way to manage your Google Cloud Platform projects. Google Cloud Resource Manager is currently in beta and may occasionally make backwards incompatible changes. + +Be sure to activate the Google Cloud Resource Manager API on the Developer's Console to use Resource Manager from your project. + +See the ``gcloud-java`` API [Resource Manager documentation][resourcemanager-api] to learn how to interact +with the Cloud Resource Manager using this client Library. + + + +Java Versions +------------- + +Java 7 or above is required for using this client. + + + +Versioning +---------- + +This library follows [Semantic Versioning] (http://semver.org/). + +It is currently in major version zero (``0.y.z``), which means that anything +may change at any time and the public API should not be considered +stable. + +Contributing +------------ + +Contributions to this library are always welcome and highly encouraged. + +See [CONTRIBUTING] for more information on how to get started. + +License +------- + +Apache 2.0 - See [LICENSE] for more information. + + +[CONTRIBUTING]:https://github.com/GoogleCloudPlatform/gcloud-java/blob/master/CONTRIBUTING.md +[LICENSE]: https://github.com/GoogleCloudPlatform/gcloud-java/blob/master/LICENSE +[TESTING]: https://github.com/GoogleCloudPlatform/gcloud-java/blob/master/TESTING.md#testing-code-that-uses-resource-manager +[cloud-platform]: https://cloud.google.com/ +[cloud-resourcemanager]: https://cloud.google.com/resource-manager/docs +[resourcemanager-api]: http://googlecloudplatform.github.io/gcloud-java/apidocs/index.html?com/google/gcloud/resourcemanager/package-summary.html + diff --git a/gcloud-java-resourcemanager/pom.xml b/gcloud-java-resourcemanager/pom.xml new file mode 100644 index 000000000000..4a4899231177 --- /dev/null +++ b/gcloud-java-resourcemanager/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + com.google.gcloud + gcloud-java-resourcemanager + jar + GCloud Java resource manager + + Java idiomatic client for Google Cloud Resource Manager. + + + com.google.gcloud + gcloud-java-pom + 0.0.11-SNAPSHOT + + + gcloud-java-resourcemanager + + + + ${project.groupId} + gcloud-java-core + ${project.version} + + + com.google.apis + google-api-services-cloudresourcemanager + v1beta1-rev6-1.19.0 + compile + + + junit + junit + 4.12 + test + + + org.easymock + easymock + 3.3 + test + + + 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 new file mode 100644 index 000000000000..8a9966faa653 --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManager.java @@ -0,0 +1,31 @@ +/* + * 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 com.google.gcloud.Service; + +/** + * An interface for Google Cloud Resource Manager. + * + * @see Google Cloud Resource Manager + */ +public interface ResourceManager extends Service { + + public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; + + // TODO(ajaykannan): Fix me! Add in missing methods. +} 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 new file mode 100644 index 000000000000..e136db8fd339 --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerException.java @@ -0,0 +1,65 @@ +/* + * 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 com.google.gcloud.RetryHelper.RetryHelperException; +import com.google.gcloud.RetryHelper.RetryInterruptedException; + +/** + * Resource Manager service exception. + * + * @see Google Cloud + * Resource Manager error codes + */ +public class ResourceManagerException extends RuntimeException { + + 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; + } + + /** + * Translate RetryHelperException to the ResourceManagerException that caused the error. This + * method will always throw an exception. + * + * @throws ResourceManagerException when {@code ex} was caused by a {@code + * ResourceManagerException} + * @throws RetryInterruptedException when {@code ex} is a {@code RetryInterruptedException} + */ + static ResourceManagerException translateAndThrow(RetryHelperException ex) { + throw new ResourceManagerException(UNKNOWN_CODE, ex.getMessage(), false); + // TODO(ajaykannan): Fix me! + } +} diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerFactory.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerFactory.java new file mode 100644 index 000000000000..256fc321e4e1 --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerFactory.java @@ -0,0 +1,25 @@ +/* + * 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 com.google.gcloud.ServiceFactory; + +/** + * An interface for ResourceManager factories. + */ +public interface ResourceManagerFactory + extends ServiceFactory {} 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 new file mode 100644 index 000000000000..e43609be95c1 --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/ResourceManagerOptions.java @@ -0,0 +1,101 @@ +/* + * 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 com.google.common.collect.ImmutableSet; +import com.google.gcloud.ServiceOptions; +import com.google.gcloud.spi.ResourceManagerRpc; +import com.google.gcloud.spi.ResourceManagerRpcFactory; + +import java.util.Set; + +public class ResourceManagerOptions + extends ServiceOptions { + + private static final long serialVersionUID = 538303101192527452L; + private static final String GCRM_SCOPE = "https://www.googleapis.com/auth/cloud-platform"; + private static final Set SCOPES = ImmutableSet.of(GCRM_SCOPE); + + public static class DefaultResourceManagerFactory implements ResourceManagerFactory { + private static final ResourceManagerFactory INSTANCE = new DefaultResourceManagerFactory(); + + @Override + public ResourceManager create(ResourceManagerOptions options) { + // return new ResourceManagerImpl(options); + return null; // TODO(ajaykannan): Fix me! + } + } + + public static class DefaultResourceManagerRpcFactory implements ResourceManagerRpcFactory { + private static final ResourceManagerRpcFactory INSTANCE = + new DefaultResourceManagerRpcFactory(); + + @Override + public ResourceManagerRpc create(ResourceManagerOptions options) { + // return new DefaultResourceManagerRpc(options); + return null; // TODO(ajaykannan): Fix me! + } + } + + public static class Builder extends ServiceOptions.Builder { + + private Builder() {} + + private Builder(ResourceManagerOptions options) { + super(options); + } + + @Override + public ResourceManagerOptions build() { + return new ResourceManagerOptions(this); + } + } + + private ResourceManagerOptions(Builder builder) { + super(ResourceManagerFactory.class, ResourceManagerRpcFactory.class, builder); + } + + @Override + protected ResourceManagerFactory defaultServiceFactory() { + return DefaultResourceManagerFactory.INSTANCE; + } + + @Override + protected ResourceManagerRpcFactory defaultRpcFactory() { + return DefaultResourceManagerRpcFactory.INSTANCE; + } + + @Override + protected Set scopes() { + return SCOPES; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof ResourceManagerOptions && baseEquals((ResourceManagerOptions) obj); + } + + @Override + public Builder toBuilder() { + return new Builder(this); + } + + public static Builder builder() { + return new Builder(); + } +} diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/package-info.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/package-info.java new file mode 100644 index 000000000000..3beaa0967443 --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * A client to Google Cloud Resource Manager. + * //TODO(ajaykannan): add code example + * @see Google Cloud Resource Manager + */ + +package com.google.gcloud.resourcemanager; 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 new file mode 100644 index 000000000000..492b18a96c8a --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpc.java @@ -0,0 +1,69 @@ +/* + * 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.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; + +public interface ResourceManagerRpc { + + class Tuple { + private final X x; + private final Y y; + + private Tuple(X x, Y y) { + this.x = x; + this.y = y; + } + + public static Tuple of(X x, Y y) { + return new Tuple<>(x, y); + } + + public X x() { + return x; + } + + public Y y() { + return y; + } + } + + Project create(Project project) throws ResourceManagerException; + + void delete(String projectId) throws ResourceManagerException; + + Project get(String projectId) throws ResourceManagerException; + + Tuple> list() throws ResourceManagerException; + + Tuple> list(String filter) throws ResourceManagerException; + + void undelete(String projectId) throws ResourceManagerException; + + Project update(String projectId, Project project) throws ResourceManagerException; + + Policy getIamPolicy(String projectId) throws ResourceManagerException; + + void setIamPolicy(String projectId, Policy policy) throws ResourceManagerException; + + List testIamPermissions(String projectId, List permissions) + throws ResourceManagerException; +} diff --git a/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpcFactory.java b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpcFactory.java new file mode 100644 index 000000000000..c2c607c0c205 --- /dev/null +++ b/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/spi/ResourceManagerRpcFactory.java @@ -0,0 +1,27 @@ +/* + * 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.spi; + +import com.google.gcloud.resourcemanager.ResourceManagerOptions; + +/** + * An interface for Resource Manager RPC factory. + * Implementation will be loaded via {@link java.util.ServiceLoader}. + */ +public interface ResourceManagerRpcFactory + extends ServiceRpcFactory { +} From 3687cb16aec0347bad882da69bc961740b118ea3 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Mon, 2 Nov 2015 17:08:59 -0800 Subject: [PATCH 02/42] Fixes to the ResourceManagerRpc layer, and also add resource manager to pom files spi api fixes --- .../google/gcloud/spi/ResourceManagerRpc.java | 34 ++++++++++++++++--- gcloud-java/pom.xml | 5 +++ pom.xml | 1 + 3 files changed, 36 insertions(+), 4 deletions(-) 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 492b18a96c8a..527e448521ed 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 @@ -46,15 +46,41 @@ public Y y() { } } + public class ListOptions { + private List filters; + private String pageToken; + + private static final ListOptions DEFAULT_INSTANCE = new ListOptions(null, null); + + ListOptions(List filters, String pageToken) { + this.filters = filters; + this.pageToken = pageToken; + } + + public static ListOptions getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + public static ListOptions createListOption(List filters, String pageToken) { + return new ListOptions(filters, pageToken); + } + + public String pageToken() { + return pageToken; + } + + public List filters() { + return filters; + } + } + Project create(Project project) throws ResourceManagerException; void delete(String projectId) throws ResourceManagerException; Project get(String projectId) throws ResourceManagerException; - Tuple> list() throws ResourceManagerException; - - Tuple> list(String filter) throws ResourceManagerException; + Tuple> list(ListOptions listOptions) throws ResourceManagerException; void undelete(String projectId) throws ResourceManagerException; @@ -64,6 +90,6 @@ public Y y() { void setIamPolicy(String projectId, Policy policy) throws ResourceManagerException; - List testIamPermissions(String projectId, List permissions) + boolean hasPermissions(String projectId, List permissions) throws ResourceManagerException; } diff --git a/gcloud-java/pom.xml b/gcloud-java/pom.xml index 7d8e251b54fb..655ef8f70e62 100644 --- a/gcloud-java/pom.xml +++ b/gcloud-java/pom.xml @@ -24,6 +24,11 @@ gcloud-java-datastore ${project.version} + + ${project.groupId} + gcloud-java-resourcemanager + ${project.version} + ${project.groupId} gcloud-java-storage diff --git a/pom.xml b/pom.xml index 5b11a09fb382..7d1751ee179d 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,7 @@ gcloud-java-core gcloud-java-datastore + gcloud-java-resourcemanager gcloud-java-storage gcloud-java gcloud-java-examples From 3892eedce3ca670eb5a8f2e83e914264c0406b2e Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 3 Nov 2015 08:36:02 -0800 Subject: [PATCH 03/42] minor changes to ResourceManagerRpc --- .../google/gcloud/spi/ResourceManagerRpc.java | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) 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 527e448521ed..285d4e887e14 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,14 +16,27 @@ 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.gcloud.resourcemanager.ResourceManagerException; +import java.util.Collections; import java.util.List; public interface ResourceManagerRpc { + public enum Permission { + CREATE, + DELETE, + GET, + LIST, + UPDATE, + GET_IAM_POLICY, + SET_IAM_POLICY; + } + class Tuple { private final X x; private final Y y; @@ -49,20 +62,24 @@ public Y y() { public class ListOptions { private List filters; private String pageToken; + private int pageSize; - private static final ListOptions DEFAULT_INSTANCE = new ListOptions(null, null); + private static final ListOptions DEFAULT_INSTANCE = + new ListOptions(Collections.emptyList(), null, -1); - ListOptions(List filters, String pageToken) { - this.filters = filters; + ListOptions(List filters, String pageToken, int pageSize) { + this.filters = checkNotNull(filters); this.pageToken = pageToken; + this.pageSize = pageSize; } public static ListOptions getDefaultInstance() { return DEFAULT_INSTANCE; } - public static ListOptions createListOption(List filters, String pageToken) { - return new ListOptions(filters, pageToken); + public static ListOptions createListOption( + List filters, String pageToken, int pageSize) { + return new ListOptions(filters, pageToken, pageSize); } public String pageToken() { @@ -72,6 +89,10 @@ public String pageToken() { public List filters() { return filters; } + + public int pageSize() { + return pageSize; + } } Project create(Project project) throws ResourceManagerException; @@ -90,6 +111,6 @@ public List filters() { void setIamPolicy(String projectId, Policy policy) throws ResourceManagerException; - boolean hasPermissions(String projectId, List permissions) + List hasPermissions(String projectId, List permissions) throws ResourceManagerException; } From a60f7d16050a4a639af80697e1d5c6c6d2dc4601 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 3 Nov 2015 09:32:36 -0800 Subject: [PATCH 04/42] Style updates to ResourceManagerRpc --- .../java/com/google/gcloud/spi/ResourceManagerRpc.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 285d4e887e14..de412b87278e 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 @@ -20,6 +20,7 @@ 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; @@ -34,7 +35,7 @@ public enum Permission { LIST, UPDATE, GET_IAM_POLICY, - SET_IAM_POLICY; + SET_IAM_POLICY } class Tuple { @@ -68,7 +69,7 @@ public class ListOptions { new ListOptions(Collections.emptyList(), null, -1); ListOptions(List filters, String pageToken, int pageSize) { - this.filters = checkNotNull(filters); + this.filters = checkNotNull(ImmutableList.copyOf(filters)); this.pageToken = pageToken; this.pageSize = pageSize; } @@ -105,7 +106,7 @@ public int pageSize() { void undelete(String projectId) throws ResourceManagerException; - Project update(String projectId, Project project) throws ResourceManagerException; + Project update(Project project) throws ResourceManagerException; Policy getIamPolicy(String projectId) throws ResourceManagerException; @@ -113,4 +114,6 @@ public int pageSize() { List hasPermissions(String projectId, List permissions) throws ResourceManagerException; + + // TODO(ajaykannan): implement "Organization" functionality when available } From c69af1acb3ee4cb24876f1444540c5b543e40c0c Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 3 Nov 2015 10:20:18 -0800 Subject: [PATCH 05/42] add return values to delete, undelete, and setIamPolicy --- .../google/gcloud/spi/ResourceManagerRpc.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) 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 de412b87278e..7511114a4500 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 @@ -38,6 +38,22 @@ public enum Permission { SET_IAM_POLICY } + public enum DeleteResult { + SUCCESS, + ALREADY_DELETED + } + + public enum UndeleteResult { + SUCCESS, + DELETE_IN_PROGRESS, + GONE + } + + public enum SetIamPolicyResult { + SUCCESS, + ETAG_NOT_MATCH + } + class Tuple { private final X x; private final Y y; @@ -98,19 +114,19 @@ public int pageSize() { Project create(Project project) throws ResourceManagerException; - void delete(String projectId) throws ResourceManagerException; + DeleteResult delete(String projectId) throws ResourceManagerException; Project get(String projectId) throws ResourceManagerException; Tuple> list(ListOptions listOptions) throws ResourceManagerException; - void undelete(String projectId) throws ResourceManagerException; + UndeleteResult undelete(String projectId) throws ResourceManagerException; Project update(Project project) throws ResourceManagerException; Policy getIamPolicy(String projectId) throws ResourceManagerException; - void setIamPolicy(String projectId, Policy policy) throws ResourceManagerException; + SetIamPolicyResult setIamPolicy(String projectId, Policy policy) throws ResourceManagerException; List hasPermissions(String projectId, List permissions) throws ResourceManagerException; From 249fae8f180a61e7a4ef619169c62d45a90b8076 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Wed, 4 Nov 2015 13:00:26 -0800 Subject: [PATCH 06/42] Remove spi result enums, change 'update/set' terminology to 'replace' --- .../google/gcloud/spi/ResourceManagerRpc.java | 30 +++++-------------- 1 file changed, 7 insertions(+), 23 deletions(-) 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 7511114a4500..1223627bbfcb 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 @@ -33,25 +33,9 @@ public enum Permission { DELETE, GET, LIST, - UPDATE, + REPLACE, GET_IAM_POLICY, - SET_IAM_POLICY - } - - public enum DeleteResult { - SUCCESS, - ALREADY_DELETED - } - - public enum UndeleteResult { - SUCCESS, - DELETE_IN_PROGRESS, - GONE - } - - public enum SetIamPolicyResult { - SUCCESS, - ETAG_NOT_MATCH + REPLACE_IAM_POLICY } class Tuple { @@ -114,22 +98,22 @@ public int pageSize() { Project create(Project project) throws ResourceManagerException; - DeleteResult delete(String projectId) throws ResourceManagerException; + void delete(String projectId) throws ResourceManagerException; Project get(String projectId) throws ResourceManagerException; Tuple> list(ListOptions listOptions) throws ResourceManagerException; - UndeleteResult undelete(String projectId) throws ResourceManagerException; + void undelete(String projectId) throws ResourceManagerException; - Project update(Project project) throws ResourceManagerException; + Project replace(Project project) throws ResourceManagerException; Policy getIamPolicy(String projectId) throws ResourceManagerException; - SetIamPolicyResult setIamPolicy(String projectId, Policy policy) throws ResourceManagerException; + boolean replaceIamPolicy(String projectId, Policy policy) throws ResourceManagerException; List hasPermissions(String projectId, List permissions) throws ResourceManagerException; - // TODO(ajaykannan): implement "Organization" functionality when available + // TODO(ajaykannan): implement "Organization" functionality when available (issue #319) } From 65a6240d9dda87434786e016e3cc2cd4d5d26f53 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Thu, 12 Nov 2015 14:11:56 -0800 Subject: [PATCH 07/42] 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 9d6fbff4ea8172f01a64a51dc78f58131e5120f0 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Mon, 16 Nov 2015 17:18:12 -0800 Subject: [PATCH 08/42] 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 e625c20f67ee7b096f944ed744d95ffba6ad3f6d Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Fri, 20 Nov 2015 10:41:07 -0800 Subject: [PATCH 09/42] 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. + * + *