From f10370993a250224e8ae88cc69f8bfb189c5ee0f Mon Sep 17 00:00:00 2001 From: spollapally Date: Wed, 27 Jun 2018 13:21:29 -0400 Subject: [PATCH 1/2] first-cut InstanceAdminClient Impl. --- .../admin/v2/InstanceAdminClient.java | 359 +++++++++++ .../v2/models/InstanceAdminRequests.java | 563 ++++++++++++++++++ .../admin/v2/it/InstanceAdminClientIT.java | 359 +++++++++++ 3 files changed, 1281 insertions(+) create mode 100644 google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/InstanceAdminClient.java create mode 100644 google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/InstanceAdminRequests.java create mode 100644 google-cloud-clients/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/InstanceAdminClientIT.java diff --git a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/InstanceAdminClient.java b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/InstanceAdminClient.java new file mode 100644 index 000000000000..a2d804d746f1 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/InstanceAdminClient.java @@ -0,0 +1,359 @@ +package com.google.cloud.bigtable.admin.v2; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import com.google.api.core.ApiFunction; +import com.google.api.core.ApiFuture; +import com.google.api.core.BetaApi; +import com.google.api.core.SettableApiFuture; +import com.google.api.gax.longrunning.OperationFuture; +import com.google.bigtable.admin.v2.AppProfileName; +import com.google.bigtable.admin.v2.ClusterName; +import com.google.bigtable.admin.v2.CreateClusterMetadata; +import com.google.bigtable.admin.v2.CreateClusterRequest; +import com.google.bigtable.admin.v2.CreateInstanceMetadata; +import com.google.bigtable.admin.v2.DeleteAppProfileRequest; +import com.google.bigtable.admin.v2.DeleteClusterRequest; +import com.google.bigtable.admin.v2.DeleteInstanceRequest; +import com.google.bigtable.admin.v2.GetAppProfileRequest; +import com.google.bigtable.admin.v2.GetClusterRequest; +import com.google.bigtable.admin.v2.GetInstanceRequest; +import com.google.bigtable.admin.v2.InstanceName; +import com.google.bigtable.admin.v2.ListAppProfilesRequest; +import com.google.bigtable.admin.v2.ListAppProfilesResponse; +import com.google.bigtable.admin.v2.ListClustersRequest; +import com.google.bigtable.admin.v2.ListClustersResponse; +import com.google.bigtable.admin.v2.ListInstancesRequest; +import com.google.bigtable.admin.v2.ListInstancesResponse; +import com.google.bigtable.admin.v2.PartialUpdateInstanceRequest; +import com.google.bigtable.admin.v2.ProjectName; +import com.google.bigtable.admin.v2.UpdateAppProfileMetadata; +import com.google.bigtable.admin.v2.UpdateAppProfileRequest; +import com.google.bigtable.admin.v2.UpdateClusterMetadata; +import com.google.bigtable.admin.v2.UpdateInstanceMetadata; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.AppProfile; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Cluster; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.CreateAppProfile; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.CreateInstance; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Instance; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Policy; +import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub; +import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStubSettings; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.iam.v1.GetIamPolicyRequest; +import com.google.iam.v1.SetIamPolicyRequest; +import com.google.iam.v1.TestIamPermissionsRequest; + +@BetaApi +public class InstanceAdminClient implements AutoCloseable { + private final BigtableInstanceAdminStub stub; + + public static final InstanceAdminClient create() throws IOException { + return new InstanceAdminClient(BigtableInstanceAdminSettings.newBuilder().build()); + } + + public static final InstanceAdminClient create(BigtableInstanceAdminSettings settings) + throws IOException { + return new InstanceAdminClient(settings); + } + + public static final InstanceAdminClient create(BigtableInstanceAdminStub stub) { + return new InstanceAdminClient(stub); + } + + public InstanceAdminClient(BigtableInstanceAdminSettings settings) throws IOException { + this(((BigtableInstanceAdminStubSettings) settings.getStubSettings()).createStub()); + } + + public InstanceAdminClient(BigtableInstanceAdminStub stub) { + this.stub = stub; + } + + @Override + public void close() throws Exception { + stub.close(); + } + + /** Discuss: need for CreateInstance wrapper */ + public ApiFuture createInstanceAsync(CreateInstance createInstance) { + final OperationFuture future = + stub.createInstanceOperationCallable().futureCall(createInstance.toProto()); + + return transfromOperationFuture( + future, + new ApiFunction() { + @Override + public Instance apply(com.google.bigtable.admin.v2.Instance input) { + return InstanceAdminRequests.convertToInstance(input); + } + }); + } + + public Instance getInstance(InstanceName instanceName) { + return InstanceAdminRequests.convertToInstance( + stub.getInstanceCallable().call(composeGetInstanceRequest(instanceName))); + } + + public List listInstances(ProjectName projectName) { + return convertToInstances( + stub.listInstancesCallable().call(composeListInstanceRequest(projectName))); + } + + public ApiFuture updateInstance(Instance updatedInstance) { + OperationFuture future = + stub.partialUpdateInstanceOperationCallable() + .futureCall(composePartialUpdateInstanceCallable(updatedInstance)); + + return transfromOperationFuture( + future, + new ApiFunction() { + @Override + public Instance apply(com.google.bigtable.admin.v2.Instance input) { + return InstanceAdminRequests.convertToInstance(input); + } + }); + } + + public void deleteInstanceRequest(InstanceName instanceName) { + stub.deleteInstanceCallable().call(composeDeleteInstanceRequest(instanceName)); + } + + public ApiFuture createCluster(InstanceName instanceName, Cluster cluster) { + OperationFuture future = + stub.createClusterOperationCallable() + .futureCall(composeCreateClusterRequest(instanceName, cluster)); + + return transfromOperationFuture( + future, + new ApiFunction() { + @Override + public Cluster apply(com.google.bigtable.admin.v2.Cluster input) { + return InstanceAdminRequests.convertToCluster(input); + } + }); + } + + public Cluster getCluster(ClusterName clusterName) { + return InstanceAdminRequests.convertToCluster( + stub.getClusterCallable().call(composeGetClusterRequest(clusterName))); + } + + public List listClusters(InstanceName instanceName) { + return convertToClusters( + stub.listClustersCallable().call(composeListClustersRequest(instanceName))); + } + + public ApiFuture updateCluster(Cluster updatedCluster) { + OperationFuture future = + stub.updateClusterOperationCallable().futureCall(updatedCluster.toUpdateProto()); + + return transfromOperationFuture( + future, + new ApiFunction() { + @Override + public Cluster apply(com.google.bigtable.admin.v2.Cluster input) { + return InstanceAdminRequests.convertToCluster(input); + } + }); + } + + public void deleteCluster(ClusterName clusterName) { + stub.deleteClusterCallable().call(composeDeleteClusterRequest(clusterName)); + } + + /** Discuss: need for CreateAppProfile wrapper */ + public AppProfile createAppProfile(CreateAppProfile createAppProfile) { + return InstanceAdminRequests.convertToAppProfile( + stub.createAppProfileCallable().call(createAppProfile.toProto())); + } + + public AppProfile getAppProfile(AppProfileName appProfileName) { + return InstanceAdminRequests.convertToAppProfile( + stub.getAppProfileCallable().call(composeGetAppProfileRequest(appProfileName))); + } + + public List listAppProfiles(InstanceName instanceName) { + return convertToAppProfiles( + stub.listAppProfilesCallable().call(composeListAppProfilesRequest(instanceName))); + } + + public ApiFuture updateAppProfile(AppProfile appProfile) { + OperationFuture future = + stub.updateAppProfileOperationCallable() + .futureCall(composeUpdateAppProfileRequest(appProfile)); + + return transfromOperationFuture( + future, + new ApiFunction() { + @Override + public AppProfile apply(com.google.bigtable.admin.v2.AppProfile input) { + return InstanceAdminRequests.convertToAppProfile(input); + } + }); + } + + public void deleteAppProfile(AppProfileName appProfileName, boolean ignoreWarnings) { + stub.deleteAppProfileCallable() + .call(composeDeleteAppProfileRequest(appProfileName, ignoreWarnings)); + } + + public Policy getIamPolicy(InstanceName instanceName) { + return InstanceAdminRequests.convertToPolicy( + stub.getIamPolicyCallable().call(composeGetIamPolicyRequest(instanceName))); + } + + public Policy setIamPolicy(InstanceName instanceName, Policy policy) { + return InstanceAdminRequests.convertToPolicy( + stub.setIamPolicyCallable().call(composeSetIamPolicyRequest(instanceName, policy))); + } + + public List testIamPermissions(InstanceName instanceName, List permissions) { + return stub.testIamPermissionsCallable() + .call(composeTestIamPermissionsRequest(instanceName, permissions)) + .getPermissionsList(); + } + + /** compose proto request helpers * */ + private static GetInstanceRequest composeGetInstanceRequest(InstanceName instanceName) { + return GetInstanceRequest.newBuilder().setName(instanceName.toString()).build(); + } + + private static ListInstancesRequest composeListInstanceRequest(ProjectName projectName) { + return ListInstancesRequest.newBuilder().setParent(projectName.toString()).build(); + } + + private static PartialUpdateInstanceRequest composePartialUpdateInstanceCallable( + Instance updatedInstance) { + return PartialUpdateInstanceRequest.newBuilder() + .setInstance(updatedInstance.toUpdateProto()) + .setUpdateMask(updatedInstance.getPartialUpdateFieldMask()) + .build(); + } + + private static DeleteInstanceRequest composeDeleteInstanceRequest(InstanceName instanceName) { + return DeleteInstanceRequest.newBuilder().setName(instanceName.toString()).build(); + } + + private static CreateClusterRequest composeCreateClusterRequest( + InstanceName instanceName, Cluster cluster) { + return CreateClusterRequest.newBuilder() + .setParent(instanceName.toString()) + .setClusterId(cluster.getId()) + .setCluster(cluster.toProto()) + .build(); + } + + private static GetClusterRequest composeGetClusterRequest(ClusterName clusterName) { + return GetClusterRequest.newBuilder().setName(clusterName.toString()).build(); + } + + private static ListClustersRequest composeListClustersRequest(InstanceName instanceName) { + return ListClustersRequest.newBuilder().setParent(instanceName.toString()).build(); + } + + private static DeleteClusterRequest composeDeleteClusterRequest(ClusterName clusterName) { + return DeleteClusterRequest.newBuilder().setName(clusterName.toString()).build(); + } + + private static GetAppProfileRequest composeGetAppProfileRequest(AppProfileName appProfileName) { + return GetAppProfileRequest.newBuilder().setName(appProfileName.toString()).build(); + } + + private static ListAppProfilesRequest composeListAppProfilesRequest(InstanceName instanceName) { + return ListAppProfilesRequest.newBuilder().setParent(instanceName.toString()).build(); + } + + private static UpdateAppProfileRequest composeUpdateAppProfileRequest(AppProfile appProfile) { + return UpdateAppProfileRequest.newBuilder() + .setAppProfile(appProfile.toUpdateProto()) + .setUpdateMask(appProfile.getPartialUpdateFieldMask()) + .build(); + } + + private static DeleteAppProfileRequest composeDeleteAppProfileRequest( + AppProfileName appProfileName, boolean ignoreWarnings) { + return DeleteAppProfileRequest.newBuilder() + .setName(appProfileName.toString()) + .setIgnoreWarnings(ignoreWarnings) + .build(); + } + + private static GetIamPolicyRequest composeGetIamPolicyRequest(InstanceName instanceName) { + return GetIamPolicyRequest.newBuilder().setResource(instanceName.toString()).build(); + } + + private static SetIamPolicyRequest composeSetIamPolicyRequest( + InstanceName instanceName, Policy policy) { + return SetIamPolicyRequest.newBuilder() + .setResource(instanceName.toString()) + .setPolicy(policy.toProto()) + .build(); + } + + private static TestIamPermissionsRequest composeTestIamPermissionsRequest( + InstanceName instanceName, List permissions) { + return TestIamPermissionsRequest.newBuilder() + .setResource(instanceName.toString()) + .addAllPermissions(permissions) + .build(); + } + + private static List convertToInstances(ListInstancesResponse listInstancesResponse) { + List instances = new ArrayList<>(); + + for (com.google.bigtable.admin.v2.Instance instance : + listInstancesResponse.getInstancesList()) { + instances.add(InstanceAdminRequests.convertToInstance(instance)); + } + // TODO: handle failed_locations + return instances; + } + + private static List convertToClusters(ListClustersResponse listClustersResponse) { + List clusters = new ArrayList<>(); + + for (com.google.bigtable.admin.v2.Cluster cluster : listClustersResponse.getClustersList()) { + clusters.add(InstanceAdminRequests.convertToCluster(cluster)); + } + + // TODO: Trying a simple approach to handle these for now + for (String failedLocation : listClustersResponse.getFailedLocationsList()) { + clusters.add(InstanceAdminRequests.convertToFailedCluster(failedLocation)); + } + return clusters; + } + + private static List convertToAppProfiles( + ListAppProfilesResponse listAppProfilesResponse) { + List appProfiles = new ArrayList<>(); + + for (com.google.bigtable.admin.v2.AppProfile profile : + listAppProfilesResponse.getAppProfilesList()) { + appProfiles.add(InstanceAdminRequests.convertToAppProfile(profile)); + } + return appProfiles; + } + + /** Can be removed after https://github.com/googleapis/gax-java/issues/552 is handled */ + private static ApiFuture transfromOperationFuture( + final OperationFuture future, + final ApiFunction function) { + final SettableApiFuture result = SettableApiFuture.create(); + future.addListener( + new Runnable() { + @Override + public void run() { + try { + result.set(function.apply(future.get())); + } catch (InterruptedException | ExecutionException e) { + result.setException(e); + } + } + }, + MoreExecutors.directExecutor()); + return result; + } +} diff --git a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/InstanceAdminRequests.java b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/InstanceAdminRequests.java new file mode 100644 index 000000000000..02b396aaf3fc --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/InstanceAdminRequests.java @@ -0,0 +1,563 @@ +package com.google.cloud.bigtable.admin.v2.models; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import com.google.api.core.BetaApi; +import com.google.api.core.InternalApi; +import com.google.bigtable.admin.v2.AppProfile.RoutingPolicyCase; +import com.google.bigtable.admin.v2.AppProfileName; +import com.google.bigtable.admin.v2.ClusterName; +import com.google.bigtable.admin.v2.CreateAppProfileRequest; +import com.google.bigtable.admin.v2.CreateInstanceRequest; +import com.google.bigtable.admin.v2.Instance.State; +import com.google.bigtable.admin.v2.Instance.Type; +import com.google.bigtable.admin.v2.InstanceName; +import com.google.bigtable.admin.v2.ProjectName; +import com.google.bigtable.admin.v2.StorageType; +import com.google.cloud.Role; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.iam.v1.Binding; +import com.google.protobuf.ByteString; +import com.google.protobuf.FieldMask; + +@BetaApi +public final class InstanceAdminRequests { + + public static CreateInstance createInstance( + ProjectName projectName, Instance instance, Cluster cluster) { + return new CreateInstance(projectName, instance, cluster); + } + + public static CreateAppProfile createAppProfile( + InstanceName instanceName, AppProfile appProfile, boolean ignoreWarnings) { + return new CreateAppProfile(instanceName, appProfile, ignoreWarnings); + } + + public static Instance convertToInstance(com.google.bigtable.admin.v2.Instance protoInstance) { + return new Instance(protoInstance); + } + + public static Cluster convertToCluster(com.google.bigtable.admin.v2.Cluster protoCluster) { + return new Cluster(protoCluster); + } + + public static Cluster convertToFailedCluster(String location) { + return new Cluster(location); + } + + public static AppProfile convertToAppProfile(com.google.bigtable.admin.v2.AppProfile appProfile) { + return new AppProfile(appProfile); + } + + public static Policy convertToPolicy(com.google.iam.v1.Policy policy) { + return new Policy(policy); + } + + /** */ + public static final class CreateInstance { + private final CreateInstanceRequest.Builder createInstanceRequest = + CreateInstanceRequest.newBuilder(); + + private CreateInstance(ProjectName projectName, Instance instance, Cluster cluster) { + Preconditions.checkNotNull(projectName); + Preconditions.checkNotNull(instance); + Preconditions.checkNotNull(cluster); + + createInstanceRequest + .setParent(projectName.toString()) + .setInstanceId(instance.getid()) + .setInstance(instance.toProto()) + .putClusters(cluster.getId(), cluster.toProto()); + } + + public CreateInstance addCluster(Cluster cluster) { + createInstanceRequest.putClusters(cluster.getId(), cluster.toProto()); + return this; + } + + public CreateInstanceRequest toProto() { + return createInstanceRequest.build(); + } + } + + public static final class Instance { + private final String DISPLAY_NAME_FIELDMASK = "display_name"; + private final String TYPE_FIELDMASK = "type"; + private final String LABELS_FIELDMASK = "labels"; + + private final String id; + private final List replacefields = new ArrayList<>(); + private com.google.bigtable.admin.v2.Instance.Builder protoInstance = + com.google.bigtable.admin.v2.Instance.newBuilder(); + + public static Instance of(String instanceId, String displayName, Type instanceType) { + return new Instance(instanceId, displayName, instanceType); + } + + private Instance(String instanceId, String displayName, Type instanceType) { + this.id = instanceId; + protoInstance.setDisplayName(displayName).setType(instanceType); + } + + private Instance(com.google.bigtable.admin.v2.Instance instance) { + this.protoInstance = instance.toBuilder(); + id = getName().getInstance(); + } + + public String getid() { + return id; + } + + public InstanceName getName() { + return InstanceName.parse(protoInstance.getName()); + } + + public String getDisplayName() { + return protoInstance.getDisplayName(); + } + + public State getState() { + return protoInstance.getState(); + } + + public Type getType() { + return protoInstance.getType(); + } + + public Map getLabelsMap() { + return protoInstance.getLabelsMap(); + } + + public Instance addLabel(String key, String value) { + // TODO: add an regex check. Error from is hard to decipher + protoInstance.putLabels(key, value); + return this; + } + + public Instance updateDisplayName(String updatedDisplayName) { + replacefields.add(DISPLAY_NAME_FIELDMASK); + protoInstance.setDisplayName(updatedDisplayName); + return this; + } + + public Instance upgradeType() { + Preconditions.checkArgument( + Type.DEVELOPMENT.equals(protoInstance.getType()), "PRODUCTION type cannot be upgraded"); + replacefields.add(TYPE_FIELDMASK); + protoInstance.setType(Type.PRODUCTION); + return this; + } + + public Instance updateLabels(Map updatedLabels) { + replacefields.add(LABELS_FIELDMASK); + protoInstance.putAllLabels(updatedLabels); + return this; + } + + @InternalApi + public com.google.bigtable.admin.v2.Instance toProto() { + return protoInstance.build(); + } + + @InternalApi + public com.google.bigtable.admin.v2.Instance toUpdateProto() { + return protoInstance.clone().clearState().build(); + } + + @InternalApi + public FieldMask getPartialUpdateFieldMask() { + return FieldMask.newBuilder().addAllPaths(replacefields).build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", getName()) + .add("displayName", getDisplayName()) + .add("state", getState()) + .add("type", getType()) + .add("labels", getLabelsMap()) + .toString(); + } + } + + public static final class Cluster { + public static Cluster ofProd( + String clusterId, Location location, StorageType defaultStorage, int serverNodes) { + return new Cluster(clusterId, location, defaultStorage, serverNodes); + } + + public static Cluster ofDev(String clusterId, Location location, StorageType defaultStorage) { + return new Cluster(clusterId, location, defaultStorage, 0); + } + + private final String id; + private com.google.bigtable.admin.v2.Cluster.Builder protoCluster = + com.google.bigtable.admin.v2.Cluster.newBuilder(); + + private Cluster( + String clusterId, Location location, StorageType defaultStorage, int serverNodes) { + protoCluster + .setLocation(location.toString()) + .setServeNodes(serverNodes) + .setDefaultStorageType(defaultStorage); + this.id = clusterId; + } + + private Cluster(String location) { + protoCluster.setLocation(location); + id = "failedlocation"; + } + + private Cluster(com.google.bigtable.admin.v2.Cluster cluster) { + protoCluster = cluster.toBuilder(); + id = getName().getCluster(); + } + + public String getId() { + return id; + } + + public ClusterName getName() { + return ClusterName.parse(protoCluster.getName()); + } + + public String getLocation() { + return protoCluster.getLocation(); + } + + public com.google.bigtable.admin.v2.Cluster.State getState() { + return protoCluster.getState(); + } + + public int getServerNodes() { + return protoCluster.getServeNodes(); + } + + public StorageType getDefaultStorageType() { + return protoCluster.getDefaultStorageType(); + } + + public Cluster updateNumNodes(int serverNodes) { + protoCluster.setServeNodes(serverNodes); + return this; + } + + @InternalApi + public com.google.bigtable.admin.v2.Cluster toProto() { + return protoCluster.build(); + } + + @InternalApi + public com.google.bigtable.admin.v2.Cluster toUpdateProto() { + return protoCluster.clone().clearState().clearDefaultStorageType().build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", getName()) + .add("location", getLocation()) + .add("state", getState()) + .add("serverNodes", getServerNodes()) + .add("defaultStorageType", getDefaultStorageType()) + .toString(); + } + } + + public static final class CreateAppProfile { + private final CreateAppProfileRequest.Builder createAppProfRequest = + CreateAppProfileRequest.newBuilder(); + + private CreateAppProfile( + InstanceName instanceName, AppProfile appProfile, boolean ignoreWarnings) { + createAppProfRequest + .setParent(instanceName.toString()) + .setAppProfileId(appProfile.getId()) + .setAppProfile(appProfile.toProto()) + .setIgnoreWarnings(ignoreWarnings); + } + + public CreateAppProfileRequest toProto() { + return createAppProfRequest.build(); + } + } + + public static final class AppProfile { + private static final String DESCRIPTION_FIELDMASK = "description"; + private static final String MULTI_CLUSTER_FIELDMASK = "multi_cluster_routing_use_any"; + private static final String SINGLE_CLUSTER__FIELDMASK = "single_cluster_routing"; + + private final String id; + private final List replacefields = new ArrayList<>(); + private com.google.bigtable.admin.v2.AppProfile.Builder protoProfile = + com.google.bigtable.admin.v2.AppProfile.newBuilder(); + + public static AppProfile of(String profileId, RoutingPolicy routingPolicy) { + return new AppProfile(profileId, routingPolicy); + } + + private AppProfile(String profileId, RoutingPolicy routingPolicy) { + Preconditions.checkNotNull(routingPolicy); + id = profileId; + setRoutingPolicy(routingPolicy); + } + + private AppProfile(com.google.bigtable.admin.v2.AppProfile appProfile) { + protoProfile = appProfile.toBuilder(); + id = getName().getAppProfile(); + } + + private void setRoutingPolicy(RoutingPolicy routingPolicy) { + if (RoutingPolicyCase.MULTI_CLUSTER_ROUTING_USE_ANY.equals(routingPolicy.name())) { + protoProfile.setMultiClusterRoutingUseAny( + com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny.newBuilder().build()); + protoProfile.clearSingleClusterRouting(); + replacefields.add(MULTI_CLUSTER_FIELDMASK); + } + + if (RoutingPolicyCase.SINGLE_CLUSTER_ROUTING.equals(routingPolicy.name())) { + protoProfile.setSingleClusterRouting( + com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting.newBuilder() + .setClusterId(((SingleClusterRouting) routingPolicy).clusterId) + .setAllowTransactionalWrites( + ((SingleClusterRouting) routingPolicy).allowTransactionalWrites)); + protoProfile.clearMultiClusterRoutingUseAny(); + replacefields.add(SINGLE_CLUSTER__FIELDMASK); + } + } + + public String getId() { + return id; + } + + public AppProfile setDescription(String description) { + protoProfile.setDescription(description); + return this; + } + + public AppProfileName getName() { + return AppProfileName.parse(protoProfile.getName()); + } + + public String getEtag() { + return protoProfile.getEtag(); + } + + public String getDescription() { + return protoProfile.getDescription(); + } + + public RoutingPolicy getRoutingPolicy() { + if (RoutingPolicyCase.MULTI_CLUSTER_ROUTING_USE_ANY.equals( + protoProfile.getRoutingPolicyCase().name())) { + return new MultiClusterRoutingUseAny(); + } + + if (RoutingPolicyCase.SINGLE_CLUSTER_ROUTING.equals( + protoProfile.getRoutingPolicyCase().name())) { + return new SingleClusterRouting(protoProfile.getSingleClusterRouting()); + } + + return new RoutingPolicyNotSet(); + } + + public AppProfile updateDescription(String updatedDescription) { + replacefields.add(DESCRIPTION_FIELDMASK); + protoProfile.setDescription(updatedDescription); + return this; + } + + public AppProfile updateRoutingPolicy(RoutingPolicy routingPolicy) { + setRoutingPolicy(routingPolicy); + return this; + } + + @InternalApi + public com.google.bigtable.admin.v2.AppProfile toProto() { + return protoProfile.build(); + } + + @InternalApi + public com.google.bigtable.admin.v2.AppProfile toUpdateProto() { + return protoProfile.clone().build(); + } + + @InternalApi + public FieldMask getPartialUpdateFieldMask() { + return FieldMask.newBuilder().addAllPaths(replacefields).build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", getName()) + .add("etag", getEtag()) + .add("description", getDescription()) + .add("routingPolicy", getRoutingPolicy()) + .toString(); + } + + public interface RoutingPolicy { + RoutingPolicyCase name(); + } + + public static class RoutingPolicyNotSet implements RoutingPolicy { + private RoutingPolicyNotSet() {} + + @Override + public RoutingPolicyCase name() { + return RoutingPolicyCase.ROUTINGPOLICY_NOT_SET; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("name", name()).toString(); + } + } + + public static class MultiClusterRoutingUseAny implements RoutingPolicy { + public static MultiClusterRoutingUseAny of() { + return new MultiClusterRoutingUseAny(); + } + + private MultiClusterRoutingUseAny() {} + + @Override + public RoutingPolicyCase name() { + return RoutingPolicyCase.MULTI_CLUSTER_ROUTING_USE_ANY; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("name", name()).toString(); + } + } + + public static class SingleClusterRouting implements RoutingPolicy { + private final String clusterId; + private final boolean allowTransactionalWrites; + + public static SingleClusterRouting of(String clusterId, boolean allowTransactionalWrites) { + return new SingleClusterRouting(clusterId, allowTransactionalWrites); + } + + private SingleClusterRouting(String clusterId, boolean allowTransactionalWrites) { + this.clusterId = clusterId; + this.allowTransactionalWrites = allowTransactionalWrites; + } + + private SingleClusterRouting( + com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting routing) { + this.clusterId = routing.getClusterId(); + this.allowTransactionalWrites = routing.getAllowTransactionalWrites(); + } + + public String getClusterId() { + return clusterId; + } + + public boolean isAllowTransactionalWrites() { + return allowTransactionalWrites; + } + + @Override + public RoutingPolicyCase name() { + return RoutingPolicyCase.SINGLE_CLUSTER_ROUTING; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", name()) + .add("clusterId", getClusterId()) + .add("allowTransactionalWrites", isAllowTransactionalWrites()) + .toString(); + } + } + } + + public static final class Policy { + private com.google.iam.v1.Policy.Builder protoPolicy = com.google.iam.v1.Policy.newBuilder(); + + public static Policy of(int version, Role role, List members) { + return new Policy(version, role, members); + } + + private Policy(int version, Role role, List members) { + Preconditions.checkNotNull(role); + Preconditions.checkNotNull(members); + + protoPolicy.setVersion(version); + addRole(role, members); + } + + private Policy(com.google.iam.v1.Policy policy) { + protoPolicy = policy.toBuilder(); + } + + public Policy addRole(Role role, List members) { + Preconditions.checkNotNull(role); + Preconditions.checkNotNull(members); + + protoPolicy.addBindings( + com.google.iam.v1.Binding.newBuilder().setRole(role.toString()).addAllMembers(members)); + return this; + } + + public int getVersion() { + return protoPolicy.getVersion(); + } + + public ByteString getEtag() { + return protoPolicy.getEtag(); + } + + public Map> getBindingsMap() { + Map> bindings = new HashMap<>(); + + for (Binding binding : protoPolicy.getBindingsList()) { + bindings.put(Role.of(binding.getRole()), binding.getMembersList()); + } + return bindings; + } + + @InternalApi + public com.google.iam.v1.Policy toProto() { + return protoPolicy.build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("version", getVersion()) + .add("etag", getEtag()) + .add("bindingsMap", getBindingsMap()) + .toString(); + } + } + + public static final class Location { + public static Location of(ProjectName projectName, String zone) { + return new Location(projectName, zone); + } + + private final String location; + + private Location(ProjectName projectName, String zone) { + Preconditions.checkNotNull(projectName); + Preconditions.checkNotNull(zone); + + location = + new StringBuilder(projectName.toString()).append("/locations/").append(zone).toString(); + } + + @Override + public String toString() { + return location; + } + } +} diff --git a/google-cloud-clients/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/InstanceAdminClientIT.java b/google-cloud-clients/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/InstanceAdminClientIT.java new file mode 100644 index 000000000000..d2175148cd4f --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/InstanceAdminClientIT.java @@ -0,0 +1,359 @@ +package com.google.cloud.bigtable.admin.v2.it; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import com.google.bigtable.admin.v2.AppProfileName; +import com.google.bigtable.admin.v2.ClusterName; +import com.google.bigtable.admin.v2.Instance.State; +import com.google.bigtable.admin.v2.Instance.Type; +import com.google.bigtable.admin.v2.InstanceName; +import com.google.bigtable.admin.v2.ProjectName; +import com.google.bigtable.admin.v2.StorageType; +import com.google.cloud.bigtable.admin.v2.InstanceAdminClient; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.AppProfile; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.AppProfile.MultiClusterRoutingUseAny; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Cluster; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Instance; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Location; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Policy; +import com.google.common.collect.ImmutableMap; + +public class InstanceAdminClientIT { + private static InstanceAdminClient instanceAdmin; + private static final ProjectName TEST_PROJECT = ProjectName.of("sduskis-hello-shakespear"); + private static final String TEST_PROD_INST_ID = "instadmprodtest"; + private static final String TEST_DEV_INST_ID = "instadmdevtest"; + private static final int PROD_CLUSTER_SIZE = 3; + + @BeforeClass + public static void createClient() throws Exception { + instanceAdmin = InstanceAdminClient.create(); + } + + @AfterClass + public static void closeClient() throws Exception { + instanceAdmin.close(); + } + + @Test + public void createInstanceHarness() throws Exception { + Instance rawinstance = + InstanceAdminRequests.Instance.of( + TEST_PROD_INST_ID, TEST_PROD_INST_ID + "disp", Type.PRODUCTION); + + Cluster rawcluster = + InstanceAdminRequests.Cluster.ofProd( + TEST_PROD_INST_ID + "us-east1-c", + Location.of(TEST_PROJECT, "us-east1-c"), + StorageType.HDD, + PROD_CLUSTER_SIZE); + + try { + // Instance tests + int numInstances = instanceAdmin.listInstances(TEST_PROJECT).size(); + Instance actualInstance = createInstanceAsync(TEST_PROJECT, rawinstance, rawcluster); + listInstances(numInstances + 1); + getInstance(actualInstance); + updateInstance(actualInstance); + partialUpdateInstance(actualInstance); + + // Cluster tests + getClusterFromRaw(actualInstance.getName(), rawcluster); + listClusters(actualInstance.getName(), 1); + + Exception cannotMixClusterType = null; + try { + createCluster(actualInstance, "us-east1-d", Type.DEVELOPMENT); + } catch (Exception ex) { + cannotMixClusterType = ex; + } + assertNotNull(cannotMixClusterType); + + Cluster actualCluster2 = createCluster(actualInstance, "us-east1-d", Type.PRODUCTION); + getCluster(actualCluster2); + updateCluster(actualCluster2); + listClusters(actualInstance.getName(), 2); + deleteCluster(actualCluster2); + listClusters(actualInstance.getName(), 1); + + // AppProfile tests + AppProfile rawMulti = AppProfile.of("roundRobin", MultiClusterRoutingUseAny.of()); + AppProfile actualMulti = createAppProfile(actualInstance.getName(), rawMulti); + getAppProfile(actualMulti); + updateAppProfileSwitchToSingle(actualMulti, rawcluster.getId()); + listAppProfiles(actualInstance.getName(), 2); // +1 for default appProfile + deleteAppProfile(actualMulti.getName()); + + // IamPolicy tests + // TODO: Needs Iam permissions to test this. Doesn't look like I have them + // Policy rawPolicy = Policy.of(1, Role.owner(), + // Arrays.asList("user:spollaplly@udbhavinc.com")); + // Policy actualPolicy = instanceAdmin.setIamPolicy(actualInstance.getName(), rawPolicy); + + Policy iamPolicy = instanceAdmin.getIamPolicy(actualInstance.getName()); + assertNotNull(iamPolicy); + + List actualPermissions = + instanceAdmin.testIamPermissions( + actualInstance.getName(), Arrays.asList("bigtable.tables.checkConsistency")); + assertEquals(Arrays.asList("bigtable.tables.checkConsistency"), actualPermissions); + } finally { + instanceAdmin.deleteInstanceRequest( + InstanceName.of(TEST_PROJECT.getProject(), TEST_PROD_INST_ID)); + } + } + + @Test + public void createInstanceUpgradeHarness() throws Exception { + Instance rawinstance = + InstanceAdminRequests.Instance.of( + TEST_DEV_INST_ID, TEST_DEV_INST_ID + "disp", Type.DEVELOPMENT) + .addLabel("label_name_1", "label_value_1") + .addLabel("label_name_2", "label_value_2"); + + Cluster rawcluster1 = + InstanceAdminRequests.Cluster.ofDev( + TEST_DEV_INST_ID + "us-east1-c", + Location.of(TEST_PROJECT, "us-east1-c"), + StorageType.HDD); + /* + * Cluster rawcluster2 = InstanceAdminRequests.Cluster.ofDev(TEST_DEV_INST_ID + "us-east1-b", + * Location.of(TEST_PROJECT, "us-east1-b"), StorageType.HDD); + */ + + try { + Instance actualInstance = + instanceAdmin + .createInstanceAsync( + InstanceAdminRequests.createInstance(TEST_PROJECT, rawinstance, rawcluster1) + // TODO: Test fails with instance not found. Verify if more than one cluster on + // creation is + // a valid case + // .addCluster(rawcluster2) + ) + .get(); + assertInstanceEquals(rawinstance, actualInstance); + + listClusters(actualInstance.getName(), 1); + getClusterFromRaw(actualInstance.getName(), rawcluster1); + // getClusterFromRaw(actualInstance.getName(), rawcluster2); + + Instance upgradedInstance = instanceAdmin.updateInstance(actualInstance.upgradeType()).get(); + assertEquals(Type.PRODUCTION, upgradedInstance.getType()); + } finally { + instanceAdmin.deleteInstanceRequest( + InstanceName.of(TEST_PROJECT.getProject(), TEST_DEV_INST_ID)); + } + } + + @Test + public void iamPolicyHarness() throws Exception { + Instance rawinstance = + InstanceAdminRequests.Instance.of( + TEST_PROD_INST_ID, TEST_PROD_INST_ID + "disp", Type.PRODUCTION); + + Cluster rawcluster = + InstanceAdminRequests.Cluster.ofProd( + TEST_PROD_INST_ID + "us-east1-c", + Location.of(TEST_PROJECT, "us-east1-c"), + StorageType.HDD, + PROD_CLUSTER_SIZE); + + try { + Instance actualInstance = createInstanceAsync(TEST_PROJECT, rawinstance, rawcluster); + + // TODO: Needs Iam permissions to test this. Doesn't look like I have them + // Policy rawPolicy = Policy.of(1, Role.owner(), + // Arrays.asList("user:spollaplly@udbhavinc.com")); + // Policy actualPolicy = instanceAdmin.setIamPolicy(actualInstance.getName(), rawPolicy); + + Policy iamPolicy = instanceAdmin.getIamPolicy(actualInstance.getName()); + assertNotNull(iamPolicy); + + List actualPermissions = + instanceAdmin.testIamPermissions( + actualInstance.getName(), Arrays.asList("bigtable.tables.checkConsistency")); + assertEquals(Arrays.asList("bigtable.tables.checkConsistency"), actualPermissions); + } finally { + instanceAdmin.deleteInstanceRequest( + InstanceName.of(TEST_PROJECT.getProject(), TEST_PROD_INST_ID)); + } + } + + private Instance createInstanceAsync( + ProjectName projectName, Instance rawinstance, Cluster rawcluster) throws Exception { + Instance actualInstance = + instanceAdmin + .createInstanceAsync( + InstanceAdminRequests.createInstance(projectName, rawinstance, rawcluster)) + .get(); + assertInstanceEquals(rawinstance, actualInstance); + return actualInstance; + } + + private void getInstance(Instance expected) { + Instance actual = instanceAdmin.getInstance(expected.getName()); + assertThat(actual).isEqualTo(actual); + } + + private void updateInstance(Instance instance) throws Exception { + Map updatedLabels = ImmutableMap.of("team", "team1", "subteam", "subteam1"); + + Instance updatedInstance = + instanceAdmin + .updateInstance( + instance + .updateDisplayName(TEST_DEV_INST_ID + "upddisp") + .updateLabels(updatedLabels)) + .get(); + + assertEquals(TEST_DEV_INST_ID + "upddisp", updatedInstance.getDisplayName()); + assertEquals(updatedLabels, updatedInstance.getLabelsMap()); + } + + private void partialUpdateInstance(Instance instance) throws Exception { + Instance updatedInstance = + instanceAdmin.updateInstance(instance.updateDisplayName(TEST_PROD_INST_ID + "disp")).get(); + + assertEquals(TEST_PROD_INST_ID + "disp", updatedInstance.getDisplayName()); + assertEquals(instance.getLabelsMap(), updatedInstance.getLabelsMap()); + } + + private void getClusterFromRaw(InstanceName instanceName, Cluster raw) { + ClusterName clusterName = + ClusterName.of(instanceName.getProject(), instanceName.getInstance(), raw.getId()); + Cluster actual = instanceAdmin.getCluster(clusterName); + assertClusterEquals(raw, actual, clusterName); + } + + private Cluster createCluster(Instance instance, String zone, Type type) throws Exception { + Cluster raw; + + if (type.equals(Type.PRODUCTION)) { + raw = + Cluster.ofProd( + instance.getid() + zone, + Location.of(TEST_PROJECT, zone), + StorageType.HDD, + PROD_CLUSTER_SIZE); + } else { + raw = + Cluster.ofDev(instance.getid() + zone, Location.of(TEST_PROJECT, zone), StorageType.HDD); + } + + Cluster actual = instanceAdmin.createCluster(instance.getName(), raw).get(); + assertClusterEquals( + raw, + actual, + ClusterName.of( + instance.getName().getProject(), instance.getName().getInstance(), raw.getId())); + return actual; + } + + private void getCluster(Cluster expected) { + Cluster actual = instanceAdmin.getCluster(expected.getName()); + assertClusterEquals(expected, actual, expected.getName()); + } + + private void updateCluster(Cluster cluster) throws Exception { + Cluster updatedCluster = + instanceAdmin.updateCluster(cluster.updateNumNodes(PROD_CLUSTER_SIZE + 1)).get(); + assertEquals(cluster.getServerNodes(), updatedCluster.getServerNodes()); + } + + private void deleteCluster(Cluster cluster) { + instanceAdmin.deleteCluster(cluster.getName()); + } + + private void listInstances(int expectedSize) { + assertEquals(expectedSize, instanceAdmin.listInstances(TEST_PROJECT).size()); + } + + private void listClusters(InstanceName instanceName, int expectedSize) { + assertEquals(expectedSize, instanceAdmin.listClusters(instanceName).size()); + } + + private AppProfile createAppProfile(InstanceName instanceName, AppProfile rawProfile) { + AppProfile actual = + instanceAdmin.createAppProfile( + InstanceAdminRequests.createAppProfile(instanceName, rawProfile, true)); + assertAppProfileEquals( + rawProfile, + actual, + AppProfileName.of(TEST_PROJECT.getProject(), TEST_PROD_INST_ID, rawProfile.getId())); + return actual; + } + + private void getAppProfile(AppProfile expected) { + AppProfile actual = instanceAdmin.getAppProfile(expected.getName()); + assertAppProfileEquals(expected, actual, expected.getName()); + } + + private void listAppProfiles(InstanceName instanceName, int expectedSize) { + assertEquals(expectedSize, instanceAdmin.listAppProfiles(instanceName).size()); + } + + private void updateAppProfileSwitchToSingle(AppProfile original, String singleClusterId) + throws Exception { + // SingleClusterRouting singlePolicy = SingleClusterRouting.of(singleClusterId, true); + AppProfile updated = + instanceAdmin + .updateAppProfile( + original.updateDescription("newDescription") + // TODO fix policy switch failing test + // .updateRoutingPolicy(singlePolicy)) + ) + .get(); + + assertEquals("newDescription", updated.getDescription()); + // assertEquals(singlePolicy.toString(), updated.getRoutingPolicy().toString()); + } + + private void deleteAppProfile(AppProfileName appProfileName) { + instanceAdmin.deleteAppProfile(appProfileName, true); + + Exception ensureDelete = null; + try { + instanceAdmin.getAppProfile(appProfileName); + } catch (Exception e) { + ensureDelete = e; + } + assertNotNull(ensureDelete); + } + + private static void assertInstanceEquals(Instance exptected, Instance actual) { + assertEquals(InstanceName.of(TEST_PROJECT.getProject(), exptected.getid()), actual.getName()); + assertEquals(State.READY, actual.getState()); + + assertEquals(actual.getDisplayName(), actual.getDisplayName()); + assertEquals(actual.getType(), actual.getType()); + assertEquals(actual.getLabelsMap(), actual.getLabelsMap()); + } + + private void assertClusterEquals(Cluster exptected, Cluster actual, ClusterName expectedName) { + assertEquals(com.google.bigtable.admin.v2.Cluster.State.READY, actual.getState()); + assertEquals(expectedName, actual.getName()); + + assertEquals(exptected.getLocation(), actual.getLocation()); + assertEquals(exptected.getServerNodes(), actual.getServerNodes()); + assertEquals(exptected.getDefaultStorageType(), actual.getDefaultStorageType()); + } + + private void assertAppProfileEquals( + AppProfile exptected, AppProfile actual, AppProfileName expectedName) { + assertEquals(expectedName, actual.getName()); + + assertEquals(exptected.getId(), actual.getId()); + assertEquals(exptected.getEtag(), actual.getEtag()); + assertEquals(exptected.getDescription(), actual.getDescription()); + assertEquals(exptected.getRoutingPolicy().toString(), actual.getRoutingPolicy().toString()); + } +} From f5ec5c406e1838900bfed7f6730f426b8d06ec9b Mon Sep 17 00:00:00 2001 From: spollapally Date: Mon, 2 Jul 2018 23:05:19 -0400 Subject: [PATCH 2/2] changes to DSL model objects --- .../admin/v2/InstanceAdminClient.java | 247 +++++++++----- .../v2/models/FailedLocationException.java | 26 ++ .../v2/models/InstanceAdminRequests.java | 318 ++++++++++-------- .../admin/v2/it/InstanceAdminClientIT.java | 264 +++++++-------- 4 files changed, 495 insertions(+), 360 deletions(-) create mode 100644 google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/FailedLocationException.java diff --git a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/InstanceAdminClient.java b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/InstanceAdminClient.java index a2d804d746f1..72ed4aaba45d 100644 --- a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/InstanceAdminClient.java +++ b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/InstanceAdminClient.java @@ -11,6 +11,7 @@ import com.google.api.gax.longrunning.OperationFuture; import com.google.bigtable.admin.v2.AppProfileName; import com.google.bigtable.admin.v2.ClusterName; +import com.google.bigtable.admin.v2.CreateAppProfileRequest; import com.google.bigtable.admin.v2.CreateClusterMetadata; import com.google.bigtable.admin.v2.CreateClusterRequest; import com.google.bigtable.admin.v2.CreateInstanceMetadata; @@ -33,13 +34,16 @@ import com.google.bigtable.admin.v2.UpdateAppProfileRequest; import com.google.bigtable.admin.v2.UpdateClusterMetadata; import com.google.bigtable.admin.v2.UpdateInstanceMetadata; +import com.google.cloud.bigtable.admin.v2.models.FailedLocationException; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.AppProfile; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.AppProfile.UpdateAppProfile; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Cluster; -import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.CreateAppProfile; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.CreateInstance; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Instance; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Policy; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.UpdateCluster; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.UpdateInstance; import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub; import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStubSettings; import com.google.common.util.concurrent.MoreExecutors; @@ -77,13 +81,34 @@ public void close() throws Exception { stub.close(); } - /** Discuss: need for CreateInstance wrapper */ + /** + * + *
+   * {@code 
+   * try(InstanceAdminClient instanceAdmin = InstanceAdminClient.create()) {
+   *   CreateInstance request =
+   *     InstanceAdminRequests.createInstance(
+   *         ProjectName.of("project"),
+   *         Instance.ofNewProdInstance("instanceid", "displayname"),
+   *         Cluster.ofNewProdCluster(
+   *           "clusterone", Location.of("project", "zone"), 3))
+   *       .addCluster(
+   *         Cluster.ofNewProdCluster(
+   *           "clustertwo", Location.of("project", "us-east1-c"), 4));
+   *
+   *    Instance createdInstance = instanceAdmin.createInstanceAsync(request).get();
+   * }
+   * }
+   * 
+ * + * @param createInstance + * @return + */ public ApiFuture createInstanceAsync(CreateInstance createInstance) { final OperationFuture future = stub.createInstanceOperationCallable().futureCall(createInstance.toProto()); - return transfromOperationFuture( - future, + return transfromOperationFuture(future, new ApiFunction() { @Override public Instance apply(com.google.bigtable.admin.v2.Instance input) { @@ -102,13 +127,32 @@ public List listInstances(ProjectName projectName) { stub.listInstancesCallable().call(composeListInstanceRequest(projectName))); } - public ApiFuture updateInstance(Instance updatedInstance) { + /** + * + *
+   * {@code 
+   * try(InstanceAdminClient instanceAdmin = InstanceAdminClient.create()) {
+   *    Instance devInstance = instanceAdmin.getInstance(
+   *        InstanceName.of("project", "instance"));
+   *    
+   *    instanceAdmin.updateInstance(
+   *      Instance.ofUpdateInstance(devInstance)
+   *        .updateDisplayName("display")
+   *        .upgradeType()
+   *        .updateLabels(updatedLabels));
+   * }
+   * }
+   * 
+ * + * @param updatedInstance + * @return + */ + public ApiFuture updateInstance(UpdateInstance updatedInstance) { OperationFuture future = stub.partialUpdateInstanceOperationCallable() .futureCall(composePartialUpdateInstanceCallable(updatedInstance)); - return transfromOperationFuture( - future, + return transfromOperationFuture(future, new ApiFunction() { @Override public Instance apply(com.google.bigtable.admin.v2.Instance input) { @@ -126,8 +170,7 @@ public ApiFuture createCluster(InstanceName instanceName, Cluster clust stub.createClusterOperationCallable() .futureCall(composeCreateClusterRequest(instanceName, cluster)); - return transfromOperationFuture( - future, + return transfromOperationFuture(future, new ApiFunction() { @Override public Cluster apply(com.google.bigtable.admin.v2.Cluster input) { @@ -146,12 +189,29 @@ public List listClusters(InstanceName instanceName) { stub.listClustersCallable().call(composeListClustersRequest(instanceName))); } - public ApiFuture updateCluster(Cluster updatedCluster) { + /** + * + *
+   * {@code 
+   * try(InstanceAdminClient instanceAdmin = InstanceAdminClient.create()) {
+   *   Cluster prodCluster = instanceAdmin.getCluster(
+   *     ClusterName.of("project", "instance", "cluster"));
+   *    
+   *   instanceAdmin.updateCluster(
+   *     Cluster.ofUpdateCluster(prodCluster)
+   *       .updateNumNodes(5));
+   * }
+   * }
+   * 
+ * + * @param updatedCluster + * @return + */ + public ApiFuture updateCluster(UpdateCluster updatedCluster) { OperationFuture future = - stub.updateClusterOperationCallable().futureCall(updatedCluster.toUpdateProto()); + stub.updateClusterOperationCallable().futureCall(updatedCluster.toProto()); - return transfromOperationFuture( - future, + return transfromOperationFuture(future, new ApiFunction() { @Override public Cluster apply(com.google.bigtable.admin.v2.Cluster input) { @@ -164,10 +224,26 @@ public void deleteCluster(ClusterName clusterName) { stub.deleteClusterCallable().call(composeDeleteClusterRequest(clusterName)); } - /** Discuss: need for CreateAppProfile wrapper */ - public AppProfile createAppProfile(CreateAppProfile createAppProfile) { - return InstanceAdminRequests.convertToAppProfile( - stub.createAppProfileCallable().call(createAppProfile.toProto())); + /** + * + *
+   * {@code 
+   * try(InstanceAdminClient instanceAdmin = InstanceAdminClient.create()) {
+   *   instanceAdmin.createAppProfile(
+   *     InstanceName.of("project", "instance"),
+   *     AppProfile.ofNewAppProfile("roundRobin")
+   *       .routeToAny());
+   * }
+   * }
+   * 
+ * + * @param instanceName + * @param appProfile + * @return + */ + public AppProfile createAppProfile(InstanceName instanceName, AppProfile appProfile) { + return InstanceAdminRequests.convertToAppProfile(stub.createAppProfileCallable().call( + composeCreateAppProfileRequest(instanceName, appProfile))); } public AppProfile getAppProfile(AppProfileName appProfileName) { @@ -180,13 +256,32 @@ public List listAppProfiles(InstanceName instanceName) { stub.listAppProfilesCallable().call(composeListAppProfilesRequest(instanceName))); } - public ApiFuture updateAppProfile(AppProfile appProfile) { + /** + * + *
+   * {@code 
+   * try(InstanceAdminClient instanceAdmin = InstanceAdminClient.create()) {
+   *   AppProfile appProfileAny = instanceAdmin.getAppProfile(
+   *       AppProfileName.of("project", "instance", "profile"));
+   *   
+   *   AppProfile appProfileCluster = instanceAdmin.updateAppProfile(
+   *       AppProfile.ofUpdateAppProfile(appProfileAny)
+   *         .updateDescription("newDescription")
+   *         .updateRouteToCluster("clusterToUse", false))
+   *         .get();
+   * }
+   * }
+   * 
+ * + * @param updateAppProfile + * @return + */ + public ApiFuture updateAppProfile(UpdateAppProfile updateAppProfile) { OperationFuture future = stub.updateAppProfileOperationCallable() - .futureCall(composeUpdateAppProfileRequest(appProfile)); + .futureCall(composeUpdateAppProfileRequest(updateAppProfile)); - return transfromOperationFuture( - future, + return transfromOperationFuture(future, new ApiFunction() { @Override public AppProfile apply(com.google.bigtable.admin.v2.AppProfile input) { @@ -212,8 +307,8 @@ public Policy setIamPolicy(InstanceName instanceName, Policy policy) { public List testIamPermissions(InstanceName instanceName, List permissions) { return stub.testIamPermissionsCallable() - .call(composeTestIamPermissionsRequest(instanceName, permissions)) - .getPermissionsList(); + .call(composeTestIamPermissionsRequest(instanceName, permissions)) + .getPermissionsList(); } /** compose proto request helpers * */ @@ -226,24 +321,20 @@ private static ListInstancesRequest composeListInstanceRequest(ProjectName proje } private static PartialUpdateInstanceRequest composePartialUpdateInstanceCallable( - Instance updatedInstance) { - return PartialUpdateInstanceRequest.newBuilder() - .setInstance(updatedInstance.toUpdateProto()) - .setUpdateMask(updatedInstance.getPartialUpdateFieldMask()) - .build(); + UpdateInstance updatedInstance) { + return PartialUpdateInstanceRequest.newBuilder().setInstance(updatedInstance.toProto()) + .setUpdateMask(updatedInstance.getPartialUpdateFieldMask()) + .build(); } private static DeleteInstanceRequest composeDeleteInstanceRequest(InstanceName instanceName) { return DeleteInstanceRequest.newBuilder().setName(instanceName.toString()).build(); } - private static CreateClusterRequest composeCreateClusterRequest( - InstanceName instanceName, Cluster cluster) { - return CreateClusterRequest.newBuilder() - .setParent(instanceName.toString()) - .setClusterId(cluster.getId()) - .setCluster(cluster.toProto()) - .build(); + private static CreateClusterRequest composeCreateClusterRequest(InstanceName instanceName, + Cluster cluster) { + return CreateClusterRequest.newBuilder().setParent(instanceName.toString()) + .setClusterId(cluster.getId()).setCluster(cluster.toProto()).build(); } private static GetClusterRequest composeGetClusterRequest(ClusterName clusterName) { @@ -258,6 +349,13 @@ private static DeleteClusterRequest composeDeleteClusterRequest(ClusterName clus return DeleteClusterRequest.newBuilder().setName(clusterName.toString()).build(); } + private static CreateAppProfileRequest composeCreateAppProfileRequest(InstanceName instanceName, + AppProfile appProfile) { + return CreateAppProfileRequest.newBuilder().setParent(instanceName.toString()) + .setAppProfileId(appProfile.getId()) + .setAppProfile(appProfile.toProto()).build(); + } + private static GetAppProfileRequest composeGetAppProfileRequest(AppProfileName appProfileName) { return GetAppProfileRequest.newBuilder().setName(appProfileName.toString()).build(); } @@ -266,63 +364,63 @@ private static ListAppProfilesRequest composeListAppProfilesRequest(InstanceName return ListAppProfilesRequest.newBuilder().setParent(instanceName.toString()).build(); } - private static UpdateAppProfileRequest composeUpdateAppProfileRequest(AppProfile appProfile) { - return UpdateAppProfileRequest.newBuilder() - .setAppProfile(appProfile.toUpdateProto()) - .setUpdateMask(appProfile.getPartialUpdateFieldMask()) - .build(); + private static UpdateAppProfileRequest composeUpdateAppProfileRequest( + UpdateAppProfile updateAppProfile) { + return UpdateAppProfileRequest.newBuilder().setAppProfile(updateAppProfile.toProto()) + .setUpdateMask(updateAppProfile.getPartialUpdateFieldMask()) + .build(); } private static DeleteAppProfileRequest composeDeleteAppProfileRequest( AppProfileName appProfileName, boolean ignoreWarnings) { - return DeleteAppProfileRequest.newBuilder() - .setName(appProfileName.toString()) - .setIgnoreWarnings(ignoreWarnings) - .build(); + return DeleteAppProfileRequest.newBuilder().setName(appProfileName.toString()) + .setIgnoreWarnings(ignoreWarnings).build(); } private static GetIamPolicyRequest composeGetIamPolicyRequest(InstanceName instanceName) { return GetIamPolicyRequest.newBuilder().setResource(instanceName.toString()).build(); } - private static SetIamPolicyRequest composeSetIamPolicyRequest( - InstanceName instanceName, Policy policy) { - return SetIamPolicyRequest.newBuilder() - .setResource(instanceName.toString()) - .setPolicy(policy.toProto()) - .build(); + private static SetIamPolicyRequest composeSetIamPolicyRequest(InstanceName instanceName, + Policy policy) { + return SetIamPolicyRequest.newBuilder().setResource(instanceName.toString()) + .setPolicy(policy.toProto()).build(); } private static TestIamPermissionsRequest composeTestIamPermissionsRequest( InstanceName instanceName, List permissions) { - return TestIamPermissionsRequest.newBuilder() - .setResource(instanceName.toString()) - .addAllPermissions(permissions) - .build(); + return TestIamPermissionsRequest.newBuilder().setResource(instanceName.toString()) + .addAllPermissions(permissions).build(); } private static List convertToInstances(ListInstancesResponse listInstancesResponse) { List instances = new ArrayList<>(); - - for (com.google.bigtable.admin.v2.Instance instance : - listInstancesResponse.getInstancesList()) { + List succeededLocations = new ArrayList<>(); + for (com.google.bigtable.admin.v2.Instance instance : listInstancesResponse.getInstancesList()) { instances.add(InstanceAdminRequests.convertToInstance(instance)); } - // TODO: handle failed_locations + + if (listInstancesResponse.getFailedLocationsList().size() > 0) { + throw new FailedLocationException("Failed to list all locations", succeededLocations, + listInstancesResponse.getFailedLocationsList()); + } + return instances; } private static List convertToClusters(ListClustersResponse listClustersResponse) { List clusters = new ArrayList<>(); - + List succeededLocations = new ArrayList<>(); for (com.google.bigtable.admin.v2.Cluster cluster : listClustersResponse.getClustersList()) { clusters.add(InstanceAdminRequests.convertToCluster(cluster)); + succeededLocations.add(cluster.getLocation()); } - // TODO: Trying a simple approach to handle these for now - for (String failedLocation : listClustersResponse.getFailedLocationsList()) { - clusters.add(InstanceAdminRequests.convertToFailedCluster(failedLocation)); + if (listClustersResponse.getFailedLocationsList().size() > 0) { + throw new FailedLocationException("Failed to list all locations", succeededLocations, + listClustersResponse.getFailedLocationsList()); } + return clusters; } @@ -330,8 +428,7 @@ private static List convertToAppProfiles( ListAppProfilesResponse listAppProfilesResponse) { List appProfiles = new ArrayList<>(); - for (com.google.bigtable.admin.v2.AppProfile profile : - listAppProfilesResponse.getAppProfilesList()) { + for (com.google.bigtable.admin.v2.AppProfile profile : listAppProfilesResponse.getAppProfilesList()) { appProfiles.add(InstanceAdminRequests.convertToAppProfile(profile)); } return appProfiles; @@ -342,18 +439,16 @@ private static ApiFuture transfromOperationFuture( final OperationFuture future, final ApiFunction function) { final SettableApiFuture result = SettableApiFuture.create(); - future.addListener( - new Runnable() { - @Override - public void run() { - try { - result.set(function.apply(future.get())); - } catch (InterruptedException | ExecutionException e) { - result.setException(e); - } - } - }, - MoreExecutors.directExecutor()); + future.addListener(new Runnable() { + @Override + public void run() { + try { + result.set(function.apply(future.get())); + } catch (InterruptedException | ExecutionException e) { + result.setException(e); + } + } + }, MoreExecutors.directExecutor()); return result; } } diff --git a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/FailedLocationException.java b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/FailedLocationException.java new file mode 100644 index 000000000000..cfc62e44a516 --- /dev/null +++ b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/FailedLocationException.java @@ -0,0 +1,26 @@ +package com.google.cloud.bigtable.admin.v2.models; + +import java.util.List; +import com.google.api.core.BetaApi; + +@BetaApi +public class FailedLocationException extends RuntimeException { + private static final long serialVersionUID = 1L; + private final List succeededLocations; + private final List failedLocations; + + public FailedLocationException( + String message, List succeededLocations, List failedLocations) { + super(message); + this.succeededLocations = succeededLocations; + this.failedLocations = failedLocations; + } + + public List getSucceededLocations() { + return succeededLocations; + } + + public List getFailedLocations() { + return failedLocations; + } +} diff --git a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/InstanceAdminRequests.java b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/InstanceAdminRequests.java index 02b396aaf3fc..6d598e70ef82 100644 --- a/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/InstanceAdminRequests.java +++ b/google-cloud-clients/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/InstanceAdminRequests.java @@ -9,7 +9,6 @@ import com.google.bigtable.admin.v2.AppProfile.RoutingPolicyCase; import com.google.bigtable.admin.v2.AppProfileName; import com.google.bigtable.admin.v2.ClusterName; -import com.google.bigtable.admin.v2.CreateAppProfileRequest; import com.google.bigtable.admin.v2.CreateInstanceRequest; import com.google.bigtable.admin.v2.Instance.State; import com.google.bigtable.admin.v2.Instance.Type; @@ -31,11 +30,6 @@ public static CreateInstance createInstance( return new CreateInstance(projectName, instance, cluster); } - public static CreateAppProfile createAppProfile( - InstanceName instanceName, AppProfile appProfile, boolean ignoreWarnings) { - return new CreateAppProfile(instanceName, appProfile, ignoreWarnings); - } - public static Instance convertToInstance(com.google.bigtable.admin.v2.Instance protoInstance) { return new Instance(protoInstance); } @@ -44,10 +38,6 @@ public static Cluster convertToCluster(com.google.bigtable.admin.v2.Cluster prot return new Cluster(protoCluster); } - public static Cluster convertToFailedCluster(String location) { - return new Cluster(location); - } - public static AppProfile convertToAppProfile(com.google.bigtable.admin.v2.AppProfile appProfile) { return new AppProfile(appProfile); } @@ -84,17 +74,20 @@ public CreateInstanceRequest toProto() { } public static final class Instance { - private final String DISPLAY_NAME_FIELDMASK = "display_name"; - private final String TYPE_FIELDMASK = "type"; - private final String LABELS_FIELDMASK = "labels"; - private final String id; - private final List replacefields = new ArrayList<>(); private com.google.bigtable.admin.v2.Instance.Builder protoInstance = com.google.bigtable.admin.v2.Instance.newBuilder(); - public static Instance of(String instanceId, String displayName, Type instanceType) { - return new Instance(instanceId, displayName, instanceType); + public static Instance ofNewDevInstance(String instanceId, String displayName) { + return new Instance(instanceId, displayName, Type.DEVELOPMENT); + } + + public static Instance ofNewProdInstance(String instanceId, String displayName) { + return new Instance(instanceId, displayName, Type.PRODUCTION); + } + + public static UpdateInstance ofUpdateInstance(Instance instance) { + return new UpdateInstance(instance); } private Instance(String instanceId, String displayName, Type instanceType) { @@ -137,86 +130,100 @@ public Instance addLabel(String key, String value) { return this; } - public Instance updateDisplayName(String updatedDisplayName) { + @InternalApi + public com.google.bigtable.admin.v2.Instance toProto() { + return protoInstance.build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", getName()) + .add("displayName", getDisplayName()) + .add("state", getState()) + .add("type", getType()) + .add("labels", getLabelsMap()) + .toString(); + } + } + + public static final class UpdateInstance { + private final String DISPLAY_NAME_FIELDMASK = "display_name"; + private final String TYPE_FIELDMASK = "type"; + private final String LABELS_FIELDMASK = "labels"; + + private final List replacefields = new ArrayList<>(); + private com.google.bigtable.admin.v2.Instance.Builder protoUpdateInstance = + com.google.bigtable.admin.v2.Instance.newBuilder(); + + private UpdateInstance(Instance instance) { + protoUpdateInstance = instance.toProto().toBuilder().clone(); + } + + public UpdateInstance updateDisplayName(String updatedDisplayName) { replacefields.add(DISPLAY_NAME_FIELDMASK); - protoInstance.setDisplayName(updatedDisplayName); + protoUpdateInstance.setDisplayName(updatedDisplayName); return this; } - public Instance upgradeType() { + public UpdateInstance upgradeType() { Preconditions.checkArgument( - Type.DEVELOPMENT.equals(protoInstance.getType()), "PRODUCTION type cannot be upgraded"); + Type.DEVELOPMENT.equals(protoUpdateInstance.getType()), + "PRODUCTION type cannot be upgraded"); replacefields.add(TYPE_FIELDMASK); - protoInstance.setType(Type.PRODUCTION); + protoUpdateInstance.setType(Type.PRODUCTION); return this; } - public Instance updateLabels(Map updatedLabels) { + public UpdateInstance updateLabels(Map updatedLabels) { replacefields.add(LABELS_FIELDMASK); - protoInstance.putAllLabels(updatedLabels); + protoUpdateInstance.putAllLabels(updatedLabels); return this; } @InternalApi public com.google.bigtable.admin.v2.Instance toProto() { - return protoInstance.build(); - } - - @InternalApi - public com.google.bigtable.admin.v2.Instance toUpdateProto() { - return protoInstance.clone().clearState().build(); + return protoUpdateInstance.clearState().build(); } @InternalApi public FieldMask getPartialUpdateFieldMask() { return FieldMask.newBuilder().addAllPaths(replacefields).build(); } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("name", getName()) - .add("displayName", getDisplayName()) - .add("state", getState()) - .add("type", getType()) - .add("labels", getLabelsMap()) - .toString(); - } } public static final class Cluster { - public static Cluster ofProd( - String clusterId, Location location, StorageType defaultStorage, int serverNodes) { - return new Cluster(clusterId, location, defaultStorage, serverNodes); + public static Cluster ofNewDevCluster(String clusterId, Location location) { + return new Cluster(clusterId, location, 0); + } + + public static Cluster ofNewProdCluster(String clusterId, Location location, int serverNodes) { + return new Cluster(clusterId, location, serverNodes); } - public static Cluster ofDev(String clusterId, Location location, StorageType defaultStorage) { - return new Cluster(clusterId, location, defaultStorage, 0); + public static UpdateCluster ofUpdateCluster(Cluster cluster) { + return new UpdateCluster(cluster); } private final String id; private com.google.bigtable.admin.v2.Cluster.Builder protoCluster = com.google.bigtable.admin.v2.Cluster.newBuilder(); - private Cluster( - String clusterId, Location location, StorageType defaultStorage, int serverNodes) { - protoCluster - .setLocation(location.toString()) - .setServeNodes(serverNodes) - .setDefaultStorageType(defaultStorage); + private Cluster(String clusterId, Location location, int serverNodes) { + protoCluster.setLocation(location.toString()).setServeNodes(serverNodes); this.id = clusterId; } - private Cluster(String location) { - protoCluster.setLocation(location); - id = "failedlocation"; - } - private Cluster(com.google.bigtable.admin.v2.Cluster cluster) { protoCluster = cluster.toBuilder(); id = getName().getCluster(); } + public Cluster setDefaultStorage(StorageType defaultStorage) { + protoCluster.setDefaultStorageType(defaultStorage); + return this; + } + public String getId() { return id; } @@ -241,21 +248,12 @@ public StorageType getDefaultStorageType() { return protoCluster.getDefaultStorageType(); } - public Cluster updateNumNodes(int serverNodes) { - protoCluster.setServeNodes(serverNodes); - return this; - } - @InternalApi public com.google.bigtable.admin.v2.Cluster toProto() { + // TODO: defaultStorage is currently optional, should we make this required? return protoCluster.build(); } - @InternalApi - public com.google.bigtable.admin.v2.Cluster toUpdateProto() { - return protoCluster.clone().clearState().clearDefaultStorageType().build(); - } - @Override public String toString() { return MoreObjects.toStringHelper(this) @@ -268,42 +266,40 @@ public String toString() { } } - public static final class CreateAppProfile { - private final CreateAppProfileRequest.Builder createAppProfRequest = - CreateAppProfileRequest.newBuilder(); + public static final class UpdateCluster { + private com.google.bigtable.admin.v2.Cluster.Builder protoUpdateCluster = + com.google.bigtable.admin.v2.Cluster.newBuilder(); - private CreateAppProfile( - InstanceName instanceName, AppProfile appProfile, boolean ignoreWarnings) { - createAppProfRequest - .setParent(instanceName.toString()) - .setAppProfileId(appProfile.getId()) - .setAppProfile(appProfile.toProto()) - .setIgnoreWarnings(ignoreWarnings); + private UpdateCluster(Cluster cluster) { + protoUpdateCluster = cluster.toProto().toBuilder().clone(); } - public CreateAppProfileRequest toProto() { - return createAppProfRequest.build(); + public UpdateCluster updateNumNodes(int serverNodes) { + protoUpdateCluster.setServeNodes(serverNodes); + return this; + } + + @InternalApi + public com.google.bigtable.admin.v2.Cluster toProto() { + return protoUpdateCluster.clearState().clearDefaultStorageType().build(); } } public static final class AppProfile { - private static final String DESCRIPTION_FIELDMASK = "description"; - private static final String MULTI_CLUSTER_FIELDMASK = "multi_cluster_routing_use_any"; - private static final String SINGLE_CLUSTER__FIELDMASK = "single_cluster_routing"; - private final String id; - private final List replacefields = new ArrayList<>(); private com.google.bigtable.admin.v2.AppProfile.Builder protoProfile = com.google.bigtable.admin.v2.AppProfile.newBuilder(); - public static AppProfile of(String profileId, RoutingPolicy routingPolicy) { - return new AppProfile(profileId, routingPolicy); + public static AppProfile ofNewAppProfile(String profileId) { + return new AppProfile(profileId); + } + + public static UpdateAppProfile ofUpdateAppProfile(AppProfile appProfile) { + return new UpdateAppProfile(appProfile); } - private AppProfile(String profileId, RoutingPolicy routingPolicy) { - Preconditions.checkNotNull(routingPolicy); + private AppProfile(String profileId) { id = profileId; - setRoutingPolicy(routingPolicy); } private AppProfile(com.google.bigtable.admin.v2.AppProfile appProfile) { @@ -311,34 +307,31 @@ private AppProfile(com.google.bigtable.admin.v2.AppProfile appProfile) { id = getName().getAppProfile(); } - private void setRoutingPolicy(RoutingPolicy routingPolicy) { - if (RoutingPolicyCase.MULTI_CLUSTER_ROUTING_USE_ANY.equals(routingPolicy.name())) { - protoProfile.setMultiClusterRoutingUseAny( - com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny.newBuilder().build()); - protoProfile.clearSingleClusterRouting(); - replacefields.add(MULTI_CLUSTER_FIELDMASK); - } - - if (RoutingPolicyCase.SINGLE_CLUSTER_ROUTING.equals(routingPolicy.name())) { - protoProfile.setSingleClusterRouting( - com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting.newBuilder() - .setClusterId(((SingleClusterRouting) routingPolicy).clusterId) - .setAllowTransactionalWrites( - ((SingleClusterRouting) routingPolicy).allowTransactionalWrites)); - protoProfile.clearMultiClusterRoutingUseAny(); - replacefields.add(SINGLE_CLUSTER__FIELDMASK); - } + public AppProfile setDescription(String description) { + protoProfile.setDescription(description); + return this; } - public String getId() { - return id; + public AppProfile routeToAny() { + protoProfile.setMultiClusterRoutingUseAny( + com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny.newBuilder().build()); + protoProfile.clearSingleClusterRouting(); + return this; } - public AppProfile setDescription(String description) { - protoProfile.setDescription(description); + public AppProfile routeToCluster(String clusterId, boolean ignoreWarnings) { + protoProfile.setSingleClusterRouting( + com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting.newBuilder() + .setClusterId(clusterId) + .setAllowTransactionalWrites(ignoreWarnings)); + protoProfile.clearMultiClusterRoutingUseAny(); return this; } + public String getId() { + return id; + } + public AppProfileName getName() { return AppProfileName.parse(protoProfile.getName()); } @@ -352,45 +345,30 @@ public String getDescription() { } public RoutingPolicy getRoutingPolicy() { - if (RoutingPolicyCase.MULTI_CLUSTER_ROUTING_USE_ANY.equals( - protoProfile.getRoutingPolicyCase().name())) { + if (RoutingPolicyCase.MULTI_CLUSTER_ROUTING_USE_ANY + .name() + .equals(protoProfile.getRoutingPolicyCase().name())) { return new MultiClusterRoutingUseAny(); } - if (RoutingPolicyCase.SINGLE_CLUSTER_ROUTING.equals( - protoProfile.getRoutingPolicyCase().name())) { + if (RoutingPolicyCase.SINGLE_CLUSTER_ROUTING + .name() + .equals(protoProfile.getRoutingPolicyCase().name())) { return new SingleClusterRouting(protoProfile.getSingleClusterRouting()); } return new RoutingPolicyNotSet(); } - public AppProfile updateDescription(String updatedDescription) { - replacefields.add(DESCRIPTION_FIELDMASK); - protoProfile.setDescription(updatedDescription); - return this; - } - - public AppProfile updateRoutingPolicy(RoutingPolicy routingPolicy) { - setRoutingPolicy(routingPolicy); - return this; - } - @InternalApi public com.google.bigtable.admin.v2.AppProfile toProto() { + // TODO: should we default this to any instead? + Preconditions.checkState( + protoProfile.hasMultiClusterRoutingUseAny() || protoProfile.hasSingleClusterRouting(), + "Must specify a routing option"); return protoProfile.build(); } - @InternalApi - public com.google.bigtable.admin.v2.AppProfile toUpdateProto() { - return protoProfile.clone().build(); - } - - @InternalApi - public FieldMask getPartialUpdateFieldMask() { - return FieldMask.newBuilder().addAllPaths(replacefields).build(); - } - @Override public String toString() { return MoreObjects.toStringHelper(this) @@ -401,6 +379,55 @@ public String toString() { .toString(); } + public static class UpdateAppProfile { + private static final String DESCRIPTION_FIELDMASK = "description"; + private static final String MULTI_CLUSTER_FIELDMASK = "multi_cluster_routing_use_any"; + private static final String SINGLE_CLUSTER__FIELDMASK = "single_cluster_routing"; + + private final List replacefields = new ArrayList<>(); + private com.google.bigtable.admin.v2.AppProfile.Builder protoUpdateProfile = + com.google.bigtable.admin.v2.AppProfile.newBuilder(); + + private UpdateAppProfile(AppProfile appProfile) { + Preconditions.checkNotNull(appProfile); + protoUpdateProfile = appProfile.toProto().toBuilder().clone(); + } + + public UpdateAppProfile updateDescription(String updatedDescription) { + replacefields.add(DESCRIPTION_FIELDMASK); + protoUpdateProfile.setDescription(updatedDescription); + return this; + } + + public UpdateAppProfile updateRouteToAny() { + protoUpdateProfile.setMultiClusterRoutingUseAny( + com.google.bigtable.admin.v2.AppProfile.MultiClusterRoutingUseAny.newBuilder().build()); + protoUpdateProfile.clearSingleClusterRouting(); + replacefields.add(MULTI_CLUSTER_FIELDMASK); + return this; + } + + public UpdateAppProfile updateRouteToCluster(String clusterId, boolean ignoreWarnings) { + protoUpdateProfile.setSingleClusterRouting( + com.google.bigtable.admin.v2.AppProfile.SingleClusterRouting.newBuilder() + .setClusterId(clusterId) + .setAllowTransactionalWrites(ignoreWarnings)); + protoUpdateProfile.clearMultiClusterRoutingUseAny(); + replacefields.add(SINGLE_CLUSTER__FIELDMASK); + return this; + } + + @InternalApi + public com.google.bigtable.admin.v2.AppProfile toProto() { + return protoUpdateProfile.build(); + } + + @InternalApi + public FieldMask getPartialUpdateFieldMask() { + return FieldMask.newBuilder().addAllPaths(replacefields).build(); + } + } + public interface RoutingPolicy { RoutingPolicyCase name(); } @@ -420,10 +447,6 @@ public String toString() { } public static class MultiClusterRoutingUseAny implements RoutingPolicy { - public static MultiClusterRoutingUseAny of() { - return new MultiClusterRoutingUseAny(); - } - private MultiClusterRoutingUseAny() {} @Override @@ -441,10 +464,6 @@ public static class SingleClusterRouting implements RoutingPolicy { private final String clusterId; private final boolean allowTransactionalWrites; - public static SingleClusterRouting of(String clusterId, boolean allowTransactionalWrites) { - return new SingleClusterRouting(clusterId, allowTransactionalWrites); - } - private SingleClusterRouting(String clusterId, boolean allowTransactionalWrites) { this.clusterId = clusterId; this.allowTransactionalWrites = allowTransactionalWrites; @@ -541,18 +560,21 @@ public String toString() { } public static final class Location { - public static Location of(ProjectName projectName, String zone) { - return new Location(projectName, zone); + public static Location of(String project, String zone) { + return new Location(project, zone); } private final String location; - private Location(ProjectName projectName, String zone) { - Preconditions.checkNotNull(projectName); + private Location(String project, String zone) { + Preconditions.checkNotNull(project); Preconditions.checkNotNull(zone); location = - new StringBuilder(projectName.toString()).append("/locations/").append(zone).toString(); + new StringBuilder(ProjectName.of(project).toString()) + .append("/locations/") + .append(zone) + .toString(); } @Override diff --git a/google-cloud-clients/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/InstanceAdminClientIT.java b/google-cloud-clients/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/InstanceAdminClientIT.java index d2175148cd4f..54517334aac6 100644 --- a/google-cloud-clients/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/InstanceAdminClientIT.java +++ b/google-cloud-clients/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/InstanceAdminClientIT.java @@ -9,6 +9,7 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import com.google.bigtable.admin.v2.AppProfile.RoutingPolicyCase; import com.google.bigtable.admin.v2.AppProfileName; import com.google.bigtable.admin.v2.ClusterName; import com.google.bigtable.admin.v2.Instance.State; @@ -19,8 +20,8 @@ import com.google.cloud.bigtable.admin.v2.InstanceAdminClient; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.AppProfile; -import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.AppProfile.MultiClusterRoutingUseAny; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Cluster; +import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.CreateInstance; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Instance; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Location; import com.google.cloud.bigtable.admin.v2.models.InstanceAdminRequests.Policy; @@ -37,7 +38,7 @@ public class InstanceAdminClientIT { public static void createClient() throws Exception { instanceAdmin = InstanceAdminClient.create(); } - + @AfterClass public static void closeClient() throws Exception { instanceAdmin.close(); @@ -45,108 +46,131 @@ public static void closeClient() throws Exception { @Test public void createInstanceHarness() throws Exception { - Instance rawinstance = - InstanceAdminRequests.Instance.of( - TEST_PROD_INST_ID, TEST_PROD_INST_ID + "disp", Type.PRODUCTION); + Instance newProdInstance = Instance.ofNewProdInstance(TEST_PROD_INST_ID, "disp"); - Cluster rawcluster = - InstanceAdminRequests.Cluster.ofProd( + Cluster newCluster = + Cluster.ofNewProdCluster( TEST_PROD_INST_ID + "us-east1-c", - Location.of(TEST_PROJECT, "us-east1-c"), - StorageType.HDD, + Location.of(TEST_PROJECT.getProject(), "us-east1-c"), PROD_CLUSTER_SIZE); try { // Instance tests int numInstances = instanceAdmin.listInstances(TEST_PROJECT).size(); - Instance actualInstance = createInstanceAsync(TEST_PROJECT, rawinstance, rawcluster); + Instance createdInstance = createInstance(TEST_PROJECT, newProdInstance, newCluster); listInstances(numInstances + 1); - getInstance(actualInstance); - updateInstance(actualInstance); - partialUpdateInstance(actualInstance); + getInstance(createdInstance); + updateInstance(createdInstance); + partialUpdateInstance(createdInstance); // Cluster tests - getClusterFromRaw(actualInstance.getName(), rawcluster); - listClusters(actualInstance.getName(), 1); + getCluster( + newCluster, + ClusterName.of(TEST_PROJECT.getProject(), TEST_PROD_INST_ID, newCluster.getId())); + listClusters(createdInstance.getName(), 1); Exception cannotMixClusterType = null; try { - createCluster(actualInstance, "us-east1-d", Type.DEVELOPMENT); + createCluster( + createdInstance, + Cluster.ofNewDevCluster( + TEST_DEV_INST_ID + "us-east1-d", + Location.of(TEST_PROJECT.getProject(), "us-east1-d"))); } catch (Exception ex) { cannotMixClusterType = ex; } assertNotNull(cannotMixClusterType); - Cluster actualCluster2 = createCluster(actualInstance, "us-east1-d", Type.PRODUCTION); - getCluster(actualCluster2); - updateCluster(actualCluster2); - listClusters(actualInstance.getName(), 2); - deleteCluster(actualCluster2); - listClusters(actualInstance.getName(), 1); + Cluster createdCluster2 = + createCluster( + createdInstance, + Cluster.ofNewProdCluster( + TEST_PROD_INST_ID + "us-east1-d", + Location.of(TEST_PROJECT.getProject(), "us-east1-d"), + PROD_CLUSTER_SIZE + 1)); + getCluster(createdCluster2); + updateCluster(createdCluster2); + listClusters(createdInstance.getName(), 2); // AppProfile tests - AppProfile rawMulti = AppProfile.of("roundRobin", MultiClusterRoutingUseAny.of()); - AppProfile actualMulti = createAppProfile(actualInstance.getName(), rawMulti); - getAppProfile(actualMulti); - updateAppProfileSwitchToSingle(actualMulti, rawcluster.getId()); - listAppProfiles(actualInstance.getName(), 2); // +1 for default appProfile - deleteAppProfile(actualMulti.getName()); + AppProfile createdAny = + createAppProfile( + createdInstance.getName(), AppProfile.ofNewAppProfile("roundRobin").routeToAny()); + getAppProfile(createdAny); + updateAppProfileToSingle(createdAny, createdCluster2.getId()); + listAppProfiles(createdInstance.getName(), 2); // +1 for default appProfile + deleteAppProfile(createdAny.getName()); // IamPolicy tests - // TODO: Needs Iam permissions to test this. Doesn't look like I have them + // TODO: Needs Iam permissions to test this. // Policy rawPolicy = Policy.of(1, Role.owner(), - // Arrays.asList("user:spollaplly@udbhavinc.com")); - // Policy actualPolicy = instanceAdmin.setIamPolicy(actualInstance.getName(), rawPolicy); + // Arrays.asList("user:user@domain.com")); + // Policy actualPolicy = instanceAdmin.setIamPolicy(createdInstance.getName(), rawPolicy); - Policy iamPolicy = instanceAdmin.getIamPolicy(actualInstance.getName()); + Policy iamPolicy = instanceAdmin.getIamPolicy(createdInstance.getName()); assertNotNull(iamPolicy); List actualPermissions = instanceAdmin.testIamPermissions( - actualInstance.getName(), Arrays.asList("bigtable.tables.checkConsistency")); + createdInstance.getName(), Arrays.asList("bigtable.tables.checkConsistency")); assertEquals(Arrays.asList("bigtable.tables.checkConsistency"), actualPermissions); + + deleteCluster(createdCluster2); + listClusters(createdInstance.getName(), 1); } finally { instanceAdmin.deleteInstanceRequest( InstanceName.of(TEST_PROJECT.getProject(), TEST_PROD_INST_ID)); } } + @Test + public void createInstanceMultiCluster() throws Exception { + CreateInstance request = + InstanceAdminRequests.createInstance( + TEST_PROJECT, + Instance.ofNewProdInstance("multitest", "twoclusters"), + Cluster.ofNewProdCluster( + "clusterone", Location.of(TEST_PROJECT.getProject(), "us-east1-c"), 3)) + .addCluster( + Cluster.ofNewProdCluster( + "clustertwo", Location.of(TEST_PROJECT.getProject(), "us-east1-c"), 4)); + + try { + Instance createdInstance = instanceAdmin.createInstanceAsync(request).get(); + getInstance(createdInstance); + listClusters(createdInstance.getName(), 2); + } finally { + instanceAdmin.deleteInstanceRequest(InstanceName.of(TEST_PROJECT.getProject(), "multitest")); + } + } + @Test public void createInstanceUpgradeHarness() throws Exception { - Instance rawinstance = - InstanceAdminRequests.Instance.of( - TEST_DEV_INST_ID, TEST_DEV_INST_ID + "disp", Type.DEVELOPMENT) + Instance newDevInstance = + Instance.ofNewDevInstance(TEST_DEV_INST_ID, TEST_DEV_INST_ID + "disp") .addLabel("label_name_1", "label_value_1") .addLabel("label_name_2", "label_value_2"); - Cluster rawcluster1 = - InstanceAdminRequests.Cluster.ofDev( - TEST_DEV_INST_ID + "us-east1-c", - Location.of(TEST_PROJECT, "us-east1-c"), - StorageType.HDD); - /* - * Cluster rawcluster2 = InstanceAdminRequests.Cluster.ofDev(TEST_DEV_INST_ID + "us-east1-b", - * Location.of(TEST_PROJECT, "us-east1-b"), StorageType.HDD); - */ - + Cluster newDevCluster = + Cluster.ofNewDevCluster( + TEST_DEV_INST_ID + "us-east1-c", Location.of(TEST_PROJECT.getProject(), "us-east1-c")); try { - Instance actualInstance = + Instance createdInstance = instanceAdmin .createInstanceAsync( - InstanceAdminRequests.createInstance(TEST_PROJECT, rawinstance, rawcluster1) - // TODO: Test fails with instance not found. Verify if more than one cluster on - // creation is - // a valid case - // .addCluster(rawcluster2) - ) + InstanceAdminRequests.createInstance(TEST_PROJECT, newDevInstance, newDevCluster)) .get(); - assertInstanceEquals(rawinstance, actualInstance); + assertInstanceEquals(newDevInstance, createdInstance); - listClusters(actualInstance.getName(), 1); - getClusterFromRaw(actualInstance.getName(), rawcluster1); - // getClusterFromRaw(actualInstance.getName(), rawcluster2); + listClusters(createdInstance.getName(), 1); + getCluster( + newDevCluster, + ClusterName.of(TEST_PROJECT.getProject(), TEST_DEV_INST_ID, newDevCluster.getId())); - Instance upgradedInstance = instanceAdmin.updateInstance(actualInstance.upgradeType()).get(); + Instance upgradedInstance = + instanceAdmin + .updateInstance(Instance.ofUpdateInstance(createdInstance).upgradeType()) + .get(); assertEquals(Type.PRODUCTION, upgradedInstance.getType()); } finally { instanceAdmin.deleteInstanceRequest( @@ -154,48 +178,15 @@ public void createInstanceUpgradeHarness() throws Exception { } } - @Test - public void iamPolicyHarness() throws Exception { - Instance rawinstance = - InstanceAdminRequests.Instance.of( - TEST_PROD_INST_ID, TEST_PROD_INST_ID + "disp", Type.PRODUCTION); - - Cluster rawcluster = - InstanceAdminRequests.Cluster.ofProd( - TEST_PROD_INST_ID + "us-east1-c", - Location.of(TEST_PROJECT, "us-east1-c"), - StorageType.HDD, - PROD_CLUSTER_SIZE); - - try { - Instance actualInstance = createInstanceAsync(TEST_PROJECT, rawinstance, rawcluster); - - // TODO: Needs Iam permissions to test this. Doesn't look like I have them - // Policy rawPolicy = Policy.of(1, Role.owner(), - // Arrays.asList("user:spollaplly@udbhavinc.com")); - // Policy actualPolicy = instanceAdmin.setIamPolicy(actualInstance.getName(), rawPolicy); - - Policy iamPolicy = instanceAdmin.getIamPolicy(actualInstance.getName()); - assertNotNull(iamPolicy); - - List actualPermissions = - instanceAdmin.testIamPermissions( - actualInstance.getName(), Arrays.asList("bigtable.tables.checkConsistency")); - assertEquals(Arrays.asList("bigtable.tables.checkConsistency"), actualPermissions); - } finally { - instanceAdmin.deleteInstanceRequest( - InstanceName.of(TEST_PROJECT.getProject(), TEST_PROD_INST_ID)); - } - } - - private Instance createInstanceAsync( - ProjectName projectName, Instance rawinstance, Cluster rawcluster) throws Exception { + /** helpers to execute and assert * */ + private Instance createInstance(ProjectName projectName, Instance newInstance, Cluster newCluster) + throws Exception { Instance actualInstance = instanceAdmin .createInstanceAsync( - InstanceAdminRequests.createInstance(projectName, rawinstance, rawcluster)) + InstanceAdminRequests.createInstance(projectName, newInstance, newCluster)) .get(); - assertInstanceEquals(rawinstance, actualInstance); + assertInstanceEquals(newInstance, actualInstance); return actualInstance; } @@ -206,11 +197,10 @@ private void getInstance(Instance expected) { private void updateInstance(Instance instance) throws Exception { Map updatedLabels = ImmutableMap.of("team", "team1", "subteam", "subteam1"); - Instance updatedInstance = instanceAdmin .updateInstance( - instance + Instance.ofUpdateInstance(instance) .updateDisplayName(TEST_DEV_INST_ID + "upddisp") .updateLabels(updatedLabels)) .get(); @@ -221,40 +211,27 @@ private void updateInstance(Instance instance) throws Exception { private void partialUpdateInstance(Instance instance) throws Exception { Instance updatedInstance = - instanceAdmin.updateInstance(instance.updateDisplayName(TEST_PROD_INST_ID + "disp")).get(); + instanceAdmin + .updateInstance( + Instance.ofUpdateInstance(instance).updateDisplayName(TEST_PROD_INST_ID + "disp")) + .get(); assertEquals(TEST_PROD_INST_ID + "disp", updatedInstance.getDisplayName()); assertEquals(instance.getLabelsMap(), updatedInstance.getLabelsMap()); } - private void getClusterFromRaw(InstanceName instanceName, Cluster raw) { - ClusterName clusterName = - ClusterName.of(instanceName.getProject(), instanceName.getInstance(), raw.getId()); + private void getCluster(Cluster raw, ClusterName clusterName) { Cluster actual = instanceAdmin.getCluster(clusterName); assertClusterEquals(raw, actual, clusterName); } - private Cluster createCluster(Instance instance, String zone, Type type) throws Exception { - Cluster raw; - - if (type.equals(Type.PRODUCTION)) { - raw = - Cluster.ofProd( - instance.getid() + zone, - Location.of(TEST_PROJECT, zone), - StorageType.HDD, - PROD_CLUSTER_SIZE); - } else { - raw = - Cluster.ofDev(instance.getid() + zone, Location.of(TEST_PROJECT, zone), StorageType.HDD); - } - - Cluster actual = instanceAdmin.createCluster(instance.getName(), raw).get(); + private Cluster createCluster(Instance instance, Cluster rawCluster) throws Exception { + Cluster actual = instanceAdmin.createCluster(instance.getName(), rawCluster).get(); assertClusterEquals( - raw, + rawCluster, actual, ClusterName.of( - instance.getName().getProject(), instance.getName().getInstance(), raw.getId())); + instance.getName().getProject(), instance.getName().getInstance(), rawCluster.getId())); return actual; } @@ -265,8 +242,11 @@ private void getCluster(Cluster expected) { private void updateCluster(Cluster cluster) throws Exception { Cluster updatedCluster = - instanceAdmin.updateCluster(cluster.updateNumNodes(PROD_CLUSTER_SIZE + 1)).get(); - assertEquals(cluster.getServerNodes(), updatedCluster.getServerNodes()); + instanceAdmin + .updateCluster( + Cluster.ofUpdateCluster(cluster).updateNumNodes(cluster.getServerNodes() + 1)) + .get(); + assertEquals(cluster.getServerNodes() + 1, updatedCluster.getServerNodes()); } private void deleteCluster(Cluster cluster) { @@ -274,17 +254,25 @@ private void deleteCluster(Cluster cluster) { } private void listInstances(int expectedSize) { - assertEquals(expectedSize, instanceAdmin.listInstances(TEST_PROJECT).size()); + List instances = instanceAdmin.listInstances(TEST_PROJECT); + assertEquals(expectedSize, instances.size()); + + for (Instance instance : instances) { + getInstance(instance); + } } private void listClusters(InstanceName instanceName, int expectedSize) { - assertEquals(expectedSize, instanceAdmin.listClusters(instanceName).size()); + List clusters = instanceAdmin.listClusters(instanceName); + assertEquals(expectedSize, clusters.size()); + + for (Cluster cluster : clusters) { + getCluster(cluster); + } } private AppProfile createAppProfile(InstanceName instanceName, AppProfile rawProfile) { - AppProfile actual = - instanceAdmin.createAppProfile( - InstanceAdminRequests.createAppProfile(instanceName, rawProfile, true)); + AppProfile actual = instanceAdmin.createAppProfile(instanceName, rawProfile); assertAppProfileEquals( rawProfile, actual, @@ -298,23 +286,26 @@ private void getAppProfile(AppProfile expected) { } private void listAppProfiles(InstanceName instanceName, int expectedSize) { - assertEquals(expectedSize, instanceAdmin.listAppProfiles(instanceName).size()); + List appProfiles = instanceAdmin.listAppProfiles(instanceName); + assertEquals(expectedSize, appProfiles.size()); + + for (AppProfile appProfile : appProfiles) { + getAppProfile(appProfile); + } } - private void updateAppProfileSwitchToSingle(AppProfile original, String singleClusterId) + private void updateAppProfileToSingle(AppProfile original, String singleClusterId) throws Exception { - // SingleClusterRouting singlePolicy = SingleClusterRouting.of(singleClusterId, true); AppProfile updated = instanceAdmin .updateAppProfile( - original.updateDescription("newDescription") - // TODO fix policy switch failing test - // .updateRoutingPolicy(singlePolicy)) - ) + AppProfile.ofUpdateAppProfile(original) + .updateDescription("newDescription") + .updateRouteToCluster(singleClusterId, false)) .get(); assertEquals("newDescription", updated.getDescription()); - // assertEquals(singlePolicy.toString(), updated.getRoutingPolicy().toString()); + assertEquals(RoutingPolicyCase.SINGLE_CLUSTER_ROUTING, updated.getRoutingPolicy().name()); } private void deleteAppProfile(AppProfileName appProfileName) { @@ -341,10 +332,11 @@ private static void assertInstanceEquals(Instance exptected, Instance actual) { private void assertClusterEquals(Cluster exptected, Cluster actual, ClusterName expectedName) { assertEquals(com.google.bigtable.admin.v2.Cluster.State.READY, actual.getState()); assertEquals(expectedName, actual.getName()); + assertEquals(exptected.getId(), actual.getId()); assertEquals(exptected.getLocation(), actual.getLocation()); assertEquals(exptected.getServerNodes(), actual.getServerNodes()); - assertEquals(exptected.getDefaultStorageType(), actual.getDefaultStorageType()); + assertEquals(StorageType.SSD, actual.getDefaultStorageType()); } private void assertAppProfileEquals(