From 957ee8f8b51afecb6afc790aa8234d476bac7bed Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Wed, 29 Aug 2018 16:41:42 -0400 Subject: [PATCH 1/8] WIP: Bigtable: CRUD for AppProfiles --- .../admin/v2/BigtableInstanceAdminClient.java | 206 ++++++++++++++++++ .../bigtable/admin/v2/models/AppProfile.java | 170 +++++++++++++++ .../v2/models/CreateAppProfileRequest.java | 73 +++++++ .../v2/models/UpdateAppProfileRequest.java | 121 ++++++++++ 4 files changed, 570 insertions(+) create mode 100644 google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/AppProfile.java create mode 100644 google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequest.java create mode 100644 google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java index b2a2f741126d..230d73d7e1db 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java @@ -15,9 +15,29 @@ */ package com.google.cloud.bigtable.admin.v2; +import com.google.api.core.ApiAsyncFunction; +import com.google.api.core.ApiFunction; +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.bigtable.admin.v2.AppProfileName; +import com.google.bigtable.admin.v2.DeleteAppProfileRequest; +import com.google.bigtable.admin.v2.GetAppProfileRequest; +import com.google.bigtable.admin.v2.InstanceName; +import com.google.bigtable.admin.v2.ListAppProfilesRequest; import com.google.bigtable.admin.v2.ProjectName; +import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPage; +import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPagedResponse; +import com.google.cloud.bigtable.admin.v2.models.AppProfile; +import com.google.cloud.bigtable.admin.v2.models.CreateAppProfileRequest; +import com.google.cloud.bigtable.admin.v2.models.UpdateAppProfileRequest; import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.protobuf.Empty; import java.io.IOException; +import java.util.List; import javax.annotation.Nonnull; /** @@ -105,4 +125,190 @@ public ProjectName getProjectName() { public void close() { stub.close(); } + + @SuppressWarnings("WeakerAccess") + public AppProfile createAppProfile(CreateAppProfileRequest request) { + return awaitFuture(createAppProfileAsync(request)); + } + + @SuppressWarnings("WeakerAccess") + public ApiFuture createAppProfileAsync(CreateAppProfileRequest request) { + return ApiFutures.transform( + stub.createAppProfileCallable().futureCall(request.toProto(projectName)), + new ApiFunction() { + @Override + public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { + return AppProfile.fromProto(proto); + } + }, + MoreExecutors.directExecutor() + ); + } + + @SuppressWarnings("WeakerAccess") + public AppProfile getAppProfile(String instanceId, String appProfileId) { + return awaitFuture(getAppProfileAsync(instanceId, appProfileId)); + } + + @SuppressWarnings("WeakerAccess") + public ApiFuture getAppProfileAsync(String instanceId, String appProfileId) { + AppProfileName name = AppProfileName.of(projectName.getProject(), instanceId, appProfileId); + + GetAppProfileRequest request = GetAppProfileRequest.newBuilder() + .setName(name.toString()) + .build(); + + return ApiFutures.transform( + stub.getAppProfileCallable().futureCall(request), + new ApiFunction() { + @Override + public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { + return AppProfile.fromProto(proto); + } + }, + MoreExecutors.directExecutor() + ); + } + + @SuppressWarnings("WeakerAccess") + public List listAppProfiles(String instanceId) { + return awaitFuture(listAppProfilesAsync(instanceId)); + } + + @SuppressWarnings("WeakerAccess") + public ApiFuture> listAppProfilesAsync(String instanceId) { + InstanceName instanceName = InstanceName.of(projectName.getProject(), instanceId); + + ListAppProfilesRequest request = ListAppProfilesRequest.newBuilder() + .setParent(instanceName.toString()) + .build(); + + // TODO(igorbernstein2): try to upstream pagination spooling or figure out a way to expose the + // paginated responses while maintaining the wrapper facade. + + // Fetch the first page. + ApiFuture firstPageFuture = ApiFutures.transform( + stub.listAppProfilesPagedCallable().futureCall(request), + new ApiFunction() { + @Override + public ListAppProfilesPage apply(ListAppProfilesPagedResponse response) { + return response.getPage(); + } + }, + MoreExecutors.directExecutor() + ); + + // Fetch the rest of the pages by chaining the futures. + ApiFuture> allProtos = ApiFutures + .transformAsync( + firstPageFuture, + new ApiAsyncFunction>() { + List responseAccumulator = Lists + .newArrayList(); + + @Override + public ApiFuture> apply( + ListAppProfilesPage page) { + // Add all entries from the page + responseAccumulator.addAll(Lists.newArrayList(page.getValues())); + + // If this is the last page, just return the accumulated responses. + if (!page.hasNextPage()) { + return ApiFutures.immediateFuture(responseAccumulator); + } + + // Otherwise fetch the next page. + return ApiFutures.transformAsync( + page.getNextPageAsync(), + this, + MoreExecutors.directExecutor() + ); + } + }, + MoreExecutors.directExecutor() + ); + + // Wrap all of the accumulated protos. + return ApiFutures.transform(allProtos, + new ApiFunction, List>() { + @Override + public List apply(List input) { + List results = Lists.newArrayListWithCapacity(input.size()); + for (com.google.bigtable.admin.v2.AppProfile appProfile : input) { + results.add(AppProfile.fromProto(appProfile)); + } + return results; + } + }, + MoreExecutors.directExecutor() + ); + } + + @SuppressWarnings("WeakerAccess") + public AppProfile updateAppProfile(UpdateAppProfileRequest request) { + return awaitFuture(updateAppProfileAsync(request)); + } + + @SuppressWarnings("WeakerAccess") + public ApiFuture updateAppProfileAsync(UpdateAppProfileRequest request) { + return ApiFutures.transform( + stub.updateAppProfileOperationCallable().futureCall(request.toProto(projectName)), + new ApiFunction() { + @Override + public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { + return AppProfile.fromProto(proto); + } + }, + MoreExecutors.directExecutor() + ); + } + + @SuppressWarnings("WeakerAccess") + public void deleteAppProfile(String instanceId, String appProfileId) { + awaitFuture(deleteAppProfileAsync(instanceId, appProfileId)); + } + + @SuppressWarnings("WeakerAccess") + public ApiFuture deleteAppProfileAsync(String instanceId, String appProfileId) { + AppProfileName name = AppProfileName.of(projectName.getProject(), instanceId, appProfileId); + DeleteAppProfileRequest request = DeleteAppProfileRequest.newBuilder() + .setName(name.toString()) + .build(); + + return ApiFutures.transform( + stub.deleteAppProfileCallable().futureCall(request), + new ApiFunction() { + @Override + public Void apply(Empty input) { + return null; + } + }, + MoreExecutors.directExecutor() + ); + } + + /** + * Awaits the result of a future, taking care to propagate errors while maintaining the call site + * in a suppressed exception. This allows semantic errors to be caught across threads, while + * preserving the call site in the error. The caller's stacktrace will be made available as a + * suppressed exception. + */ + // TODO(igorbernstein2): try to move this into gax + private T awaitFuture(ApiFuture future) { + RuntimeException error; + try { + return Futures.getUnchecked(future); + } catch (UncheckedExecutionException e) { + if (e.getCause() instanceof RuntimeException) { + error = (RuntimeException) e.getCause(); + } else { + error = e; + } + } catch (RuntimeException e) { + error = e; + } + // Add the caller's stack as a suppressed exception + error.addSuppressed(new RuntimeException("Encountered error while awaiting future")); + throw error; + } } diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/AppProfile.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/AppProfile.java new file mode 100644 index 000000000000..9707b2b556b3 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/AppProfile.java @@ -0,0 +1,170 @@ +/* + * Copyright 2018 Google LLC + * + * 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 + * + * https://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.cloud.bigtable.admin.v2.models; + +import com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny; +import com.google.bigtable.admin.v2.AppProfileName; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Verify; +import com.google.common.base.VerifyException; + +public class AppProfile { + private final com.google.bigtable.admin.v2.AppProfile proto; + + public static AppProfile fromProto(com.google.bigtable.admin.v2.AppProfile proto) { + return new AppProfile(proto); + } + + private AppProfile(com.google.bigtable.admin.v2.AppProfile proto) { + this.proto = proto; + Preconditions.checkArgument(proto.hasSingleClusterRouting() || proto.hasMultiClusterRoutingUseAny(), "AppProfile must have a routing policy"); + } + + public RoutingPolicy getPolicy() { + if (proto.hasMultiClusterRoutingUseAny()) { + return MultiClusterRoutingPolicy.of(); + } else if (proto.hasSingleClusterRouting()) { + return new SingleClusterRoutingPolicy(proto.getSingleClusterRouting()); + } else { + // Should never happen because the constructor verifies that one must exist. + throw new VerifyException(); + } + } + + public String getId() { + AppProfileName fullName = Verify.verifyNotNull( + AppProfileName.parse(proto.getName()), + "Name can never be null"); + + //noinspection ConstantConditions + return fullName.getAppProfile(); + } + + public String getInstanceId() { + AppProfileName fullName = Verify.verifyNotNull( + AppProfileName.parse(proto.getName()), + "Name can never be null"); + + //noinspection ConstantConditions + return fullName.getInstance(); + } + + public String getDescription() { + return proto.getDescription(); + } + + public String getEtag() { + return proto.getEtag(); + } + + com.google.bigtable.admin.v2.AppProfile getProto() { + return proto; + } + + public interface RoutingPolicy { + } + + public static class MultiClusterRoutingPolicy implements RoutingPolicy { + private static final MultiClusterRoutingUseAny proto = MultiClusterRoutingUseAny.getDefaultInstance(); + + public static MultiClusterRoutingPolicy of() { + return new MultiClusterRoutingPolicy(); + } + + private MultiClusterRoutingPolicy() { + } + + MultiClusterRoutingUseAny toProto() { + return proto; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return Objects.hashCode(proto); + } + } + + public static class SingleClusterRoutingPolicy implements RoutingPolicy { + private final com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting proto; + + public static SingleClusterRoutingPolicy fromProto(com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting proto) { + return new SingleClusterRoutingPolicy(proto); + } + + public static SingleClusterRoutingPolicy of(String clusterId) { + return fromProto( + com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting.newBuilder() + .setClusterId(clusterId) + .build() + ); + } + + public static SingleClusterRoutingPolicy of(String clusterId, boolean allowTransactionWrites) { + return fromProto( + com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting.newBuilder() + .setClusterId(clusterId) + .setAllowTransactionalWrites(allowTransactionWrites) + .build() + ); + } + + private SingleClusterRoutingPolicy(com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting proto) { + this.proto = proto; + } + + public String getClusterId() { + return proto.getClusterId(); + } + + public boolean getAllowTransactionalWrites() { + return proto.getAllowTransactionalWrites(); + } + + com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting toProto() { + return proto; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SingleClusterRoutingPolicy that = (SingleClusterRoutingPolicy) o; + return Objects.equal(proto, that.proto); + } + + @Override + public int hashCode() { + return Objects.hashCode(proto); + } + } +} diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequest.java new file mode 100644 index 000000000000..71457af42399 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2018 Google LLC + * + * 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 + * + * https://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.cloud.bigtable.admin.v2.models; + +import com.google.api.core.InternalApi; +import com.google.bigtable.admin.v2.InstanceName; +import com.google.bigtable.admin.v2.ProjectName; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.MultiClusterRoutingPolicy; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.RoutingPolicy; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.SingleClusterRoutingPolicy; +import com.google.common.base.Preconditions; +import javax.annotation.Nonnull; + +public class CreateAppProfileRequest { + private final String instanceId; + private final com.google.bigtable.admin.v2.CreateAppProfileRequest.Builder proto; + + public CreateAppProfileRequest of(String instanceId, String appProfileId) { + return new CreateAppProfileRequest(instanceId, appProfileId); + } + + private CreateAppProfileRequest(String instanceId, String appProfileId) { + this.instanceId = instanceId; + this.proto = com.google.bigtable.admin.v2.CreateAppProfileRequest.newBuilder(); + + proto.setAppProfileId(appProfileId); + proto.getAppProfileBuilder().setDescription(appProfileId); + } + + public CreateAppProfileRequest setIgnoreWarnings(boolean value) { + proto.setIgnoreWarnings(value); + return this; + } + + public CreateAppProfileRequest setDescription(@Nonnull String description) { + proto.getAppProfileBuilder().setDescription(description); + return this; + } + + public CreateAppProfileRequest setRoutingPolicy(RoutingPolicy routingPolicy) { + Preconditions.checkNotNull(routingPolicy); + + if (routingPolicy instanceof MultiClusterRoutingPolicy) { + proto.getAppProfileBuilder().setMultiClusterRoutingUseAny(((MultiClusterRoutingPolicy)routingPolicy).toProto()); + } else if (routingPolicy instanceof SingleClusterRoutingPolicy) { + proto.getAppProfileBuilder().setSingleClusterRouting(((SingleClusterRoutingPolicy)routingPolicy).toProto()); + } else { + throw new IllegalArgumentException("Unknown policy type: " + routingPolicy); + } + + return this; + } + + @InternalApi + public com.google.bigtable.admin.v2.CreateAppProfileRequest toProto(ProjectName projectName) { + InstanceName name = InstanceName.of(projectName.getProject(), instanceId); + + return proto.setParent(name.toString()).build(); + } +} diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java new file mode 100644 index 000000000000..e4669a28df1b --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java @@ -0,0 +1,121 @@ +/* + * Copyright 2018 Google LLC + * + * 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 + * + * https://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.cloud.bigtable.admin.v2.models; + +import com.google.api.core.InternalApi; +import com.google.bigtable.admin.v2.AppProfileName; +import com.google.bigtable.admin.v2.ProjectName; +import com.google.bigtable.admin.v2.UpdateAppProfileRequest.Builder; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.MultiClusterRoutingPolicy; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.RoutingPolicy; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.SingleClusterRoutingPolicy; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Verify; +import com.google.protobuf.FieldMask; +import com.google.protobuf.util.FieldMaskUtil; +import javax.annotation.Nonnull; + +public class UpdateAppProfileRequest { + private final String instanceId; + private final String appProfileId; + + private final com.google.bigtable.admin.v2.UpdateAppProfileRequest.Builder proto; + + public static UpdateAppProfileRequest of(@Nonnull String instanceId, @Nonnull String appProfileId) { + return new UpdateAppProfileRequest(instanceId, appProfileId, + com.google.bigtable.admin.v2.UpdateAppProfileRequest.newBuilder()); + } + + public static UpdateAppProfileRequest of(@Nonnull AppProfile appProfile) { + return new UpdateAppProfileRequest(appProfile.getInstanceId(), appProfile.getId(), + com.google.bigtable.admin.v2.UpdateAppProfileRequest.newBuilder() + .setAppProfile(appProfile.getProto()) + ); + } + + private UpdateAppProfileRequest(@Nonnull String instanceId, @Nonnull String appProfileId, @Nonnull Builder builder) { + Preconditions.checkNotNull(instanceId, "instanceId must be set"); + Preconditions.checkNotNull(appProfileId, "appProfileId must be set"); + Verify.verifyNotNull(builder); + + this.instanceId = instanceId; + this.appProfileId = appProfileId; + this.proto = builder; + } + + public UpdateAppProfileRequest setIgnoreWarnings(boolean value) { + proto.setIgnoreWarnings(value); + return this; + } + + public UpdateAppProfileRequest setDescription(@Nonnull String description) { + Preconditions.checkNotNull(description); + + proto.getAppProfileBuilder().setDescription(description); + updateFieldMask(com.google.bigtable.admin.v2.AppProfile.DESCRIPTION_FIELD_NUMBER); + return this; + } + + public UpdateAppProfileRequest setRoutingPolicy(RoutingPolicy routingPolicy) { + Preconditions.checkNotNull(routingPolicy); + + if (routingPolicy instanceof MultiClusterRoutingPolicy) { + proto.getAppProfileBuilder().setMultiClusterRoutingUseAny(((MultiClusterRoutingPolicy)routingPolicy).toProto()); + updateFieldMask(com.google.bigtable.admin.v2.AppProfile.MULTI_CLUSTER_ROUTING_USE_ANY_FIELD_NUMBER); + } else if (routingPolicy instanceof SingleClusterRoutingPolicy) { + proto.getAppProfileBuilder().setSingleClusterRouting(((SingleClusterRoutingPolicy)routingPolicy).toProto()); + updateFieldMask(com.google.bigtable.admin.v2.AppProfile.SINGLE_CLUSTER_ROUTING_FIELD_NUMBER); + } else { + throw new IllegalArgumentException("Unknown policy type: " + routingPolicy); + } + + return this; + } + + private void updateFieldMask(int fieldNumber) { + FieldMask newMask = FieldMaskUtil.fromFieldNumbers(com.google.bigtable.admin.v2.AppProfile.class, fieldNumber); + proto.setUpdateMask(FieldMaskUtil.union(proto.getUpdateMask(), newMask)); + } + + @InternalApi + public com.google.bigtable.admin.v2.UpdateAppProfileRequest toProto(ProjectName projectName) { + AppProfileName name = AppProfileName.of(projectName.getProject(), instanceId, appProfileId); + + proto.getAppProfileBuilder().setName(name.toString()); + + return proto.build(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UpdateAppProfileRequest that = (UpdateAppProfileRequest) o; + return Objects.equal(instanceId, that.instanceId) && + Objects.equal(appProfileId, that.appProfileId) && + Objects.equal(proto, that.proto); + } + + @Override + public int hashCode() { + return Objects.hashCode(instanceId, appProfileId, proto); + } +} From cd1c8e403fc2b66cf8f1b124992490c0ddb13a1c Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 30 Aug 2018 17:22:33 -0400 Subject: [PATCH 2/8] docs & tests --- .../google-cloud-bigtable-admin/pom.xml | 6 + .../admin/v2/BigtableInstanceAdminClient.java | 128 +++++++++ .../bigtable/admin/v2/models/AppProfile.java | 190 ++++++++++--- .../v2/models/CreateAppProfileRequest.java | 33 ++- .../v2/models/UpdateAppProfileRequest.java | 68 +++-- .../v2/BigtableInstanceAdminClientTest.java | 252 +++++++++++++++++- .../admin/v2/models/AppProfileTest.java | 84 ++++++ .../models/CreateAppProfileRequestTest.java | 64 +++++ .../models/UpdateAppProfileRequestTest.java | 69 +++++ 9 files changed, 829 insertions(+), 65 deletions(-) create mode 100644 google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/AppProfileTest.java create mode 100644 google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java create mode 100644 google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java diff --git a/google-cloud-clients/google-cloud-bigtable-admin/pom.xml b/google-cloud-clients/google-cloud-bigtable-admin/pom.xml index 5f02a6eeb8a8..5fa7506fa16e 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/pom.xml +++ b/google-cloud-clients/google-cloud-bigtable-admin/pom.xml @@ -61,6 +61,12 @@ test-jar test + + com.google.api + gax + testlib + test + junit junit diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java index 230d73d7e1db..57f7fb14d3de 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java @@ -19,6 +19,7 @@ import com.google.api.core.ApiFunction; import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; +import com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting; import com.google.bigtable.admin.v2.AppProfileName; import com.google.bigtable.admin.v2.DeleteAppProfileRequest; import com.google.bigtable.admin.v2.GetAppProfileRequest; @@ -28,6 +29,7 @@ import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPage; import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPagedResponse; import com.google.cloud.bigtable.admin.v2.models.AppProfile; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.SingleClusterRoutingPolicy; import com.google.cloud.bigtable.admin.v2.models.CreateAppProfileRequest; import com.google.cloud.bigtable.admin.v2.models.UpdateAppProfileRequest; import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub; @@ -126,11 +128,37 @@ public void close() { stub.close(); } + /** + * Creates a new app profile. + * + *

Sample code: + * + *

{@code
+   * AppProfile appProfile = client.createAppProfile(
+   *   CreateAppProfileRequest.of("my-instance", "my-new-app-profile")
+   *     .setRoutingPolicy(SingleClusterRoutingPolicy.of("my-cluster"))
+   * );
+   * }
+ */ @SuppressWarnings("WeakerAccess") public AppProfile createAppProfile(CreateAppProfileRequest request) { return awaitFuture(createAppProfileAsync(request)); } + /** + * Asynchronously creates a new app profile. + * + *

Sample code: + * + *

{@code
+   * ApiFuture appProfileFuture = client.createAppProfileAsync(
+   *   CreateAppProfileRequest.of("my-instance", "my-new-app-profile")
+   *     .setRoutingPolicy(SingleClusterRoutingPolicy.of("my-cluster"))
+   * );
+   *
+   * AppProfile appProfile = appProfileFuture.get();
+   * }
+ */ @SuppressWarnings("WeakerAccess") public ApiFuture createAppProfileAsync(CreateAppProfileRequest request) { return ApiFutures.transform( @@ -145,11 +173,31 @@ public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { ); } + /** + * Get the app profile by id. + * + *

Sample code: + * + *

{@code
+   * AppProfile appProfile = client.getAppProfile("my-instance", "my-app-profile");
+   * }
+ */ @SuppressWarnings("WeakerAccess") public AppProfile getAppProfile(String instanceId, String appProfileId) { return awaitFuture(getAppProfileAsync(instanceId, appProfileId)); } + /** + * Asynchronously get the app profile by id. + * + *

Sample code: + * + *

{@code
+   * ApiFuture appProfileFuture = client.getAppProfileAsync("my-instance", "my-app-profile");
+   *
+   * AppProfile appProfile = appProfileFuture.get();
+   * }
+ */ @SuppressWarnings("WeakerAccess") public ApiFuture getAppProfileAsync(String instanceId, String appProfileId) { AppProfileName name = AppProfileName.of(projectName.getProject(), instanceId, appProfileId); @@ -170,11 +218,31 @@ public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { ); } + /** + * Lists all app profiles the specified instance. + * + *

Sample code: + * + *

{@code
+   * List appProfiles = client.listAppProfiles("my-instance");
+   * }
+ */ @SuppressWarnings("WeakerAccess") public List listAppProfiles(String instanceId) { return awaitFuture(listAppProfilesAsync(instanceId)); } + /** + * Lists all app profiles the specified instance. + * + *

Sample code: + * + *

{@code
+   * ApiFuture> appProfilesFuture = client.listAppProfilesAsync("my-instance");
+   *
+   * List appProfiles = appProfileFuture.get();
+   * }
+ */ @SuppressWarnings("WeakerAccess") public ApiFuture> listAppProfilesAsync(String instanceId) { InstanceName instanceName = InstanceName.of(projectName.getProject(), instanceId); @@ -244,11 +312,51 @@ public List apply(List inpu ); } + /** + * Updates an existing app profile. + * + *

Sample code: + * + *

{@code
+   * AppProfile existingAppProfile = client.getAppProfile("my-instance", "my-app-profile");
+   *
+   * AppProfile updatedAppProfile = client.updateAppProfile(
+   *   UpdateAppProfileRequest.of(existingAppProfile)
+   *     .setRoutingPolicy(SingleClusterRoutingPolicy.of("my-cluster"))
+   * );
+   * }
+ */ @SuppressWarnings("WeakerAccess") public AppProfile updateAppProfile(UpdateAppProfileRequest request) { return awaitFuture(updateAppProfileAsync(request)); } + /** + * Asynchronously updates an existing app profile. + * + *

Sample code: + * + *

{@code
+   *
+   * ApiFuture existingAppProfileFuture = client.getAppProfileAsync("my-instance", "my-app-profile");
+   *
+   * ApiFuture updatedAppProfileFuture = ApiFutures.transformAsync(
+   *   existingAppProfileFuture,
+   *   new ApiAsyncFunction() {
+   *     @Override
+   *     public ApiFuture apply(AppProfile existingAppProfile) {
+   *       return client.updateAppProfileAsync(
+   *         UpdateAppProfileRequest.of(existingAppProfile)
+   *           .setRoutingPolicy(SingleClusterRoutingPolicy.of("my-other-cluster"))
+   *       );
+   *     }
+   *   },
+   *   MoreExecutors.directExecutor()
+   * );
+   *
+   * ApiFuture appProfile = updatedAppProfileFuture.get();
+   * }
+ */ @SuppressWarnings("WeakerAccess") public ApiFuture updateAppProfileAsync(UpdateAppProfileRequest request) { return ApiFutures.transform( @@ -263,11 +371,31 @@ public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { ); } + /** + * Deletes the specified app profile. + * + *

Sample code: + * + *

{@code
+   * client.deleteAppProfile("my-instance", "my-app-profile");
+   * }
+ */ @SuppressWarnings("WeakerAccess") public void deleteAppProfile(String instanceId, String appProfileId) { awaitFuture(deleteAppProfileAsync(instanceId, appProfileId)); } + /** + * Asynchronously deletes the specified app profile. + * + *

Sample code: + * + *

{@code
+   * ApiFuture deleteFuture = client.deleteAppProfileAsync("my-instance", "my-app-profile");
+   *
+   * deleteFuture.get();
+   * }
+ */ @SuppressWarnings("WeakerAccess") public ApiFuture deleteAppProfileAsync(String instanceId, String appProfileId) { AppProfileName name = AppProfileName.of(projectName.getProject(), instanceId, appProfileId); diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/AppProfile.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/AppProfile.java index 9707b2b556b3..35c20f7b60e8 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/AppProfile.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/AppProfile.java @@ -15,25 +15,54 @@ */ package com.google.cloud.bigtable.admin.v2.models; +import com.google.api.core.InternalApi; import com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny; import com.google.bigtable.admin.v2.AppProfileName; import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.base.Verify; import com.google.common.base.VerifyException; +import javax.annotation.Nonnull; -public class AppProfile { +/** + *

An application profile, or app profile, stores settings that tell your Cloud Bigtable + * instance how to handle incoming requests from an application. When one of your applications + * connects to a Cloud Bigtable instance, it can specify an app profile, and Cloud Bigtable uses + * that app profile for any requests that the application sends over that connection. + * + *

App profiles affect how your applications communicate with an instance that uses replication. + * As a result, app profiles are especially useful for instances that have 2 clusters. Even if your + * instance has only 1 cluster, you can use a unique app profile for each application that you run, + * or for different components within a single application. + * + * @see For more details. + */ +public final class AppProfile { private final com.google.bigtable.admin.v2.AppProfile proto; - public static AppProfile fromProto(com.google.bigtable.admin.v2.AppProfile proto) { + /** + * Wraps a protobuf response. + * + *

This method is considered an internal implementation detail and not meant to be used by + * applications. + */ + @InternalApi + public static AppProfile fromProto(@Nonnull com.google.bigtable.admin.v2.AppProfile proto) { return new AppProfile(proto); } - private AppProfile(com.google.bigtable.admin.v2.AppProfile proto) { + private AppProfile(@Nonnull com.google.bigtable.admin.v2.AppProfile proto) { + Preconditions.checkNotNull(proto); + Preconditions + .checkArgument(proto.hasSingleClusterRouting() || proto.hasMultiClusterRoutingUseAny(), + "AppProfile must have a routing policy"); + Preconditions.checkArgument(!proto.getName().isEmpty(), "AppProfile must have a name"); this.proto = proto; - Preconditions.checkArgument(proto.hasSingleClusterRouting() || proto.hasMultiClusterRoutingUseAny(), "AppProfile must have a routing policy"); } + + /** Gets the routing policy for all read/write requests which use this app profile. */ + @SuppressWarnings("WeakerAccess") public RoutingPolicy getPolicy() { if (proto.hasMultiClusterRoutingUseAny()) { return MultiClusterRoutingPolicy.of(); @@ -45,6 +74,8 @@ public RoutingPolicy getPolicy() { } } + /** Gets the id of this AppProfile. */ + @SuppressWarnings("WeakerAccess") public String getId() { AppProfileName fullName = Verify.verifyNotNull( AppProfileName.parse(proto.getName()), @@ -54,6 +85,8 @@ public String getId() { return fullName.getAppProfile(); } + /** Gets the id of the instance that owns this AppProfile. */ + @SuppressWarnings("WeakerAccess") public String getInstanceId() { AppProfileName fullName = Verify.verifyNotNull( AppProfileName.parse(proto.getName()), @@ -63,68 +96,84 @@ public String getInstanceId() { return fullName.getInstance(); } + /** Gets long form description of the use case for this AppProfile. */ + @SuppressWarnings("WeakerAccess") public String getDescription() { return proto.getDescription(); } - public String getEtag() { - return proto.getEtag(); - } - com.google.bigtable.admin.v2.AppProfile getProto() { + /** + * Creates the request protobuf. This method is considered an internal implementation detail and + * not meant to be used by applications. + */ + com.google.bigtable.admin.v2.AppProfile toProto() { return proto; } - public interface RoutingPolicy { - } - - public static class MultiClusterRoutingPolicy implements RoutingPolicy { - private static final MultiClusterRoutingUseAny proto = MultiClusterRoutingUseAny.getDefaultInstance(); - - public static MultiClusterRoutingPolicy of() { - return new MultiClusterRoutingPolicy(); - } - - private MultiClusterRoutingPolicy() { + @Override + public boolean equals(Object o) { + if (this == o) { + return true; } - - MultiClusterRoutingUseAny toProto() { - return proto; + if (o == null || getClass() != o.getClass()) { + return false; } + AppProfile that = (AppProfile) o; + return Objects.equal(proto, that.proto); + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } + @Override + public int hashCode() { + return Objects.hashCode(proto); + } - return true; - } - @Override - public int hashCode() { - return Objects.hashCode(proto); - } + /** + * Represents the routing for read/write requests. Please check the implementations of this + * interface for more details. + */ + @SuppressWarnings("WeakerAccess") + public interface RoutingPolicy { } + /** + * A {@link RoutingPolicy} that routes all requests to a specific cluster. + */ + @SuppressWarnings("WeakerAccess") public static class SingleClusterRoutingPolicy implements RoutingPolicy { private final com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting proto; - public static SingleClusterRoutingPolicy fromProto(com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting proto) { + /** + * Wraps a protobuf response. + * + *

This method is considered an internal implementation detail and not meant to be used by + * applications. + */ + @InternalApi + public static SingleClusterRoutingPolicy fromProto( + com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting proto) { return new SingleClusterRoutingPolicy(proto); } + /** + * Builds a new instance of the routing policy that will send all requests to the specified + * cluster. + * + *

Please note that atomic row transactions will be disabled. + */ public static SingleClusterRoutingPolicy of(String clusterId) { - return fromProto( - com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting.newBuilder() - .setClusterId(clusterId) - .build() - ); + return of(clusterId, false); } + /** + * Builds a new instance of the routing policy that will send all requests to the specified + * cluster. This variant enables the ability to re-enable single row transactions at the cost of + * consistency. + * + *

Please see the online + * documentation for more details. + */ public static SingleClusterRoutingPolicy of(String clusterId, boolean allowTransactionWrites) { return fromProto( com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting.newBuilder() @@ -134,18 +183,30 @@ public static SingleClusterRoutingPolicy of(String clusterId, boolean allowTrans ); } - private SingleClusterRoutingPolicy(com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting proto) { + private SingleClusterRoutingPolicy( + com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting proto) { this.proto = proto; } + /** Gets the target cluster of this policy. */ + @SuppressWarnings("WeakerAccess") public String getClusterId() { return proto.getClusterId(); } + /** Checks if transactional writes are enabled. */ + @SuppressWarnings("WeakerAccess") public boolean getAllowTransactionalWrites() { return proto.getAllowTransactionalWrites(); } + /** + * Wraps a protobuf response. + * + *

This method is considered an internal implementation detail and not meant to be used by + * applications. + */ + @InternalApi com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting toProto() { return proto; } @@ -167,4 +228,47 @@ public int hashCode() { return Objects.hashCode(proto); } } + + /** + * A {@link RoutingPolicy} that tells Cloud Bigtable that it can route each request to any + * available cluster. + */ + public static class MultiClusterRoutingPolicy implements RoutingPolicy { + private static final MultiClusterRoutingUseAny proto = MultiClusterRoutingUseAny + .getDefaultInstance(); + + /** Creates a new instance of {@link MultiClusterRoutingPolicy}. */ + public static MultiClusterRoutingPolicy of() { + return new MultiClusterRoutingPolicy(); + } + + private MultiClusterRoutingPolicy() { + } + + /** + * Creates the request protobuf. This method is considered an internal implementation detail and + * not meant to be used by applications. + */ + @InternalApi + MultiClusterRoutingUseAny toProto() { + return proto; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return Objects.hashCode(proto); + } + } } diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequest.java index 71457af42399..85141329c153 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequest.java @@ -24,11 +24,30 @@ import com.google.common.base.Preconditions; import javax.annotation.Nonnull; -public class CreateAppProfileRequest { +/** + * Parameters for creating a new Cloud Bigtable app profile. + * + *

An application profile, or app profile, stores settings that tell your Cloud Bigtable + * instance how to handle incoming requests from an application. When one of your applications + * connects to a Cloud Bigtable instance, it can specify an app profile, and Cloud Bigtable uses + * that app profile for any requests that the application sends over that connection. + * + *

Sample code: + * + *

{@code
+ * AppProfile existingAppProfile = ...;
+ * CreateAppProfileRequest appProfileRequest = CreateAppProfileRequest.of("my-instance", "my-new-app-profile")
+ *   .setRoutingPolicy(SingleClusterRoutingPolicy.of("my-cluster"));
+ * }
+ * + * @see AppProfile for more details + */ +public final class CreateAppProfileRequest { private final String instanceId; private final com.google.bigtable.admin.v2.CreateAppProfileRequest.Builder proto; - public CreateAppProfileRequest of(String instanceId, String appProfileId) { + /** Builds a new request to create a new app profile in the specified instance. */ + public static CreateAppProfileRequest of(String instanceId, String appProfileId) { return new CreateAppProfileRequest(instanceId, appProfileId); } @@ -40,16 +59,22 @@ private CreateAppProfileRequest(String instanceId, String appProfileId) { proto.getAppProfileBuilder().setDescription(appProfileId); } + /** Configures if safety warnings should be disabled. */ + @SuppressWarnings("WeakerAccess") public CreateAppProfileRequest setIgnoreWarnings(boolean value) { proto.setIgnoreWarnings(value); return this; } + /** Sets the optional long form description of the use case for the AppProfile. */ + @SuppressWarnings("WeakerAccess") public CreateAppProfileRequest setDescription(@Nonnull String description) { proto.getAppProfileBuilder().setDescription(description); return this; } + /** Sets the routing policy for all read/write requests that use this app profile. */ + @SuppressWarnings("WeakerAccess") public CreateAppProfileRequest setRoutingPolicy(RoutingPolicy routingPolicy) { Preconditions.checkNotNull(routingPolicy); @@ -64,6 +89,10 @@ public CreateAppProfileRequest setRoutingPolicy(RoutingPolicy routingPolicy) { return this; } + /** + * Creates the request protobuf. This method is considered an internal implementation detail and + * not meant to be used by applications. + */ @InternalApi public com.google.bigtable.admin.v2.CreateAppProfileRequest toProto(ProjectName projectName) { InstanceName name = InstanceName.of(projectName.getProject(), instanceId); diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java index e4669a28df1b..57a89c620e62 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java @@ -18,50 +18,74 @@ import com.google.api.core.InternalApi; import com.google.bigtable.admin.v2.AppProfileName; import com.google.bigtable.admin.v2.ProjectName; -import com.google.bigtable.admin.v2.UpdateAppProfileRequest.Builder; import com.google.cloud.bigtable.admin.v2.models.AppProfile.MultiClusterRoutingPolicy; import com.google.cloud.bigtable.admin.v2.models.AppProfile.RoutingPolicy; import com.google.cloud.bigtable.admin.v2.models.AppProfile.SingleClusterRoutingPolicy; import com.google.common.base.Objects; import com.google.common.base.Preconditions; -import com.google.common.base.Verify; import com.google.protobuf.FieldMask; import com.google.protobuf.util.FieldMaskUtil; import javax.annotation.Nonnull; -public class UpdateAppProfileRequest { +/** + * Parameters for updating an existing Cloud Bigtable app profile. + * + *

Examples + * + *

{@code
+ * AppProfile existingAppProfile = ...;
+ * UpdateAppProfileRequest appProfileRequest = UpdateAppProfileRequest.of(existingAppProfile)
+ *   .setRoutingPolicy(SingleClusterRoutingPolicy.of("my-cluster"));
+ * }
+ * + * @see AppProfile for more details + */ +public final class UpdateAppProfileRequest { private final String instanceId; private final String appProfileId; private final com.google.bigtable.admin.v2.UpdateAppProfileRequest.Builder proto; - public static UpdateAppProfileRequest of(@Nonnull String instanceId, @Nonnull String appProfileId) { - return new UpdateAppProfileRequest(instanceId, appProfileId, - com.google.bigtable.admin.v2.UpdateAppProfileRequest.newBuilder()); - } - + /** + * Builds a new update request using an existing AppProfile. + * + *

This variant is recommended over {@link #of(String, String)} because it provides optimistic + * concurrency control using etags. + */ public static UpdateAppProfileRequest of(@Nonnull AppProfile appProfile) { return new UpdateAppProfileRequest(appProfile.getInstanceId(), appProfile.getId(), com.google.bigtable.admin.v2.UpdateAppProfileRequest.newBuilder() - .setAppProfile(appProfile.getProto()) - ); + .setAppProfile(appProfile.toProto()) + ); + } + + /** Builds a new update request using an existing AppProfile. */ + public static UpdateAppProfileRequest of(@Nonnull String instanceId, + @Nonnull String appProfileId) { + return new UpdateAppProfileRequest(instanceId, appProfileId, + com.google.bigtable.admin.v2.UpdateAppProfileRequest.newBuilder()); } - private UpdateAppProfileRequest(@Nonnull String instanceId, @Nonnull String appProfileId, @Nonnull Builder builder) { + private UpdateAppProfileRequest(@Nonnull String instanceId, @Nonnull String appProfileId, + @Nonnull com.google.bigtable.admin.v2.UpdateAppProfileRequest.Builder builder) { Preconditions.checkNotNull(instanceId, "instanceId must be set"); Preconditions.checkNotNull(appProfileId, "appProfileId must be set"); - Verify.verifyNotNull(builder); + Preconditions.checkNotNull(builder, "builder must be set"); this.instanceId = instanceId; this.appProfileId = appProfileId; this.proto = builder; } + /** Configures if safety warnings should be disabled. */ + @SuppressWarnings("WeakerAccess") public UpdateAppProfileRequest setIgnoreWarnings(boolean value) { proto.setIgnoreWarnings(value); return this; } + /** Sets the optional long form description of the use case for the AppProfile. */ + @SuppressWarnings("WeakerAccess") public UpdateAppProfileRequest setDescription(@Nonnull String description) { Preconditions.checkNotNull(description); @@ -70,14 +94,19 @@ public UpdateAppProfileRequest setDescription(@Nonnull String description) { return this; } - public UpdateAppProfileRequest setRoutingPolicy(RoutingPolicy routingPolicy) { + /** Sets the routing policy for all read/write requests that use this app profile. */ + @SuppressWarnings("WeakerAccess") + public UpdateAppProfileRequest setRoutingPolicy(@Nonnull RoutingPolicy routingPolicy) { Preconditions.checkNotNull(routingPolicy); if (routingPolicy instanceof MultiClusterRoutingPolicy) { - proto.getAppProfileBuilder().setMultiClusterRoutingUseAny(((MultiClusterRoutingPolicy)routingPolicy).toProto()); - updateFieldMask(com.google.bigtable.admin.v2.AppProfile.MULTI_CLUSTER_ROUTING_USE_ANY_FIELD_NUMBER); + proto.getAppProfileBuilder() + .setMultiClusterRoutingUseAny(((MultiClusterRoutingPolicy) routingPolicy).toProto()); + updateFieldMask( + com.google.bigtable.admin.v2.AppProfile.MULTI_CLUSTER_ROUTING_USE_ANY_FIELD_NUMBER); } else if (routingPolicy instanceof SingleClusterRoutingPolicy) { - proto.getAppProfileBuilder().setSingleClusterRouting(((SingleClusterRoutingPolicy)routingPolicy).toProto()); + proto.getAppProfileBuilder() + .setSingleClusterRouting(((SingleClusterRoutingPolicy) routingPolicy).toProto()); updateFieldMask(com.google.bigtable.admin.v2.AppProfile.SINGLE_CLUSTER_ROUTING_FIELD_NUMBER); } else { throw new IllegalArgumentException("Unknown policy type: " + routingPolicy); @@ -87,10 +116,15 @@ public UpdateAppProfileRequest setRoutingPolicy(RoutingPolicy routingPolicy) { } private void updateFieldMask(int fieldNumber) { - FieldMask newMask = FieldMaskUtil.fromFieldNumbers(com.google.bigtable.admin.v2.AppProfile.class, fieldNumber); + FieldMask newMask = FieldMaskUtil + .fromFieldNumbers(com.google.bigtable.admin.v2.AppProfile.class, fieldNumber); proto.setUpdateMask(FieldMaskUtil.union(proto.getUpdateMask(), newMask)); } + /** + * Creates the request protobuf. This method is considered an internal implementation detail and + * not meant to be used by applications. + */ @InternalApi public com.google.bigtable.admin.v2.UpdateAppProfileRequest toProto(ProjectName projectName) { AppProfileName name = AppProfileName.of(projectName.getProject(), instanceId, appProfileId); diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java index d76193b7afb5..4efe8993525c 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java @@ -17,30 +17,82 @@ import static com.google.common.truth.Truth.assertThat; +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.api.gax.grpc.GrpcStatusCode; +import com.google.api.gax.longrunning.OperationFuture; +import com.google.api.gax.longrunning.OperationFutures; +import com.google.api.gax.longrunning.OperationSnapshot; +import com.google.api.gax.rpc.OperationCallable; +import com.google.api.gax.rpc.UnaryCallable; +import com.google.api.gax.rpc.testing.FakeOperationSnapshot; +import com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny; +import com.google.bigtable.admin.v2.AppProfileName; +import com.google.bigtable.admin.v2.InstanceName; import com.google.bigtable.admin.v2.ProjectName; +import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPage; +import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPagedResponse; +import com.google.cloud.bigtable.admin.v2.models.AppProfile; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.MultiClusterRoutingPolicy; +import com.google.cloud.bigtable.admin.v2.models.CreateAppProfileRequest; +import com.google.cloud.bigtable.admin.v2.models.UpdateAppProfileRequest; import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub; +import com.google.common.collect.Lists; +import com.google.common.truth.Truth; +import com.google.protobuf.Empty; +import com.google.protobuf.FieldMask; +import io.grpc.Status.Code; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; @RunWith(MockitoJUnitRunner.class) public class BigtableInstanceAdminClientTest { + private static final ProjectName PROJECT_NAME = ProjectName.of("my-project"); + private static final InstanceName INSTANCE_NAME = + InstanceName.of(PROJECT_NAME.getProject(), "my-instance"); + private static final AppProfileName APP_PROFILE_NAME = + AppProfileName.of(INSTANCE_NAME.getProject(), INSTANCE_NAME.getInstance(), "my-cluster"); + private BigtableInstanceAdminClient adminClient; + @Mock private BigtableInstanceAdminStub mockStub; + @Mock + private UnaryCallable mockCreateAppProfileCallable; + @Mock + private UnaryCallable mockGetAppProfileCallable; + @Mock + private UnaryCallable mockListAppProfilesCallable; + @Mock + private OperationCallable mockUpdateAppProfileCallable; + @Mock + private UnaryCallable mockDeleteAppProfileCallable; + + @Before public void setUp() { - adminClient = BigtableInstanceAdminClient - .create(ProjectName.of("[PROJECT]"), mockStub); + adminClient = BigtableInstanceAdminClient.create(PROJECT_NAME, mockStub); + + Mockito.when(mockStub.createAppProfileCallable()).thenReturn(mockCreateAppProfileCallable); + Mockito.when(mockStub.getAppProfileCallable()).thenReturn(mockGetAppProfileCallable); + Mockito.when(mockStub.listAppProfilesPagedCallable()).thenReturn(mockListAppProfilesCallable); + Mockito.when(mockStub.updateAppProfileOperationCallable()) + .thenReturn(mockUpdateAppProfileCallable); + Mockito.when(mockStub.deleteAppProfileCallable()).thenReturn(mockDeleteAppProfileCallable); } @Test public void testProjectName() { - assertThat(adminClient.getProjectName()).isEqualTo(ProjectName.of("[PROJECT]")); + assertThat(adminClient.getProjectName()).isEqualTo(PROJECT_NAME); } @Test @@ -48,4 +100,198 @@ public void testClose() { adminClient.close(); Mockito.verify(mockStub).close(); } + + @Test + public void testCreateAppProfile() { + // Setup + com.google.bigtable.admin.v2.CreateAppProfileRequest expectedRequest = + com.google.bigtable.admin.v2.CreateAppProfileRequest.newBuilder() + .setParent(INSTANCE_NAME.toString()) + .setAppProfileId(APP_PROFILE_NAME.getAppProfile()) + .setAppProfile( + com.google.bigtable.admin.v2.AppProfile.newBuilder() + .setDescription("my description") + .setMultiClusterRoutingUseAny( + com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny + .getDefaultInstance()) + ) + .build(); + + com.google.bigtable.admin.v2.AppProfile expectedResponse = + com.google.bigtable.admin.v2.AppProfile.newBuilder() + .setName(APP_PROFILE_NAME.toString()) + .setDescription("my description") + .setMultiClusterRoutingUseAny( + com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny + .getDefaultInstance()) + .build(); + + Mockito.when(mockCreateAppProfileCallable.futureCall(expectedRequest)).thenReturn( + ApiFutures.immediateFuture(expectedResponse) + ); + + // Execute + AppProfile actualResult = adminClient.createAppProfile( + CreateAppProfileRequest.of(APP_PROFILE_NAME.getInstance(), APP_PROFILE_NAME.getAppProfile()) + .setDescription("my description") + .setRoutingPolicy(MultiClusterRoutingPolicy.of()) + ); + + // Verify + Truth.assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse)); + } + + @Test + public void testGetAppProfile() { + // Setup + com.google.bigtable.admin.v2.GetAppProfileRequest expectedRequest = + com.google.bigtable.admin.v2.GetAppProfileRequest.newBuilder() + .setName(APP_PROFILE_NAME.toString()) + .build(); + + com.google.bigtable.admin.v2.AppProfile expectedResponse = + com.google.bigtable.admin.v2.AppProfile.newBuilder() + .setName(APP_PROFILE_NAME.toString()) + .setDescription("my description") + .setMultiClusterRoutingUseAny( + com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny + .getDefaultInstance()) + .build(); + + Mockito.when(mockGetAppProfileCallable.futureCall(expectedRequest)) + .thenReturn(ApiFutures.immediateFuture(expectedResponse)); + + // Execute + AppProfile actualResult = adminClient + .getAppProfile(APP_PROFILE_NAME.getInstance(), APP_PROFILE_NAME.getAppProfile()); + + // Verify + Truth.assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse)); + } + + @Test + public void testListAppProfiles() { + // Setup + com.google.bigtable.admin.v2.ListAppProfilesRequest expectedRequest = + com.google.bigtable.admin.v2.ListAppProfilesRequest.newBuilder() + .setParent(INSTANCE_NAME.toString()) + .build(); + + // 3 AppProfiles spread across 2 pages + List expectedProtos = Lists.newArrayList(); + for (int i = 0; i < 3; i++) { + expectedProtos.add( + com.google.bigtable.admin.v2.AppProfile.newBuilder() + .setName(APP_PROFILE_NAME.toString() + i) + .setDescription("profile" + i) + .setMultiClusterRoutingUseAny( + com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny + .getDefaultInstance()) + .build()); + } + // 2 on the first page + ListAppProfilesPage page0 = Mockito.mock(ListAppProfilesPage.class); + Mockito.when(page0.getValues()).thenReturn(expectedProtos.subList(0, 2)); + Mockito.when(page0.getNextPageToken()).thenReturn("next-page"); + Mockito.when(page0.hasNextPage()).thenReturn(true); + + // 1 on the last page + ListAppProfilesPage page1 = Mockito.mock(ListAppProfilesPage.class); + Mockito.when(page1.getValues()).thenReturn(expectedProtos.subList(2, 3)); + + // Link page0 to page1 + Mockito.when(page0.getNextPageAsync()).thenReturn( + ApiFutures.immediateFuture(page1) + ); + + // Link page to the response + ListAppProfilesPagedResponse response0 = Mockito.mock(ListAppProfilesPagedResponse.class); + Mockito.when(response0.getPage()).thenReturn(page0); + + Mockito.when(mockListAppProfilesCallable.futureCall(expectedRequest)).thenReturn( + ApiFutures.immediateFuture(response0) + ); + + // Execute + List actualResults = adminClient.listAppProfiles(INSTANCE_NAME.getInstance()); + + // Verify + List expectedResults = Lists.newArrayList(); + for (com.google.bigtable.admin.v2.AppProfile expectedProto : expectedProtos) { + expectedResults.add(AppProfile.fromProto(expectedProto)); + } + + Truth.assertThat(actualResults).containsExactlyElementsIn(expectedResults); + } + + @Test + public void testUpdateAppProfile() { + // Setup + com.google.bigtable.admin.v2.UpdateAppProfileRequest expectedRequest = + com.google.bigtable.admin.v2.UpdateAppProfileRequest.newBuilder() + .setAppProfile( + com.google.bigtable.admin.v2.AppProfile.newBuilder() + .setName(APP_PROFILE_NAME.toString()) + .setDescription("updated description") + ) + .setUpdateMask(FieldMask.newBuilder().addPaths("description")) + .build(); + + com.google.bigtable.admin.v2.AppProfile expectedResponse = + com.google.bigtable.admin.v2.AppProfile.newBuilder() + .setName(APP_PROFILE_NAME.toString()) + .setDescription("updated description") + .setMultiClusterRoutingUseAny(MultiClusterRoutingUseAny.getDefaultInstance()) + .build(); + + mockOperationResult(mockUpdateAppProfileCallable, expectedRequest, expectedResponse); + + // Execute + AppProfile actualResult = adminClient.updateAppProfile( + UpdateAppProfileRequest.of(APP_PROFILE_NAME.getInstance(), APP_PROFILE_NAME.getAppProfile()) + .setDescription("updated description") + ); + + // Verify + Truth.assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse)); + } + + @Test + public void testDeleteAppProfile() { + // Setup + com.google.bigtable.admin.v2.DeleteAppProfileRequest expectedRequest = + com.google.bigtable.admin.v2.DeleteAppProfileRequest.newBuilder() + .setName(APP_PROFILE_NAME.toString()) + .build(); + + final AtomicBoolean wasCalled = new AtomicBoolean(false); + + Mockito.when(mockDeleteAppProfileCallable.futureCall(expectedRequest)) + .thenAnswer(new Answer>() { + @Override + public ApiFuture answer(InvocationOnMock invocationOnMock) { + wasCalled.set(true); + return ApiFutures.immediateFuture(Empty.getDefaultInstance()); + } + }); + + // Execute + adminClient.deleteAppProfile(APP_PROFILE_NAME.getInstance(), APP_PROFILE_NAME.getAppProfile()); + + // Verify + Truth.assertThat(wasCalled.get()).isTrue(); + } + + private void mockOperationResult( + OperationCallable callable, ReqT request, RespT response) { + OperationSnapshot operationSnapshot = FakeOperationSnapshot.newBuilder() + .setDone(true) + .setErrorCode(GrpcStatusCode.of(Code.OK)) + .setName("fake-name") + .setResponse(response) + .build(); + OperationFuture operationFuture = OperationFutures + .immediateOperationFuture(operationSnapshot); + Mockito.when(callable.futureCall(request)).thenReturn(operationFuture); + } } diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/AppProfileTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/AppProfileTest.java new file mode 100644 index 000000000000..2d725d9a8489 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/AppProfileTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2018 Google LLC + * + * 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 + * + * https://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.cloud.bigtable.admin.v2.models; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting; +import com.google.bigtable.admin.v2.AppProfileName; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.SingleClusterRoutingPolicy; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class AppProfileTest { + private static final com.google.bigtable.admin.v2.AppProfile TEST_PROTO = + com.google.bigtable.admin.v2.AppProfile.newBuilder() + .setName(AppProfileName.of("my-project", "my-instance", "my-profile").toString()) + .setDescription("my description") + .setSingleClusterRouting( + SingleClusterRouting.newBuilder() + .setClusterId("my-cluster") + .setAllowTransactionalWrites(true) + .build() + + ) + .setEtag("my-etag") + .build(); + + @Test + public void testFromProto() { + AppProfile profile = AppProfile.fromProto(TEST_PROTO); + + assertThat(profile.getInstanceId()).isEqualTo("my-instance"); + assertThat(profile.getId()).isEqualTo("my-profile"); + assertThat(profile.getDescription()).isEqualTo("my description"); + assertThat(profile.getPolicy()).isEqualTo(SingleClusterRoutingPolicy.of("my-cluster", true)); + } + + @Test + public void testNoNameError() { + Exception actualException = null; + + try { + AppProfile.fromProto( + TEST_PROTO.toBuilder() + .setName("") + .build()); + } catch (Exception e) { + actualException = e; + } + + assertThat(actualException).isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void testNoPolicyError() { + Exception actualException = null; + + try { + AppProfile.fromProto( + TEST_PROTO.toBuilder() + .clearSingleClusterRouting() + .build()); + } catch (Exception e) { + actualException = e; + } + + assertThat(actualException).isInstanceOf(IllegalArgumentException.class); + } +} \ No newline at end of file diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java new file mode 100644 index 000000000000..88f32a8eb9a8 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java @@ -0,0 +1,64 @@ +package com.google.cloud.bigtable.admin.v2.models; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny; +import com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting; +import com.google.bigtable.admin.v2.InstanceName; +import com.google.bigtable.admin.v2.ProjectName; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.MultiClusterRoutingPolicy; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.SingleClusterRoutingPolicy; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class CreateAppProfileRequestTest { + @Test + public void testToProto() { + CreateAppProfileRequest wrapper = CreateAppProfileRequest.of("my-instance", "my-profile") + .setDescription("my description") + .setRoutingPolicy( + SingleClusterRoutingPolicy.of("my-cluster", true) + ) + .setIgnoreWarnings(true); + + assertThat(wrapper.toProto(ProjectName.of("my-project"))).isEqualTo( + com.google.bigtable.admin.v2.CreateAppProfileRequest.newBuilder() + .setParent(InstanceName.of("my-project", "my-instance").toString()) + .setAppProfileId("my-profile") + .setAppProfile( + com.google.bigtable.admin.v2.AppProfile.newBuilder() + .setDescription("my description") + .setSingleClusterRouting( + SingleClusterRouting.newBuilder() + .setClusterId("my-cluster") + .setAllowTransactionalWrites(true) + ) + ) + .setIgnoreWarnings(true) + .build() + ); + } + + @Test + public void testMultiClusterRouting() { + CreateAppProfileRequest wrapper = CreateAppProfileRequest.of("my-instance", "my-profile") + .setRoutingPolicy(MultiClusterRoutingPolicy.of()); + + assertThat(wrapper.toProto(ProjectName.of("my-project")).getAppProfile() + .getMultiClusterRoutingUseAny()) + .isEqualTo(MultiClusterRoutingUseAny.getDefaultInstance()); + } + + @Test + public void testDefaultDescription() { + CreateAppProfileRequest wrapper = CreateAppProfileRequest.of("my-instance", "my-profile") + .setRoutingPolicy(MultiClusterRoutingPolicy.of()); + + assertThat(wrapper.toProto(ProjectName.of("my-project")).getAppProfile().getDescription()) + .isEqualTo( + "my-profile" + ); + } +} \ No newline at end of file diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java new file mode 100644 index 000000000000..572e433af7e0 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java @@ -0,0 +1,69 @@ +package com.google.cloud.bigtable.admin.v2.models; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny; +import com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting; +import com.google.bigtable.admin.v2.ProjectName; +import com.google.cloud.bigtable.admin.v2.models.AppProfile.SingleClusterRoutingPolicy; +import com.google.protobuf.FieldMask; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class UpdateAppProfileRequestTest { + @Test + public void testToProto() { + UpdateAppProfileRequest wrapper = UpdateAppProfileRequest.of("my-instance", "my-profile") + .setDescription("my description") + .setRoutingPolicy( + SingleClusterRoutingPolicy.of("my-cluster", true) + ) + .setIgnoreWarnings(true); + + assertThat(wrapper.toProto(ProjectName.of("my-project"))).isEqualTo( + com.google.bigtable.admin.v2.UpdateAppProfileRequest.newBuilder() + .setAppProfile( + com.google.bigtable.admin.v2.AppProfile.newBuilder() + .setName("projects/my-project/instances/my-instance/appProfiles/my-profile") + .setDescription("my description") + .setSingleClusterRouting( + SingleClusterRouting.newBuilder() + .setClusterId("my-cluster") + .setAllowTransactionalWrites(true) + ) + ) + .setIgnoreWarnings(true) + .setUpdateMask( + FieldMask.newBuilder() + .addPaths("description") + .addPaths("single_cluster_routing") + ) + .build() + ); + } + + @Test + public void testUpdateExisting() { + com.google.bigtable.admin.v2.AppProfile existingProto = com.google.bigtable.admin.v2.AppProfile + .newBuilder() + .setName("projects/my-project/instances/my-instance/appProfiles/my-profile") + .setEtag("my-etag") + .setDescription("description") + .setMultiClusterRoutingUseAny(MultiClusterRoutingUseAny.getDefaultInstance()) + .build(); + + AppProfile existingWrapper = AppProfile.fromProto(existingProto); + + UpdateAppProfileRequest updateWrapper = UpdateAppProfileRequest.of(existingWrapper) + .setDescription("new description"); + + assertThat(updateWrapper.toProto(ProjectName.of("my-project"))).isEqualTo( + com.google.bigtable.admin.v2.UpdateAppProfileRequest.newBuilder() + .setAppProfile(existingProto.toBuilder().setDescription("new description")) + .setUpdateMask(FieldMask.newBuilder().addPaths("description")) + .build() + ); + } +} \ No newline at end of file From 3a7f0b4aee7f68276ca6358f665050d9b7b635c0 Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 30 Aug 2018 17:24:39 -0400 Subject: [PATCH 3/8] add @see --- .../admin/v2/BigtableInstanceAdminClient.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java index 57f7fb14d3de..bcabcdef3d80 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java @@ -139,6 +139,8 @@ public void close() { * .setRoutingPolicy(SingleClusterRoutingPolicy.of("my-cluster")) * ); * } + * + * @see CreateAppProfileRequest */ @SuppressWarnings("WeakerAccess") public AppProfile createAppProfile(CreateAppProfileRequest request) { @@ -158,6 +160,8 @@ public AppProfile createAppProfile(CreateAppProfileRequest request) { * * AppProfile appProfile = appProfileFuture.get(); * } + * + * @see CreateAppProfileRequest */ @SuppressWarnings("WeakerAccess") public ApiFuture createAppProfileAsync(CreateAppProfileRequest request) { @@ -181,6 +185,8 @@ public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { *

{@code
    * AppProfile appProfile = client.getAppProfile("my-instance", "my-app-profile");
    * }
+ * + * @see AppProfile */ @SuppressWarnings("WeakerAccess") public AppProfile getAppProfile(String instanceId, String appProfileId) { @@ -197,6 +203,8 @@ public AppProfile getAppProfile(String instanceId, String appProfileId) { * * AppProfile appProfile = appProfileFuture.get(); * } + * + * @see AppProfile */ @SuppressWarnings("WeakerAccess") public ApiFuture getAppProfileAsync(String instanceId, String appProfileId) { @@ -226,6 +234,8 @@ public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { *
{@code
    * List appProfiles = client.listAppProfiles("my-instance");
    * }
+ * + * @see AppProfile */ @SuppressWarnings("WeakerAccess") public List listAppProfiles(String instanceId) { @@ -242,6 +252,8 @@ public List listAppProfiles(String instanceId) { * * List appProfiles = appProfileFuture.get(); * } + * + * @see AppProfile */ @SuppressWarnings("WeakerAccess") public ApiFuture> listAppProfilesAsync(String instanceId) { @@ -325,6 +337,8 @@ public List apply(List inpu * .setRoutingPolicy(SingleClusterRoutingPolicy.of("my-cluster")) * ); * } + * + * @see UpdateAppProfileRequest */ @SuppressWarnings("WeakerAccess") public AppProfile updateAppProfile(UpdateAppProfileRequest request) { @@ -356,6 +370,8 @@ public AppProfile updateAppProfile(UpdateAppProfileRequest request) { * * ApiFuture appProfile = updatedAppProfileFuture.get(); * } + * + * @see UpdateAppProfileRequest */ @SuppressWarnings("WeakerAccess") public ApiFuture updateAppProfileAsync(UpdateAppProfileRequest request) { From c7b85ae7dcb7f798f07ac19a0fce773dc877aa94 Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 30 Aug 2018 17:47:32 -0400 Subject: [PATCH 4/8] copyright --- .../v2/models/CreateAppProfileRequestTest.java | 15 +++++++++++++++ .../v2/models/UpdateAppProfileRequestTest.java | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java index 88f32a8eb9a8..cbbc74199ba1 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Google LLC + * + * 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 + * + * https://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.cloud.bigtable.admin.v2.models; import static com.google.common.truth.Truth.assertThat; diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java index 572e433af7e0..5dbce3ef516e 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Google LLC + * + * 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 + * + * https://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.cloud.bigtable.admin.v2.models; import static com.google.common.truth.Truth.assertThat; From 18813cb82db7a0756d5ab5ad825105f99784c50b Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 30 Aug 2018 17:48:56 -0400 Subject: [PATCH 5/8] newlines --- .../google/cloud/bigtable/admin/v2/models/AppProfileTest.java | 2 +- .../bigtable/admin/v2/models/UpdateAppProfileRequestTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/AppProfileTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/AppProfileTest.java index 2d725d9a8489..33ca709b836b 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/AppProfileTest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/AppProfileTest.java @@ -81,4 +81,4 @@ public void testNoPolicyError() { assertThat(actualException).isInstanceOf(IllegalArgumentException.class); } -} \ No newline at end of file +} diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java index 5dbce3ef516e..60d69ae5813d 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequestTest.java @@ -81,4 +81,4 @@ public void testUpdateExisting() { .build() ); } -} \ No newline at end of file +} From 5b6792d121e7fa78f3eabd3c305d31b2d6b08fbb Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Thu, 30 Aug 2018 17:50:20 -0400 Subject: [PATCH 6/8] newlines --- .../bigtable/admin/v2/models/CreateAppProfileRequestTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java index cbbc74199ba1..ea683d62d742 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/models/CreateAppProfileRequestTest.java @@ -76,4 +76,4 @@ public void testDefaultDescription() { "my-profile" ); } -} \ No newline at end of file +} From 1e7d4e072291b8e4c37d5708b859091f9b7ca6c0 Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Fri, 31 Aug 2018 14:30:57 -0400 Subject: [PATCH 7/8] address feedback --- .../bigtable/admin/v2/BigtableInstanceAdminClient.java | 4 ++-- .../bigtable/admin/v2/models/UpdateAppProfileRequest.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java index bcabcdef3d80..0840387dfd60 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java @@ -227,7 +227,7 @@ public AppProfile apply(com.google.bigtable.admin.v2.AppProfile proto) { } /** - * Lists all app profiles the specified instance. + * Lists all app profiles of the specified instance. * *

Sample code: * @@ -243,7 +243,7 @@ public List listAppProfiles(String instanceId) { } /** - * Lists all app profiles the specified instance. + * Asynchronously lists all app profiles of the specified instance. * *

Sample code: * diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java index 57a89c620e62..127861d1e27d 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/main/java/com/google/cloud/bigtable/admin/v2/models/UpdateAppProfileRequest.java @@ -67,14 +67,14 @@ public static UpdateAppProfileRequest of(@Nonnull String instanceId, } private UpdateAppProfileRequest(@Nonnull String instanceId, @Nonnull String appProfileId, - @Nonnull com.google.bigtable.admin.v2.UpdateAppProfileRequest.Builder builder) { + @Nonnull com.google.bigtable.admin.v2.UpdateAppProfileRequest.Builder proto) { Preconditions.checkNotNull(instanceId, "instanceId must be set"); Preconditions.checkNotNull(appProfileId, "appProfileId must be set"); - Preconditions.checkNotNull(builder, "builder must be set"); + Preconditions.checkNotNull(proto, "proto must be set"); this.instanceId = instanceId; this.appProfileId = appProfileId; - this.proto = builder; + this.proto = proto; } /** Configures if safety warnings should be disabled. */ From a7ef964499cb9a32f5b730e34b738de1f44201bb Mon Sep 17 00:00:00 2001 From: Igor Bernstein Date: Tue, 4 Sep 2018 13:31:22 -0400 Subject: [PATCH 8/8] fixups --- .../v2/BigtableInstanceAdminClientTest.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java index eb06eeefc38e..487191f19768 100644 --- a/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java +++ b/google-cloud-clients/google-cloud-bigtable-admin/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java @@ -26,7 +26,6 @@ import com.google.api.gax.rpc.OperationCallable; import com.google.api.gax.rpc.UnaryCallable; import com.google.api.gax.rpc.testing.FakeOperationSnapshot; -import com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny; import com.google.bigtable.admin.v2.AppProfileName; import com.google.bigtable.admin.v2.ClusterName; import com.google.bigtable.admin.v2.CreateInstanceMetadata; @@ -52,7 +51,6 @@ import com.google.cloud.bigtable.admin.v2.models.UpdateInstanceRequest; import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub; import com.google.common.collect.Lists; -import com.google.common.truth.Truth; import com.google.protobuf.Empty; import com.google.protobuf.FieldMask; import io.grpc.Status.Code; @@ -69,6 +67,7 @@ @RunWith(MockitoJUnitRunner.class) public class BigtableInstanceAdminClientTest { + private static final ProjectName PROJECT_NAME = ProjectName.of("my-project"); private static final InstanceName INSTANCE_NAME = InstanceName.of(PROJECT_NAME.getProject(), "my-instance"); @@ -569,7 +568,7 @@ public void testCreateAppProfile() { ); // Verify - Truth.assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse)); + assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse)); } @Test @@ -597,7 +596,7 @@ public void testGetAppProfile() { .getAppProfile(APP_PROFILE_NAME.getInstance(), APP_PROFILE_NAME.getAppProfile()); // Verify - Truth.assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse)); + assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse)); } @Test @@ -652,7 +651,7 @@ public void testListAppProfiles() { expectedResults.add(AppProfile.fromProto(expectedProto)); } - Truth.assertThat(actualResults).containsExactlyElementsIn(expectedResults); + assertThat(actualResults).containsExactlyElementsIn(expectedResults); } @Test @@ -672,7 +671,9 @@ public void testUpdateAppProfile() { com.google.bigtable.admin.v2.AppProfile.newBuilder() .setName(APP_PROFILE_NAME.toString()) .setDescription("updated description") - .setMultiClusterRoutingUseAny(MultiClusterRoutingUseAny.getDefaultInstance()) + .setMultiClusterRoutingUseAny( + com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny + .getDefaultInstance()) .build(); mockOperationResult(mockUpdateAppProfileCallable, expectedRequest, expectedResponse); @@ -684,7 +685,7 @@ public void testUpdateAppProfile() { ); // Verify - Truth.assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse)); + assertThat(actualResult).isEqualTo(AppProfile.fromProto(expectedResponse)); } @Test @@ -710,7 +711,7 @@ public ApiFuture answer(InvocationOnMock invocationOnMock) { adminClient.deleteAppProfile(APP_PROFILE_NAME.getInstance(), APP_PROFILE_NAME.getAppProfile()); // Verify - Truth.assertThat(wasCalled.get()).isTrue(); + assertThat(wasCalled.get()).isTrue(); } private void mockOperationResult(