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.
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.
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.
Perhaps there's a better way to get to the allocationDeciders without injection?
henningandersen
left a comment
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Can we not simply defer the construction of this until reservedClusterStateHandlers? That seems more intuitive to me.
There was a problem hiding this comment.
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.
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.
I think this can be private?
| return NAME; | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") |
There was a problem hiding this comment.
Can this be moved to the statement?
| } | ||
|
|
||
| @Override | ||
| public TransformState transform(Object source, TransformState prevState) throws Exception { |
There was a problem hiding this comment.
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.
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.
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