Skip to content
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

[Extensions] Add DynamicActionRegistry to ActionModule #6734

Merged
merged 30 commits into from
Mar 24, 2023

Conversation

dbwiddis
Copy link
Member

@dbwiddis dbwiddis commented Mar 17, 2023

Companion PR: SDK #588. This PR must be merged first.

Description

Adds a DynamicActionRegistry class and instance field to the ActionModule.

TransportAction classes from OpenSearch and plugins are instantiated during Node bootstrap and injected as singletons.

Extensions have the need to proxy actions between extensions. For example, job scheduler needs to invoke actions on Anomaly Detector extension; Anomaly Detector may need to invoke actions on Alerting Extension; et. al. This capability is currently implemented with a single ProxyAction which relays these invocations blindly.

This PR adds a registry for Extensions to register and unregister classes which extend ActionType and TransportAction at times other than bootstrap.

The benefit of using a subclass of TransportAction is that the client.execute() invocation processes these actions through ActionFilters. The first such filter processed is in the security plugin and this provides a single point of contact for future application of security features.

Inspiration for some of these features: #4460 (but I did it my way)

Description of functionality:

  • On bootstrap, ActionModule creates an registry with two internal maps; one corresponds to the actions map obtained from the injector, which is immutable, and an empty registry for addition (and potentially removal) of extension actions
  • During Extension initialization, the getActions() extension point will be handled on OpenSearch by the ExtensionTransportActionsHandler which will register (in the registry) a custom subclass of the ActionType containing the fully qualified class name of the action on the Extension
    • There is no current usage of the implemented "unregister" functionality, but the capability is provided for future "hot swap" functionality.
  • When one extension (or OpenSearch or a plugin) wants to invoke an action on an extension, that will be handled by the NodeClient's client.execute() path. This path uses associated ActionFilters and the potential for future checks and security/identity integration.
  • The execution of this TransportAction will send it to the Extension for further processing (TBD in Companion PR).

Issues Resolved

Fixes SDK #107.

Companion PR implements SDK #525.

SDK #525 could be implemented using the existing ProxyAction setup that this PR replaces, but I believe the benefits of funneling all requests through a single touch point is a significant benefit and combined these efforts.

Check List

  • New functionality includes testing.
    • All tests pass
  • New functionality has been documented.
    • New functionality has javadoc added
  • Commits are signed per the DCO using --signoff
    Commit changes are listed out in CHANGELOG.md file (See: Changelog)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

Copy link
Member

@peternied peternied left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I like the steps forward to consolidating all actions together. I've put in some notes about coupling and how the abstraction could work a little differently that I think could be more flexible.

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

}
actionsMap.putIfAbsent(action, extension);
// Register the action in the action module's extension actions map
dynamicActionRegistry.registerExtensionAction(new ExtensionAction(action, extension.getId()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the action requires parameters then how will then be sent to the extension?

Copy link
Member Author

@dbwiddis dbwiddis Mar 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ExtensionAction here is just a subclass of ActionType which is an instance used as the key to a map. The value corresponding to this is an ExtensionTransportAction with the same name, that references the ExtensionActionRequest and ExtensionActionResponse classes.

That ExtensionActionRequest is how the details are communicated, with an action string (a fully qualified class name that the extension will match to one of its existing getAction() actions) and a byte array which will represent the parameters (serialized from the action's ActionRequest). Those will be serialized and deserialized consistently.... currently with Writeable but we'll probably switch to protobuf.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for protobufs

Copy link
Member

@peternied peternied left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the refactor 👍

@owaiskazi19
Copy link
Member

Overall looks good @dbwiddis. Small ask: would love to see a design diagram for the workflow in the SDK repository. Since we are touching the ActionModule here would be great to get some eyes from @reta @nknize

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

  • RESULT: UNSTABLE ❕
  • TEST FAILURES:
      1 org.opensearch.indices.replication.SegmentReplicationAllocationIT.testSingleIndexShardAllocation

@codecov-commenter
Copy link

codecov-commenter commented Mar 18, 2023

Codecov Report

Merging #6734 (3abbeb2) into main (5f81930) will decrease coverage by 0.05%.
The diff coverage is 79.34%.

📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

@@             Coverage Diff              @@
##               main    #6734      +/-   ##
============================================
- Coverage     70.74%   70.69%   -0.05%     
+ Complexity    59203    59195       -8     
============================================
  Files          4810     4809       -1     
  Lines        283487   283536      +49     
  Branches      40877    40885       +8     
============================================
- Hits         200543   200440     -103     
- Misses        66465    66624     +159     
+ Partials      16479    16472       -7     
Impacted Files Coverage Δ
...nsions/action/RegisterTransportActionsRequest.java 85.00% <ø> (ø)
...ns/action/TransportActionRequestFromExtension.java 66.66% <0.00%> (-2.57%) ⬇️
...ava/org/opensearch/test/client/NoOpNodeClient.java 27.77% <ø> (ø)
...sions/action/ExtensionTransportActionsHandler.java 47.31% <57.14%> (-8.94%) ⬇️
.../opensearch/extensions/action/ExtensionAction.java 61.53% <61.53%> (ø)
...in/java/org/opensearch/client/node/NodeClient.java 71.42% <66.66%> (ø)
.../main/java/org/opensearch/action/ActionModule.java 97.83% <100.00%> (+0.73%) ⬆️
...a/org/opensearch/extensions/ExtensionsManager.java 45.45% <100.00%> (ø)
...rch/extensions/action/ExtensionActionResponse.java 100.00% <100.00%> (ø)
...ch/extensions/action/ExtensionTransportAction.java 37.50% <100.00%> (+37.50%) ⬆️
... and 1 more

... and 483 files with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Daniel Widdis <widdis@gmail.com>
@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@ryanbogan ryanbogan merged commit 9febe10 into opensearch-project:main Mar 24, 2023
@dbwiddis dbwiddis deleted the dynamicActions branch March 24, 2023 19:43
@ryanbogan ryanbogan added the backport 2.x Backport to 2.x branch label Mar 24, 2023
opensearch-trigger-bot bot pushed a commit that referenced this pull request Mar 24, 2023
* Add dynamic action registry to ActionModule

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Update registration of transport actions

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Generate transport actions dynamically

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Refactor to combine registry internals

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Finally figured out the generics (or lack thereof)

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* ExtensionProxyAction is dead! Long live ExtensionAction!

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Simplify ExtensionTransportActionHandler, fix compile issues

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Maybe tests will pass with this commit

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* I guess you can't use null as a key in a map

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Lazy test setup, but this should finally work

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Add Tests

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix TransportActionRequestFromExtension inheritance

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix return type for transport actions from extensions

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix ParametersInWrongOrderError and add some preemptive null handling

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* NPE is not expected result if params are in correct order

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Remove redundant class and string parsing, add success boolean

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Last fix of params out of order. Working test case!

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Code worked, tests didn't. This is finally done (I think)

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Add more detail to comments on immutable vs. dynamic maps

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Add StreamInput getter to ExtensionActionResponse

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Generalize dynamic action registration

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Comment and naming fixes

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Register method renaming

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Add generic type parameters

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Improve/simplify which parameter types get passed

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Revert removal of ProxyAction and changes to transport and requests

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Wrap ExtensionTransportResponse in a class denoting success

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Remove generic types as they are incompatible with Guice injection

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix response handling, it works (again)

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix up comments and remove debug logging

Signed-off-by: Daniel Widdis <widdis@gmail.com>

---------

Signed-off-by: Daniel Widdis <widdis@gmail.com>
(cherry picked from commit 9febe10)
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
saratvemulapalli pushed a commit that referenced this pull request Mar 28, 2023
* Add dynamic action registry to ActionModule



* Update registration of transport actions



* Generate transport actions dynamically



* Refactor to combine registry internals



* Finally figured out the generics (or lack thereof)



* ExtensionProxyAction is dead! Long live ExtensionAction!



* Simplify ExtensionTransportActionHandler, fix compile issues



* Maybe tests will pass with this commit



* I guess you can't use null as a key in a map



* Lazy test setup, but this should finally work



* Add Tests



* Fix TransportActionRequestFromExtension inheritance



* Fix return type for transport actions from extensions



* Fix ParametersInWrongOrderError and add some preemptive null handling



* NPE is not expected result if params are in correct order



* Remove redundant class and string parsing, add success boolean



* Last fix of params out of order. Working test case!



* Code worked, tests didn't. This is finally done (I think)



* Add more detail to comments on immutable vs. dynamic maps



* Add StreamInput getter to ExtensionActionResponse



* Generalize dynamic action registration



* Comment and naming fixes



* Register method renaming



* Add generic type parameters



* Improve/simplify which parameter types get passed



* Revert removal of ProxyAction and changes to transport and requests



* Wrap ExtensionTransportResponse in a class denoting success



* Remove generic types as they are incompatible with Guice injection



* Fix response handling, it works (again)



* Fix up comments and remove debug logging



---------


(cherry picked from commit 9febe10)

Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Rishikesh1159 added a commit to Rishikesh1159/OpenSearch that referenced this pull request Mar 30, 2023
mitrofmep pushed a commit to mitrofmep/OpenSearch that referenced this pull request Apr 5, 2023
…oject#6734)

* Add dynamic action registry to ActionModule

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Update registration of transport actions

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Generate transport actions dynamically

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Refactor to combine registry internals

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Finally figured out the generics (or lack thereof)

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* ExtensionProxyAction is dead! Long live ExtensionAction!

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Simplify ExtensionTransportActionHandler, fix compile issues

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Maybe tests will pass with this commit

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* I guess you can't use null as a key in a map

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Lazy test setup, but this should finally work

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Add Tests

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix TransportActionRequestFromExtension inheritance

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix return type for transport actions from extensions

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix ParametersInWrongOrderError and add some preemptive null handling

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* NPE is not expected result if params are in correct order

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Remove redundant class and string parsing, add success boolean

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Last fix of params out of order. Working test case!

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Code worked, tests didn't. This is finally done (I think)

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Add more detail to comments on immutable vs. dynamic maps

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Add StreamInput getter to ExtensionActionResponse

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Generalize dynamic action registration

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Comment and naming fixes

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Register method renaming

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Add generic type parameters

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Improve/simplify which parameter types get passed

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Revert removal of ProxyAction and changes to transport and requests

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Wrap ExtensionTransportResponse in a class denoting success

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Remove generic types as they are incompatible with Guice injection

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix response handling, it works (again)

Signed-off-by: Daniel Widdis <widdis@gmail.com>

* Fix up comments and remove debug logging

Signed-off-by: Daniel Widdis <widdis@gmail.com>

---------

Signed-off-by: Daniel Widdis <widdis@gmail.com>
Signed-off-by: Valentin Mitrofanov <mitrofmep@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport 2.x Backport to 2.x branch skip-changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

GetActions: Add support to dynamically register actions
10 participants