-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Operator/autoscaling #89708
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
Operator/autoscaling #89708
Conversation
We can now load the handler when the plugin loads.
We can now load the handler when the plugin loads in tests
|
Hi @grcevski, I've created a changelog YAML for you. |
|
Pinging @elastic/es-core-infra (Team:Core/Infra) |
|
|
||
| private RerouteService rerouteService; | ||
|
|
||
| private AllocationService allocationService; |
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'm looking for suggestions if this can be made better. Right now the allocationDeciders are injected in the TransportActions that autoscaling uses, but I can't use injection since we made a design decision to use SPI for the reserved state handlers.
Essentially, I need a way to get to the allocationDeciders to be able to create/pass the validator in to the transport action transformation methods.
| /** | ||
| * Autoscaling provider implementation for the {@link ReservedClusterStateHandlerProvider} service interface | ||
| */ | ||
| public class LocalStateReservedAutoscalingStateHandlerProvider implements ReservedClusterStateHandlerProvider { |
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 a clone of the regular plugin SPI state handler provider for integration test purposes.
| state = TransportPutAutoscalingPolicyAction.putAutoscalingPolicy( | ||
| state, | ||
| request, | ||
| policyValidatorHolder.get(clusterService.getAllocationService().getAllocationDeciders()) |
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.
Perhaps there's a better way to get to the allocationDeciders without injection?
henningandersen
left a comment
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 mostly focused on how to provide the allocation deciders and left a comment on that. I'd prefer to defer the rest of the review until that is tackled.
| return rerouteService; | ||
| } | ||
|
|
||
| public void setAllocationService(AllocationService allocationService) { |
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 I'd prefer to either:
- Support injection for the reserved state plugins.
- Add an explicit AllocationDecidersProvider object that is passed to Plugin.createComponents that can be used to access this.
Putting it here is polluting this class I think with responsibilities that does not concern 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 think I'd prefer to either:
- Support injection for the reserved state plugins.
- Add an explicit AllocationDecidersProvider object that is passed to Plugin.createComponents that can be used to access this.
Putting it here is polluting this class I think with responsibilities that does not concern it.
Thanks for reviewing this Henning. I took approach 2. and added the AllocationDeciders provider.
|
@elasticsearchmachine run elasticsearch-ci/bwc |
henningandersen
left a comment
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 got what I asked for 🙂 , unfortunately it resulted in quite many changed files. Can we make the allocationDeciders change in a separate PR first, such that this PR gets easier to review? I added a couple of comments to the allocationDeciders change that should be carried over to the new PR as well.
| repositoriesServiceReference::get, | ||
| tracer | ||
| tracer, | ||
| clusterModule.getAllocationService()::getAllocationDeciders |
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.
Since getAllcationDeciders returns a final field, I think this means that we have the list of deciders already and might as well pass the object directly instead of a supplier of it?
| var capacityServiceHolder = new AutoscalingCalculateCapacityService.Holder(this); | ||
| reservedAutoscalingPolicyAction.set(new ReservedAutoscalingPolicyAction(capacityServiceHolder, allocationDecidersSupplier)); |
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.
Since we now have the list of deciders directly, could we not as well just set it directly here rather than pass it around in several places? I.e., add:
this.allocationDeciders.set(deciders);
and remove it from the argument to ReservedAutoscalingPolicyAction as well as from being injected into the two transport services that gets it (only to pass it to the plugin).
Sounds good. I'll split this off in another PR and mark this in draft until that's merged. Thanks again for the review! |
|
|
||
| // package private for testing | ||
| Path operatorSettingsDir() { | ||
| public Path operatorSettingsDir() { |
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.
Exposed for easier test writing.
| /** | ||
| * Autoscaling provider implementation for the {@link ReservedClusterStateHandlerProvider} service interface | ||
| */ | ||
| public class LocalStateReservedAutoscalingStateHandlerProvider implements ReservedClusterStateHandlerProvider { |
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.
Mock version of the SPI handler provider so that we can write Java integration tests. It implements equals and hashcode so we deduplicate the plugin, as it can be discovered multiple times in the MockNode because all plugins are loaded by the same classloader.
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 we not fix that in MockNode instead? I am not sure I follow the equals/hashCode problem, but sounds like we are relying on MockNode using a Set to collect these providers?
|
Hi @grcevski, I've updated the changelog YAML for you. |
|
@elasticsearchmachine run elasticsearch-ci/part-1 |
…rch into operator/autoscaling
henningandersen
left a comment
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.
LGTM.
Left a number of comments I'd prefer to see included.
| import java.util.Objects; | ||
|
|
||
| /** | ||
| * Autoscaling provider implementation for the {@link ReservedClusterStateHandlerProvider} service interface |
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.
Can you add a comment explaining why we need this test override? It is not clear to me and I'd rather read it than find out.
| /** | ||
| * Autoscaling provider implementation for the {@link ReservedClusterStateHandlerProvider} service interface | ||
| */ | ||
| public class LocalStateReservedAutoscalingStateHandlerProvider implements ReservedClusterStateHandlerProvider { |
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 we not fix that in MockNode instead? I am not sure I follow the equals/hashCode problem, but sounds like we are relying on MockNode using a Set to collect these providers?
| this.clusterServiceHolder.set(clusterService); | ||
| this.allocationDeciders.set(allocationDeciders); | ||
| var capacityServiceHolder = new AutoscalingCalculateCapacityService.Holder(this); | ||
| this.reservedAutoscalingPolicyAction.set(new ReservedAutoscalingPolicyAction(capacityServiceHolder)); |
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.
Can we not simply defer the construction of this until reservedClusterStateHandlers? That seems more intuitive to me.
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 avoided doing that because then I'd have to also keep a local reference to the AutoscalingCalculateCapacityService.Holder, I need it to construct the action object.
|
|
||
| @Override | ||
| public TransformState transform(Object source, TransformState prevState) throws Exception { | ||
| var requests = prepare(source); |
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.
Can we do the casting here rather than in prepare? That avoids SuppressWarnings and also seems more appropriate to deal with input validation immediately in this method.
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| public Collection<PutAutoscalingPolicyAction.Request> prepare(Object input) { |
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 can be private?
| return NAME; | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") |
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.
Can this be moved to the statement?
| } | ||
|
|
||
| @Override | ||
| public TransformState transform(Object source, TransformState prevState) throws Exception { |
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.
Could this not get the right type instead? Seems it is T at the interface level and the call in ReservedStateUpdateTask can be massaged to fix this. The service does "guarantee" it, since it only passes output of fromXContent to this method.
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.
On the caller side in ReservedStateUpdateTask I have a composite object containing the data for all of the handlers. I parse everything first in a map of String key to data type required by the handler, but I can't retain the type information because the data types are in classes provided by plugins and the server doesn't know of them.
|
|
||
| prevState = updatedState; | ||
| updatedState = processJSON(action, prevState, json); | ||
| assertThat(updatedState.keys(), containsInAnyOrder("my_autoscaling_policy", "my_autoscaling_policy_1")); |
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.
Can we also validate that the roles and deciders are correct in cluster state?
This PR adds support for /_autoscaling/policy for file based settings. The PR uses similar approach in how we handled ILM policies, where we load the state handlers through SPI.
Relates to #89183