diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java index efcb0cd81a..795e791469 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java @@ -24,6 +24,7 @@ import com.google.bigtable.admin.v2.DeleteAppProfileRequest; import com.google.bigtable.admin.v2.GetAppProfileRequest; import com.google.bigtable.admin.v2.ListAppProfilesRequest; +import com.google.bigtable.admin.v2.PartialUpdateClusterRequest; import com.google.cloud.Policy; import com.google.cloud.Policy.DefaultMarshaller; import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPage; @@ -31,6 +32,7 @@ import com.google.cloud.bigtable.admin.v2.internal.NameUtil; import com.google.cloud.bigtable.admin.v2.models.AppProfile; import com.google.cloud.bigtable.admin.v2.models.Cluster; +import com.google.cloud.bigtable.admin.v2.models.ClusterAutoscalingConfig; import com.google.cloud.bigtable.admin.v2.models.CreateAppProfileRequest; import com.google.cloud.bigtable.admin.v2.models.CreateClusterRequest; import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest; @@ -49,6 +51,7 @@ import com.google.iam.v1.TestIamPermissionsRequest; import com.google.iam.v1.TestIamPermissionsResponse; import com.google.protobuf.Empty; +import com.google.protobuf.util.FieldMaskUtil; import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -660,8 +663,10 @@ public List apply(com.google.bigtable.admin.v2.ListClustersResponse pro } /** - * Modifies the cluster's node count. Please note that only clusters that belong to a production - * instance can be resized. + * Modifies the cluster's node count for manual scaling. If autoscaling is already enabled, manual + * scaling will be silently ignored. If you wish to disable autoscaling and enable manual scaling, + * please use {@link BigtableInstanceAdminClient#disableClusterAutoscaling(String, String, int)} + * instead. Please note that only clusters that belong to a production instance can be resized. * *

Sample code: * @@ -676,8 +681,11 @@ public Cluster resizeCluster(String instanceId, String clusterId, int numServeNo } /** - * Asynchronously modifies the cluster's node count. Please note that only clusters that belong to - * a production instance can be resized. + * Asynchronously modifies the cluster's node count for manual scaling. If autoscaling is already + * enabled, manual scaling will be silently ignored. If you wish to disable autoscaling and enable + * manual scaling, please use {@link BigtableInstanceAdminClient#disableClusterAutoscaling(String, + * String, int)} instead. Please note that only clusters that belong to a production instance can + * be resized. * *

{@code
    * ApiFuture clusterFuture = client.resizeCluster("my-instance", "my-cluster", 30);
@@ -707,6 +715,109 @@ public Cluster apply(com.google.bigtable.admin.v2.Cluster proto) {
         MoreExecutors.directExecutor());
   }
 
+  /**
+   * Modifies the cluster's autoscaling config. This will enable autoscaling and disable manual
+   * scaling if the cluster is manually scaled. Please note that only clusters that belong to a
+   * production instance can enable autoscaling.
+   *
+   * 

Sample code: + * + *

{@code
+   * ClusterAutoscalingConfig clusterAutoscalingConfig =
+   *      ClusterAutoscalingConfig.of("my-instance", "my-cluster")
+   *          .setMinNodes(1)
+   *          .setMaxNodes(4)
+   *          .setCpuUtilizationTargetPercent(40);
+   * Cluster cluster = client.updateClusterAutoscalingConfig(clusterAutoscalingConfig);
+   * }
+ */ + public Cluster updateClusterAutoscalingConfig( + @Nonnull ClusterAutoscalingConfig clusterAutoscalingConfig) { + return ApiExceptions.callAndTranslateApiException( + updateClusterAutoscalingConfigAsync(clusterAutoscalingConfig)); + } + + /** + * Asynchronously modifies the cluster's autoscaling config. This will enable autoscaling and + * disable manual scaling if the cluster is manually scaled. Please note that only clusters that + * belong to a production instance can enable autoscaling. + * + *

Sample code: + * + *

{@code
+   * ClusterAutoscalingConfig clusterAutoscalingConfig =
+   *      ClusterAutoscalingConfig.of(targetInstanceId, targetClusterId)
+   *          .setMinNodes(1)
+   *          .setMaxNodes(4)
+   *          .setCpuUtilizationTargetPercent(40);
+   *
+   *  ApiFuture clusterApiFuture = client.updateClusterAutoscalingConfigAsync(clusterAutoscalingConfig);
+   *  Cluster cluster = clusterApiFuture.get();
+   * }
+ */ + public ApiFuture updateClusterAutoscalingConfigAsync( + @Nonnull ClusterAutoscalingConfig clusterAutoscalingConfig) { + PartialUpdateClusterRequest proto = clusterAutoscalingConfig.toProto(projectId); + + return ApiFutures.transform( + stub.partialUpdateClusterOperationCallable().futureCall(proto), + Cluster::fromProto, + MoreExecutors.directExecutor()); + } + + /** + * Disables autoscaling and enables manual scaling by setting a static node count for the cluster. + * Please note that only clusters that belong to a production instance can be resized. + * + *

Sample code: + * + *

{@code
+   * Cluster cluster = client.disableClusterAutoscaling("my-instance", "my-cluster", 3);
+   * }
+ */ + public Cluster disableClusterAutoscaling(String instanceId, String clusterId, int staticSize) { + return ApiExceptions.callAndTranslateApiException( + disableClusterAutoscalingAsync(instanceId, clusterId, staticSize)); + } + + /** + * Asynchronously disables autoscaling and enables manual scaling by setting a static node count + * for the cluster. Please note that only clusters that belong to a production instance can be + * resized. + * + *

Sample code: + * + *

{@code
+   * ApiFuture clusterApiFuture = client.disableClusterAutoscalingAsync("my-instance", "my-cluster", 3);
+   * Cluster cluster = clusterApiFuture.get();
+   * }
+ */ + public ApiFuture disableClusterAutoscalingAsync( + String instanceId, String clusterId, int staticSize) { + String name = NameUtil.formatClusterName(projectId, instanceId, clusterId); + + com.google.bigtable.admin.v2.Cluster request = + com.google.bigtable.admin.v2.Cluster.newBuilder() + .setName(name) + .setServeNodes(staticSize) + .setClusterConfig( + com.google.bigtable.admin.v2.Cluster.ClusterConfig.getDefaultInstance()) + .build(); + + PartialUpdateClusterRequest partialUpdateClusterRequest = + PartialUpdateClusterRequest.newBuilder() + .setUpdateMask( + FieldMaskUtil.fromStringList( + com.google.bigtable.admin.v2.Cluster.class, + Lists.newArrayList("cluster_config.cluster_autoscaling_config", "serve_nodes"))) + .setCluster(request) + .build(); + return ApiFutures.transform( + stub.partialUpdateClusterOperationCallable().futureCall(partialUpdateClusterRequest), + Cluster::fromProto, + MoreExecutors.directExecutor()); + } + /** * Deletes the specified cluster. Please note that an instance must have at least 1 cluster. To * remove the last cluster, please use {@link BigtableInstanceAdminClient#deleteInstance(String)}. diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/Cluster.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/Cluster.java index cf7218b062..8580fc9897 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/Cluster.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/Cluster.java @@ -148,6 +148,36 @@ public int getServeNodes() { return stateProto.getServeNodes(); } + /** Get the minimum number of nodes to scale down to. */ + public int getAutoscalingMinServeNodes() { + return stateProto + .getClusterConfig() + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMinServeNodes(); + } + + /** Get the maximum number of nodes to scale up to. */ + public int getAutoscalingMaxServeNodes() { + return stateProto + .getClusterConfig() + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMaxServeNodes(); + } + + /** + * Get the cpu utilization that the Autoscaler should be trying to achieve. This number is on a + * scale from 0 (no utilization) to 100 (total utilization). + */ + public int getAutoscalingCpuPercentageTarget() { + return stateProto + .getClusterConfig() + .getClusterAutoscalingConfig() + .getAutoscalingTargets() + .getCpuUtilizationPercent(); + } + /** * The type of storage used by this cluster to serve its parent instance's tables, unless * explicitly overridden. diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ClusterAutoscalingConfig.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ClusterAutoscalingConfig.java new file mode 100644 index 0000000000..1a0a135640 --- /dev/null +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/ClusterAutoscalingConfig.java @@ -0,0 +1,209 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigtable.admin.v2.models; + +import com.google.api.core.InternalApi; +import com.google.bigtable.admin.v2.Cluster; +import com.google.cloud.bigtable.admin.v2.internal.NameUtil; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.protobuf.util.FieldMaskUtil; +import javax.annotation.Nonnull; + +/** + * Model class to create an autoscaling config for creating or updating a cluster. When creating + * this config, min nodes, max nodes, and CPU utilization must all be set. + */ +public class ClusterAutoscalingConfig { + private final String clusterId; + private final String instanceId; + private final com.google.bigtable.admin.v2.PartialUpdateClusterRequest.Builder builder = + com.google.bigtable.admin.v2.PartialUpdateClusterRequest.newBuilder(); + private final com.google.bigtable.admin.v2.Cluster.ClusterConfig.Builder clusterConfigBuilder = + com.google.bigtable.admin.v2.Cluster.ClusterConfig.newBuilder(); + + public static ClusterAutoscalingConfig of(@Nonnull String instanceId, @Nonnull String clusterId) { + return new ClusterAutoscalingConfig(instanceId, clusterId); + } + + private ClusterAutoscalingConfig(@Nonnull String instanceId, @Nonnull String clusterId) { + Preconditions.checkNotNull(instanceId, "instanceId can't be null"); + Preconditions.checkNotNull(clusterId, "clusterId can't be null"); + this.instanceId = instanceId; + this.clusterId = clusterId; + } + + /** The cluster id to set autoscaling on */ + public String getClusterId() { + return clusterId; + } + + /** The instance id of the cluster to set autoscaling on */ + public String getInstanceId() { + return instanceId; + } + + /** Set the minimum number of nodes to scale down to. */ + public ClusterAutoscalingConfig setMinNodes(int minNodes) { + builder.setUpdateMask( + FieldMaskUtil.union( + builder.getUpdateMask(), + FieldMaskUtil.fromString( + Cluster.class, + "cluster_config.cluster_autoscaling_config.autoscaling_limits.min_serve_nodes"))); + clusterConfigBuilder + .getClusterAutoscalingConfigBuilder() + .getAutoscalingLimitsBuilder() + .setMinServeNodes(minNodes); + return this; + } + + /** Set the maximum number of nodes to scale up to. */ + public ClusterAutoscalingConfig setMaxNodes(int maxNodes) { + builder.setUpdateMask( + FieldMaskUtil.union( + builder.getUpdateMask(), + FieldMaskUtil.fromString( + Cluster.class, + "cluster_config.cluster_autoscaling_config.autoscaling_limits.max_serve_nodes"))); + clusterConfigBuilder + .getClusterAutoscalingConfigBuilder() + .getAutoscalingLimitsBuilder() + .setMaxServeNodes(maxNodes); + return this; + } + + /** + * Set the CPU utilization that the Autoscaler should be trying to achieve. This number is on a + * scale from 0 (no utilization) to 100 (total utilization). + */ + public ClusterAutoscalingConfig setCpuUtilizationTargetPercent(int cpuUtilizationTargetPercent) { + builder.setUpdateMask( + FieldMaskUtil.union( + builder.getUpdateMask(), + FieldMaskUtil.fromString( + Cluster.class, + "cluster_config.cluster_autoscaling_config.autoscaling_targets.cpu_utilization_percent"))); + clusterConfigBuilder + .getClusterAutoscalingConfigBuilder() + .getAutoscalingTargetsBuilder() + .setCpuUtilizationPercent(cpuUtilizationTargetPercent); + return this; + } + + /** Get the minimum number of nodes to scale down to. */ + public int getMinNodes() { + return clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMinServeNodes(); + } + + /** Get the maximum number of nodes to scale up to. */ + public int getMaxNodes() { + return clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMaxServeNodes(); + } + + /** + * Get the CPU utilization that the Autoscaler should be trying to achieve. This number is on a + * scale from 0 (no utilization) to 100 (total utilization). + */ + public int getCpuUtilizationTargetPercent() { + return clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingTargets() + .getCpuUtilizationPercent(); + } + + /** + * Creates the request protobuf. This method is considered an internal implementation detail and + * not meant to be used by applications. + */ + @InternalApi + public com.google.bigtable.admin.v2.PartialUpdateClusterRequest toProto(String projectId) { + // Empty field mask implies full resource replacement, which would clear all fields in an empty + // update request. + + this.builder + .getClusterBuilder() + .setName(NameUtil.formatClusterName(projectId, instanceId, clusterId)) + .setClusterConfig(clusterConfigBuilder.build()); + + return this.builder.build(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ClusterAutoscalingConfig that = (ClusterAutoscalingConfig) o; + return Objects.equal( + clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMaxServeNodes(), + that.clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMaxServeNodes()) + && Objects.equal( + clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMinServeNodes(), + that.clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMinServeNodes()) + && Objects.equal( + clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingTargets() + .getCpuUtilizationPercent(), + that.clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingTargets() + .getCpuUtilizationPercent()) + && Objects.equal(clusterId, that.clusterId) + && Objects.equal(instanceId, that.instanceId); + } + + @Override + public int hashCode() { + return Objects.hashCode( + clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMaxServeNodes(), + clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingLimits() + .getMinServeNodes(), + clusterConfigBuilder + .getClusterAutoscalingConfig() + .getAutoscalingTargets() + .getCpuUtilizationPercent(), + clusterId, + instanceId); + } +} diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateClusterRequest.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateClusterRequest.java index cf06f63b09..65ecae8d78 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateClusterRequest.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateClusterRequest.java @@ -84,13 +84,60 @@ public CreateClusterRequest setZone(String zone) { /** * Sets the number of nodes allocated to this cluster. More nodes enable higher throughput and * more consistent performance. + * + * @deprecated Please use CreateClusterRequest#setScalingMode instead */ @SuppressWarnings("WeakerAccess") + @Deprecated public CreateClusterRequest setServeNodes(int numNodes) { proto.getClusterBuilder().setServeNodes(numNodes); return this; } + /** + * Sets the scaling node to manual and sets the number of nodes allocated to this cluster. More + * nodes enable higher throughput and more consistent performance. + */ + public CreateClusterRequest setScalingMode(@Nonnull StaticClusterSize staticClusterSize) { + Preconditions.checkState(staticClusterSize.getClusterSize() > 0, "Serve nodes must be > 0"); + if (proto.getCluster().getClusterConfig().hasClusterAutoscalingConfig()) { + throw new IllegalArgumentException( + "Autoscaling is already set. To enable manual scaling, do not set the max nodes, min nodes, and CPU percentage."); + } + proto.getClusterBuilder().setServeNodes(staticClusterSize.getClusterSize()); + return this; + } + + /** + * Sets the scaling mode to autoscaling by accepting an AutoscalingConfig where min nodes, max + * nodes, and CPU utlization percent target are set. + */ + public CreateClusterRequest setScalingMode(@Nonnull ClusterAutoscalingConfig autoscalingConfig) { + int minNodes = autoscalingConfig.getMinNodes(); + int maxNodes = autoscalingConfig.getMaxNodes(); + int cpuTargetPercent = autoscalingConfig.getCpuUtilizationTargetPercent(); + + proto + .getClusterBuilder() + .getClusterConfigBuilder() + .getClusterAutoscalingConfigBuilder() + .getAutoscalingLimitsBuilder() + .setMinServeNodes(minNodes); + proto + .getClusterBuilder() + .getClusterConfigBuilder() + .getClusterAutoscalingConfigBuilder() + .getAutoscalingLimitsBuilder() + .setMaxServeNodes(maxNodes); + proto + .getClusterBuilder() + .getClusterConfigBuilder() + .getClusterAutoscalingConfigBuilder() + .getAutoscalingTargetsBuilder() + .setCpuUtilizationPercent(cpuTargetPercent); + return this; + } + /** * Sets the type of storage used by this cluster to serve its parent instance's tables. Defaults * to {@code SSD}. diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateInstanceRequest.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateInstanceRequest.java index b318c95cab..685e52d555 100644 --- a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateInstanceRequest.java +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/CreateInstanceRequest.java @@ -119,7 +119,7 @@ public CreateInstanceRequest addLabel(@Nonnull String key, @Nonnull String value } /** - * Adds a cluster to the instance request. + * Adds a cluster to the instance request with manual scaling enabled. * *

All new instances must have at least one cluster. DEVELOPMENT instances must have exactly * one cluster. @@ -147,6 +147,34 @@ public CreateInstanceRequest addCluster( return this; } + /** + * Adds a cluster to the instance request with autoscaling enabled. + * + *

All new instances must have at least one cluster. DEVELOPMENT instances must have exactly + * one cluster. + * + * @param clusterId the name of the cluster. + * @param zone the zone where the cluster will be created. + * @param clusterAutoscalingConfig the autoscaling config that sets the min serve nodes, max serve + * nodes, and CPU utilization percentage + * @param storageType the type of storage used by this cluster to serve its parent instance's + * tables. + */ + public CreateInstanceRequest addCluster( + @Nonnull String clusterId, + @Nonnull String zone, + @Nonnull ClusterAutoscalingConfig clusterAutoscalingConfig, + @Nonnull StorageType storageType) { + CreateClusterRequest clusterRequest = + CreateClusterRequest.of("ignored-instance-id", clusterId) + .setZone(zone) + .setScalingMode(clusterAutoscalingConfig) + .setStorageType(storageType); + clusterRequests.add(clusterRequest); + + return this; + } + /** * Adds a CMEK protected cluster using the specified KMS key name. * diff --git a/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/StaticClusterSize.java b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/StaticClusterSize.java new file mode 100644 index 0000000000..c6826e03c4 --- /dev/null +++ b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/StaticClusterSize.java @@ -0,0 +1,28 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigtable.admin.v2.models; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class StaticClusterSize { + + public static StaticClusterSize of(int clusterSize) { + return new AutoValue_StaticClusterSize(clusterSize); + } + + public abstract int getClusterSize(); +} diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java index 9ea6146c1b..8a21f95c1a 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClientTest.java @@ -27,8 +27,12 @@ import com.google.api.gax.rpc.OperationCallable; import com.google.api.gax.rpc.UnaryCallable; import com.google.api.gax.rpc.testing.FakeOperationSnapshot; +import com.google.bigtable.admin.v2.AutoscalingLimits; +import com.google.bigtable.admin.v2.AutoscalingTargets; import com.google.bigtable.admin.v2.CreateInstanceMetadata; import com.google.bigtable.admin.v2.GetInstanceRequest; +import com.google.bigtable.admin.v2.PartialUpdateClusterMetadata; +import com.google.bigtable.admin.v2.PartialUpdateClusterRequest; import com.google.bigtable.admin.v2.UpdateClusterMetadata; import com.google.bigtable.admin.v2.UpdateInstanceMetadata; import com.google.cloud.Identity; @@ -40,6 +44,7 @@ import com.google.cloud.bigtable.admin.v2.models.AppProfile; import com.google.cloud.bigtable.admin.v2.models.AppProfile.MultiClusterRoutingPolicy; import com.google.cloud.bigtable.admin.v2.models.Cluster; +import com.google.cloud.bigtable.admin.v2.models.ClusterAutoscalingConfig; import com.google.cloud.bigtable.admin.v2.models.CreateAppProfileRequest; import com.google.cloud.bigtable.admin.v2.models.CreateClusterRequest; import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest; @@ -93,6 +98,19 @@ public class BigtableInstanceAdminClientTest { private BigtableInstanceAdminClient adminClient; + private final com.google.bigtable.admin.v2.Cluster.ClusterConfig clusterConfig = + com.google.bigtable.admin.v2.Cluster.ClusterConfig.newBuilder() + .setClusterAutoscalingConfig( + com.google.bigtable.admin.v2.Cluster.ClusterAutoscalingConfig.newBuilder() + .setAutoscalingLimits( + AutoscalingLimits.newBuilder() + .setMaxServeNodes(10) + .setMinServeNodes(2) + .build()) + .setAutoscalingTargets( + AutoscalingTargets.newBuilder().setCpuUtilizationPercent(22).build())) + .build(); + @Mock private BigtableInstanceAdminStub mockStub; @Mock @@ -149,6 +167,13 @@ public class BigtableInstanceAdminClientTest { UpdateClusterMetadata> mockUpdateClusterCallable; + @Mock + private OperationCallable< + PartialUpdateClusterRequest, + com.google.bigtable.admin.v2.Cluster, + PartialUpdateClusterMetadata> + mockPartialUpdateClusterCallable; + @Mock private UnaryCallable mockDeleteClusterCallable; @@ -248,6 +273,61 @@ public void testCreateInstance() { assertThat(actualResult).isEqualTo(Instance.fromProto(expectedResponse)); } + @Test + public void testCreateInstanceAutoscaling() { + Mockito.when(mockStub.createInstanceOperationCallable()).thenReturn(mockCreateInstanceCallable); + + // Setup + AutoscalingLimits autoscalingLimits = + AutoscalingLimits.newBuilder().setMaxServeNodes(5).setMinServeNodes(1).build(); + AutoscalingTargets autoscalingTargets = + AutoscalingTargets.newBuilder().setCpuUtilizationPercent(49).build(); + com.google.bigtable.admin.v2.Cluster.ClusterAutoscalingConfig clusterAutoscalingConfig = + com.google.bigtable.admin.v2.Cluster.ClusterAutoscalingConfig.newBuilder() + .setAutoscalingLimits(autoscalingLimits) + .setAutoscalingTargets(autoscalingTargets) + .build(); + com.google.bigtable.admin.v2.CreateInstanceRequest expectedRequest = + com.google.bigtable.admin.v2.CreateInstanceRequest.newBuilder() + .setParent(PROJECT_NAME) + .setInstanceId(INSTANCE_ID) + .setInstance( + com.google.bigtable.admin.v2.Instance.newBuilder() + .setType(com.google.bigtable.admin.v2.Instance.Type.DEVELOPMENT) + .setDisplayName(INSTANCE_ID)) + .putClusters( + "cluster1", + com.google.bigtable.admin.v2.Cluster.newBuilder() + .setLocation("projects/my-project/locations/us-east1-c") + .setClusterConfig( + com.google.bigtable.admin.v2.Cluster.ClusterConfig.newBuilder() + .setClusterAutoscalingConfig(clusterAutoscalingConfig) + .build()) + .setDefaultStorageType(com.google.bigtable.admin.v2.StorageType.SSD) + .build()) + .build(); + + com.google.bigtable.admin.v2.Instance expectedResponse = + com.google.bigtable.admin.v2.Instance.newBuilder().setName(INSTANCE_NAME).build(); + + mockOperationResult(mockCreateInstanceCallable, expectedRequest, expectedResponse); + + // Execute + ClusterAutoscalingConfig autoscalingConfig = + ClusterAutoscalingConfig.of(INSTANCE_ID, "cluster1") + .setCpuUtilizationTargetPercent(49) + .setMaxNodes(5) + .setMinNodes(1); + Instance actualResult = + adminClient.createInstance( + CreateInstanceRequest.of(INSTANCE_ID) + .setType(Instance.Type.DEVELOPMENT) + .addCluster("cluster1", "us-east1-c", autoscalingConfig, StorageType.SSD)); + + // Verify + assertThat(actualResult).isEqualTo(Instance.fromProto(expectedResponse)); + } + @Test public void testUpdateInstance() { // Setup @@ -277,6 +357,35 @@ public void testUpdateInstance() { assertThat(actualResult).isEqualTo(Instance.fromProto(expectedResponse)); } + @Test + public void testUpdateCluster() { + Mockito.when(mockStub.partialUpdateInstanceOperationCallable()) + .thenReturn(mockUpdateInstanceCallable); + + // Setup + com.google.bigtable.admin.v2.PartialUpdateInstanceRequest expectedRequest = + com.google.bigtable.admin.v2.PartialUpdateInstanceRequest.newBuilder() + .setUpdateMask(FieldMask.newBuilder().addPaths("display_name")) + .setInstance( + com.google.bigtable.admin.v2.Instance.newBuilder() + .setName(INSTANCE_NAME) + .setDisplayName("new display name")) + .build(); + + com.google.bigtable.admin.v2.Instance expectedResponse = + com.google.bigtable.admin.v2.Instance.newBuilder().setName(INSTANCE_NAME).build(); + + mockOperationResult(mockUpdateInstanceCallable, expectedRequest, expectedResponse); + + // Execute + Instance actualResult = + adminClient.updateInstance( + UpdateInstanceRequest.of(INSTANCE_ID).setDisplayName("new display name")); + + // Verify + assertThat(actualResult).isEqualTo(Instance.fromProto(expectedResponse)); + } + @Test public void testGetInstance() { // Setup @@ -433,6 +542,40 @@ public void testCreateCluster() { assertThat(actualResult).isEqualTo(Cluster.fromProto(expectedResponse)); } + @Test + public void testCreateClusterAutoscaling() { + Mockito.when(mockStub.createClusterOperationCallable()).thenReturn(mockCreateClusterCallable); + + // Setup + com.google.bigtable.admin.v2.CreateClusterRequest expectedRequest = + com.google.bigtable.admin.v2.CreateClusterRequest.newBuilder() + .setParent(INSTANCE_NAME) + .setClusterId(CLUSTER_ID) + .setCluster( + com.google.bigtable.admin.v2.Cluster.newBuilder() + .setLocation("projects/my-project/locations/us-east1-c") + .setClusterConfig(clusterConfig) + .setDefaultStorageType(com.google.bigtable.admin.v2.StorageType.SSD)) + .build(); + com.google.bigtable.admin.v2.Cluster expectedResponse = + com.google.bigtable.admin.v2.Cluster.newBuilder().setName(CLUSTER_NAME).build(); + mockOperationResult(mockCreateClusterCallable, expectedRequest, expectedResponse); + + // Execute + Cluster actualResult = + adminClient.createCluster( + CreateClusterRequest.of(INSTANCE_ID, CLUSTER_ID) + .setZone("us-east1-c") + .setScalingMode( + ClusterAutoscalingConfig.of(INSTANCE_ID, CLUSTER_ID) + .setMinNodes(2) + .setMaxNodes(10) + .setCpuUtilizationTargetPercent(22)) + .setStorageType(StorageType.SSD)); + // Verify + assertThat(actualResult).isEqualTo(Cluster.fromProto(expectedResponse)); + } + @Test public void testGetCluster() { // Setup @@ -549,6 +692,91 @@ public void testResizeCluster() { assertThat(actualResult).isEqualTo(Cluster.fromProto(expectedResponse)); } + @Test + public void testDisableAutoscaling() { + Mockito.when(mockStub.partialUpdateClusterOperationCallable()) + .thenReturn(mockPartialUpdateClusterCallable); + + // Setup + com.google.bigtable.admin.v2.Cluster cluster = + com.google.bigtable.admin.v2.Cluster.newBuilder() + .setName(CLUSTER_NAME) + .setClusterConfig( + com.google.bigtable.admin.v2.Cluster.ClusterConfig.newBuilder().build()) + .setServeNodes(30) + .build(); + PartialUpdateClusterRequest expectedRequest = + PartialUpdateClusterRequest.newBuilder() + .setCluster(cluster) + .setUpdateMask( + FieldMask.newBuilder() + .addPaths("cluster_config.cluster_autoscaling_config") + .addPaths("serve_nodes") + .build()) + .build(); + + com.google.bigtable.admin.v2.Cluster expectedResponse = + com.google.bigtable.admin.v2.Cluster.newBuilder() + .setName(CLUSTER_NAME) + .setLocation(NameUtil.formatLocationName(PROJECT_ID, "us-east1-c")) + .setServeNodes(30) + .build(); + + mockOperationResult(mockPartialUpdateClusterCallable, expectedRequest, expectedResponse); + + // Execute + Cluster actualResult = adminClient.disableClusterAutoscaling(INSTANCE_ID, CLUSTER_ID, 30); + + // Verify + assertThat(actualResult).isEqualTo(Cluster.fromProto(expectedResponse)); + } + + @Test + public void testPartialUpdateCluster() { + Mockito.when(mockStub.partialUpdateClusterOperationCallable()) + .thenReturn(mockPartialUpdateClusterCallable); + + // Setup + com.google.bigtable.admin.v2.Cluster cluster = + com.google.bigtable.admin.v2.Cluster.newBuilder() + .setName(CLUSTER_NAME) + .setClusterConfig(clusterConfig) + .build(); + + PartialUpdateClusterRequest expectedRequest = + PartialUpdateClusterRequest.newBuilder() + .setCluster(cluster) + .setUpdateMask( + FieldMask.newBuilder() + .addPaths( + "cluster_config.cluster_autoscaling_config.autoscaling_limits.max_serve_nodes") + .addPaths( + "cluster_config.cluster_autoscaling_config.autoscaling_limits.min_serve_nodes") + .addPaths( + "cluster_config.cluster_autoscaling_config.autoscaling_targets.cpu_utilization_percent") + .build()) + .build(); + + com.google.bigtable.admin.v2.Cluster expectedResponse = + com.google.bigtable.admin.v2.Cluster.newBuilder() + .setName(CLUSTER_NAME) + .setLocation(NameUtil.formatLocationName(PROJECT_ID, "us-east1-c")) + .setClusterConfig(clusterConfig) + .build(); + mockOperationResult(mockPartialUpdateClusterCallable, expectedRequest, expectedResponse); + + // Execute + Cluster actualResult = + adminClient.updateClusterAutoscalingConfig( + ClusterAutoscalingConfig.of(INSTANCE_ID, CLUSTER_ID) + .setMaxNodes(10) + .setMinNodes(2) + .setCpuUtilizationTargetPercent(22)); + + // Verify + assertThat(actualResult).isEqualTo(Cluster.fromProto(expectedResponse)); + } + @Test public void testDeleteCluster() { // Setup diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableInstanceAdminClientIT.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableInstanceAdminClientIT.java index 0746a7fd2e..8496561676 100644 --- a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableInstanceAdminClientIT.java +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableInstanceAdminClientIT.java @@ -23,11 +23,13 @@ import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminClient; import com.google.cloud.bigtable.admin.v2.models.AppProfile; import com.google.cloud.bigtable.admin.v2.models.Cluster; +import com.google.cloud.bigtable.admin.v2.models.ClusterAutoscalingConfig; import com.google.cloud.bigtable.admin.v2.models.CreateAppProfileRequest; import com.google.cloud.bigtable.admin.v2.models.CreateClusterRequest; import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest; import com.google.cloud.bigtable.admin.v2.models.Instance; import com.google.cloud.bigtable.admin.v2.models.Instance.Type; +import com.google.cloud.bigtable.admin.v2.models.StaticClusterSize; import com.google.cloud.bigtable.admin.v2.models.StorageType; import com.google.cloud.bigtable.admin.v2.models.UpdateAppProfileRequest; import com.google.cloud.bigtable.admin.v2.models.UpdateInstanceRequest; @@ -282,6 +284,136 @@ public void basicInstanceOperationTest() { assertThat(client.listInstances()).contains(instance); } + @Test + public void createClusterWithAutoscalingTest() { + String newInstanceId = prefixGenerator.newPrefix(); + String newClusterId = newInstanceId + "-c1"; + + try { + client.createInstance( + CreateInstanceRequest.of(newInstanceId) + .addCluster(newClusterId, testEnvRule.env().getPrimaryZone(), 1, StorageType.HDD) + .setDisplayName("Multi-Cluster-Instance-Test") + .addLabel("state", "readytodelete") + .setType(Type.PRODUCTION)); + + String clusterId = prefixGenerator.newPrefix(); + CreateClusterRequest createClusterRequest = + CreateClusterRequest.of(newInstanceId, clusterId) + .setZone(testEnvRule.env().getSecondaryZone()) + .setStorageType(StorageType.HDD) + .setScalingMode( + ClusterAutoscalingConfig.of(newInstanceId, clusterId) + .setMaxNodes(4) + .setMinNodes(1) + .setCpuUtilizationTargetPercent(20)); + + Cluster cluster = client.createCluster(createClusterRequest); + assertThat(cluster.getId()).contains(clusterId); + assertThat(cluster.getServeNodes()).isEqualTo(0); + assertThat(cluster.getAutoscalingMinServeNodes()).isEqualTo(1); + assertThat(cluster.getAutoscalingMaxServeNodes()).isEqualTo(4); + assertThat(cluster.getAutoscalingCpuPercentageTarget()).isEqualTo(20); + } finally { + client.deleteInstance(newInstanceId); + } + } + + @Test + public void createClusterWithAutoscalingAndPartialUpdateTest() { + String newInstanceId = prefixGenerator.newPrefix(); + String newClusterId = newInstanceId + "-c1"; + + try { + client.createInstance( + CreateInstanceRequest.of(newInstanceId) + .addCluster(newClusterId, testEnvRule.env().getPrimaryZone(), 1, StorageType.SSD) + .setDisplayName("Multi-Cluster-Instance-Test") + .addLabel("state", "readytodelete") + .setType(Type.PRODUCTION)); + + String clusterId = prefixGenerator.newPrefix(); + CreateClusterRequest createClusterRequest = + CreateClusterRequest.of(newInstanceId, clusterId) + .setZone(testEnvRule.env().getSecondaryZone()) + .setScalingMode( + ClusterAutoscalingConfig.of("ignored", clusterId) + .setMaxNodes(4) + .setMinNodes(1) + .setCpuUtilizationTargetPercent(20)); + + Cluster cluster = client.createCluster(createClusterRequest); + assertThat(cluster.getId()).contains(clusterId); + assertThat(cluster.getServeNodes()).isEqualTo(0); + assertThat(cluster.getAutoscalingMinServeNodes()).isEqualTo(1); + assertThat(cluster.getAutoscalingMaxServeNodes()).isEqualTo(4); + assertThat(cluster.getAutoscalingCpuPercentageTarget()).isEqualTo(20); + + Cluster updatedCluster = + client.updateClusterAutoscalingConfig( + ClusterAutoscalingConfig.of(newInstanceId, clusterId).setMaxNodes(3)); + assertThat(updatedCluster.getAutoscalingMinServeNodes()).isEqualTo(1); + assertThat(updatedCluster.getAutoscalingMaxServeNodes()).isEqualTo(3); + assertThat(updatedCluster.getAutoscalingCpuPercentageTarget()).isEqualTo(20); + + updatedCluster = + client.updateClusterAutoscalingConfig( + ClusterAutoscalingConfig.of(newInstanceId, clusterId).setMinNodes(2)); + assertThat(updatedCluster.getAutoscalingMinServeNodes()).isEqualTo(2); + assertThat(updatedCluster.getAutoscalingMaxServeNodes()).isEqualTo(3); + assertThat(updatedCluster.getAutoscalingCpuPercentageTarget()).isEqualTo(20); + + updatedCluster = + client.updateClusterAutoscalingConfig( + ClusterAutoscalingConfig.of(newInstanceId, clusterId) + .setCpuUtilizationTargetPercent(40)); + assertThat(updatedCluster.getAutoscalingMinServeNodes()).isEqualTo(2); + assertThat(updatedCluster.getAutoscalingMaxServeNodes()).isEqualTo(3); + assertThat(updatedCluster.getAutoscalingCpuPercentageTarget()).isEqualTo(40); + + updatedCluster = + client.updateClusterAutoscalingConfig( + ClusterAutoscalingConfig.of(newInstanceId, clusterId) + .setCpuUtilizationTargetPercent(45) + .setMaxNodes(5)); + assertThat(updatedCluster.getAutoscalingMinServeNodes()).isEqualTo(2); + assertThat(updatedCluster.getAutoscalingMaxServeNodes()).isEqualTo(5); + assertThat(updatedCluster.getAutoscalingCpuPercentageTarget()).isEqualTo(45); + } finally { + client.deleteInstance(newInstanceId); + } + } + + @Test + public void createClusterWithManualScalingTest() { + String newInstanceId = prefixGenerator.newPrefix(); + String newClusterId = newInstanceId + "-c1"; + + try { + client.createInstance( + CreateInstanceRequest.of(newInstanceId) + .addCluster(newClusterId, testEnvRule.env().getPrimaryZone(), 1, StorageType.SSD) + .setDisplayName("Multi-Cluster-Instance-Test") + .addLabel("state", "readytodelete") + .setType(Type.PRODUCTION)); + + String clusterId = prefixGenerator.newPrefix(); + CreateClusterRequest createClusterRequest = + CreateClusterRequest.of(newInstanceId, clusterId) + .setZone(testEnvRule.env().getSecondaryZone()) + .setScalingMode(StaticClusterSize.of(5)); + + Cluster cluster = client.createCluster(createClusterRequest); + assertThat(cluster.getId()).contains(clusterId); + assertThat(cluster.getServeNodes()).isEqualTo(5); + assertThat(cluster.getAutoscalingMaxServeNodes()).isEqualTo(0); + assertThat(cluster.getAutoscalingMinServeNodes()).isEqualTo(0); + assertThat(cluster.getAutoscalingCpuPercentageTarget()).isEqualTo(0); + } finally { + client.deleteInstance(newInstanceId); + } + } + // To improve test runtime, piggyback off the instance creation/deletion test's fresh instance. private void basicClusterOperationTestHelper(String targetInstanceId, String targetClusterId) { List clusters = client.listClusters(targetInstanceId); @@ -303,5 +435,21 @@ private void basicClusterOperationTestHelper(String targetInstanceId, String tar Cluster resizeCluster = client.resizeCluster(targetInstanceId, targetClusterId, freshNumOfNodes); assertThat(resizeCluster.getServeNodes()).isEqualTo(freshNumOfNodes); + + ClusterAutoscalingConfig autoscalingConfig = + ClusterAutoscalingConfig.of(targetInstanceId, targetClusterId) + .setMinNodes(1) + .setMaxNodes(4) + .setCpuUtilizationTargetPercent(40); + Cluster cluster = client.updateClusterAutoscalingConfig(autoscalingConfig); + assertThat(cluster.getAutoscalingMaxServeNodes()).isEqualTo(4); + assertThat(cluster.getAutoscalingMinServeNodes()).isEqualTo(1); + assertThat(cluster.getAutoscalingCpuPercentageTarget()).isEqualTo(40); + + Cluster updatedCluster = client.disableClusterAutoscaling(targetInstanceId, targetClusterId, 3); + assertThat(updatedCluster.getServeNodes()).isEqualTo(3); + assertThat(updatedCluster.getAutoscalingMaxServeNodes()).isEqualTo(0); + assertThat(updatedCluster.getAutoscalingMinServeNodes()).isEqualTo(0); + assertThat(updatedCluster.getAutoscalingCpuPercentageTarget()).isEqualTo(0); } } diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/models/ClusterAutoscalingConfigTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/models/ClusterAutoscalingConfigTest.java new file mode 100644 index 0000000000..f36bacb675 --- /dev/null +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/models/ClusterAutoscalingConfigTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigtable.admin.v2.models; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.bigtable.admin.v2.AutoscalingLimits; +import com.google.bigtable.admin.v2.AutoscalingTargets; +import com.google.bigtable.admin.v2.Cluster; +import com.google.bigtable.admin.v2.PartialUpdateClusterRequest; +import com.google.cloud.bigtable.admin.v2.internal.NameUtil; +import com.google.protobuf.FieldMask; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ClusterAutoscalingConfigTest { + private static final String PROJECT_ID = "my-project"; + private static final String INSTANCE_ID = "my-instance"; + private static final String CLUSTER_ID = "my-cluster"; + + @Test + public void testToProto() { + ClusterAutoscalingConfig request = + ClusterAutoscalingConfig.of(INSTANCE_ID, CLUSTER_ID) + .setMaxNodes(10) + .setMinNodes(3) + .setCpuUtilizationTargetPercent(30); + + PartialUpdateClusterRequest partialUpdateClusterRequestProto = request.toProto(PROJECT_ID); + + AutoscalingTargets autoscalingTargets = + AutoscalingTargets.newBuilder().setCpuUtilizationPercent(30).build(); + AutoscalingLimits autoscalingLimits = + AutoscalingLimits.newBuilder().setMinServeNodes(3).setMaxServeNodes(10).build(); + Cluster.ClusterAutoscalingConfig clusterAutoscalingConfig = + Cluster.ClusterAutoscalingConfig.newBuilder() + .setAutoscalingTargets(autoscalingTargets) + .setAutoscalingLimits(autoscalingLimits) + .build(); + Cluster.ClusterConfig clusterConfig = + Cluster.ClusterConfig.newBuilder() + .setClusterAutoscalingConfig(clusterAutoscalingConfig) + .build(); + Cluster cluster = + Cluster.newBuilder() + .setName(NameUtil.formatClusterName(PROJECT_ID, INSTANCE_ID, CLUSTER_ID)) + .setClusterConfig(clusterConfig) + .build(); + PartialUpdateClusterRequest requestProto = + PartialUpdateClusterRequest.newBuilder() + .setUpdateMask( + FieldMask.newBuilder() + .addPaths( + "cluster_config.cluster_autoscaling_config.autoscaling_limits.max_serve_nodes") + .addPaths( + "cluster_config.cluster_autoscaling_config.autoscaling_limits.min_serve_nodes") + .addPaths( + "cluster_config.cluster_autoscaling_config.autoscaling_targets.cpu_utilization_percent")) + .setCluster(cluster) + .build(); + assertThat(partialUpdateClusterRequestProto).isEqualTo(requestProto); + } + + @Test + public void testEquality() { + ClusterAutoscalingConfig request = + ClusterAutoscalingConfig.of(INSTANCE_ID, CLUSTER_ID) + .setCpuUtilizationTargetPercent(10) + .setMaxNodes(2) + .setMinNodes(1); + assertThat(request) + .isEqualTo( + ClusterAutoscalingConfig.of(INSTANCE_ID, CLUSTER_ID) + .setCpuUtilizationTargetPercent(10) + .setMaxNodes(2) + .setMinNodes(1)); + assertThat(request) + .isNotEqualTo( + ClusterAutoscalingConfig.of(INSTANCE_ID, CLUSTER_ID) + .setCpuUtilizationTargetPercent(1) + .setMaxNodes(2) + .setMinNodes(1)); + } + + @Test + public void testHashCode() { + ClusterAutoscalingConfig request = + ClusterAutoscalingConfig.of(INSTANCE_ID, CLUSTER_ID).setMaxNodes(10); + assertThat(request.hashCode()) + .isEqualTo(ClusterAutoscalingConfig.of(INSTANCE_ID, CLUSTER_ID).setMaxNodes(10).hashCode()); + assertThat(request.hashCode()) + .isNotEqualTo( + ClusterAutoscalingConfig.of(INSTANCE_ID, CLUSTER_ID).setMinNodes(50).hashCode()); + } +} diff --git a/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/models/StaticClusterSizeTest.java b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/models/StaticClusterSizeTest.java new file mode 100644 index 0000000000..71b1d1bc95 --- /dev/null +++ b/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/models/StaticClusterSizeTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigtable.admin.v2.models; + +import com.google.common.truth.Truth; +import org.junit.Test; + +public class StaticClusterSizeTest { + + @Test + public void testStaticClusterSize() { + StaticClusterSize staticClusterSize = StaticClusterSize.of(4); + Truth.assertThat(staticClusterSize.getClusterSize()).isEqualTo(4); + } +}