-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Autoscaler #1077
feat: Autoscaler #1077
Conversation
@@ -75,7 +76,10 @@ export type GetClustersCallback = ( | |||
apiResponse?: google.bigtable.admin.v2.IListClustersResponse | |||
) => void; | |||
export interface SetClusterMetadataOptions { | |||
nodes: number; | |||
nodes?: number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this considered breaking if we change something from required to optional? I'm guessing it would be the other way around, but want to confirm :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we are changing something from required to optional so that would make it not a breaking change since users can still pass just nodes
in. This is where we make nodes
optional because instead the user can provide autoscaling parameters. These parameters will be validated against a new validation function and an error will be thrown if an invalid combination of parameters are provided.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not consider switching from required to optional for TypeScript breaking 👍
if ( | ||
metadata.cpuUtilizationPercent || | ||
metadata.minServeNodes || | ||
metadata.maxServeNodes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens if only one of these are set? Let's say metadata.minServeNodes
= 4, but the rest are unset. Could that cause issues?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we use this in instance.ts
we validate beforehand so in this case an error would be thrown as required, but after investigating this further, I think I will add validation to createInstance
as well to make sure an error gets thrown if properties are not set properly for each cluster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When creating instances we now validate inputs.
system-test/cluster.ts
Outdated
assert.equal(e.message, ClusterUtils.noConfigError); | ||
} | ||
}); | ||
it('By providing too much cluster configurations', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - reword to express that the user entered manual AND autoscaling configurations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial follow-up to first review.
if ( | ||
metadata.cpuUtilizationPercent || | ||
metadata.minServeNodes || | ||
metadata.maxServeNodes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we use this in instance.ts
we validate beforehand so in this case an error would be thrown as required, but after investigating this further, I think I will add validation to createInstance
as well to make sure an error gets thrown if properties are not set properly for each cluster.
system-test/cluster.ts
Outdated
assert.equal(e.message, ClusterUtils.noConfigError); | ||
} | ||
}); | ||
it('By providing too much cluster configurations', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
system-test/cluster.ts
Outdated
it('Create an instance with clusters for manual scaling', async () => { | ||
await checkMetadata(cluster, 2); | ||
}); | ||
it('Create an instance and then create a cluster for manual scaling', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - here and in all other it(..
descriptions, I think they should be reworded slightly; for example, here I would change it to say:
it('should create an instance and then create a cluster with manual scaling')
Let me know your thoughts :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good point. I'll look at some of the other PRs and make sure that they have these descriptions as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed two more outstanding comments
system-test/cluster.ts
Outdated
it('Create an instance with clusters for manual scaling', async () => { | ||
await checkMetadata(cluster, 2); | ||
}); | ||
it('Create an instance and then create a cluster for manual scaling', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good point. I'll look at some of the other PRs and make sure that they have these descriptions as well.
if ( | ||
metadata.cpuUtilizationPercent || | ||
metadata.minServeNodes || | ||
metadata.maxServeNodes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When creating instances we now validate inputs.
src/utils/cluster.ts
Outdated
static incompleteConfigError = | ||
'All of autoscaling configurations must be specified at the same time (min_serve_nodes, max_serve_nodes, and cpu_utilization_percent).'; | ||
|
||
static validateMetadata( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename this validateCreateClusterMetadata
as we are checking for all autoscaling settings set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about validateClusterMetadata
since sometimes this check is done when updating a cluster as well as creating it?
system-test/cluster.ts
Outdated
assert.equal(e.message, ClusterUtils.allConfigError); | ||
} | ||
}); | ||
it('should throw an error providing all autoscaling configurations', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this say "should throw an error when missing some autoscaling configurations"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes!
}); | ||
it('should create an instance and then create clusters for automatic scaling', async () => { | ||
const clusterId: string = generateId('cluster'); | ||
await createStandardNewInstance(clusterId, 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we creating a cluster with manual scaling for this test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is designed to capture a particular edge case. The test before this already covers the case where we create an instance that has clusters with automatic scaling. In this case we want to make sure everything works if we create an instance and then create a cluster since that user experience uses a different function entirely.
This test case does the following:
createStandardNewInstance
creates an instance with a cluster that has manual scalingcluster.create(createClusterOptions)
creates a cluster with automatic scaling on this instancecheckMetadata
ensures that the metadata for the cluster created with automatic scaling hasnodes
,minServeNodes
,maxServeNodes
,cpuUtilizationPercent
set correctly.
system-test/cluster.ts
Outdated
|
||
it('should change nodes for manual scaling', async () => { | ||
const updateNodes = 5; | ||
assert.notEqual(startingNodes, updateNodes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this check is comparing two int variables - if you want to have this, I would instead get the creater cluster's nodes, then compare the created cluster's nodes to the updateNodes value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
checkMetadata
does the second thing you mentioned though it checks metadata.serveNodes
equals updateNodes
rather than checking metadata.serveNodes
does not equal startingNodes
. This assert.notEqual
is more of a maintainability thing to ensure the programmer doesn't set updateNodes
to equal startingNodes
and then have the test pass when setMetadata
doesn't actually work properly. If it's confusing though then we can remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is providing much in terms of autoscaling assertions, so I would remove it in favor of the checks you already mentioned.
system-test/cluster.ts
Outdated
}); | ||
}); | ||
describe('Update cluster', () => { | ||
describe('Starting from manual scaling', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename this description to something like "updating manual scaling for a cluster"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
system-test/cluster.ts
Outdated
assert.equal(e.message, ClusterUtils.allConfigError); | ||
} | ||
}); | ||
it('should throw an error providing all autoscaling configurations', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this is the wrong description for this test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. This is a confusing error. Related to the comment above. Changing this now.
async function checkMetadata( | ||
cluster: Cluster, | ||
compareValues: SetClusterMetadataOptions, | ||
isConfigDefined: boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we passing this into this function? Shouldn't we be able to determine this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is meant to be the expected value rather than the actual value of an assertion check. The purpose of passing isConfigDefined
in is just to make sure the test is more thorough. For example, if we have a test that creates a cluster with automatic scaling and then we find the metadata fetched has no clusterConfig defined then we want it to fail on the line of code that says:
assert.equal(isConfigDefined, false);
src/cluster.ts
Outdated
callback(err, resp); | ||
} | ||
); | ||
const setMetadataWithLocation = (location: string, name: string) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove this logic if we think it's currently not needed based on your testing.
src/utils/cluster.ts
Outdated
metadata | ||
); | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
delete (cluster as any).nodes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you should have to case to any
, assuming that these are properties on ICluster
.
…into autoscaler # Conflicts: # test/cluster.ts
This feature allows the user to set properties when creating a cluster or updating a cluster that turn on the autoscaler or turn it off to use manual scaling.