diff --git a/src/main/java/org/opensearch/sdk/Extension.java b/src/main/java/org/opensearch/sdk/Extension.java index eea1ca93..54ef2467 100644 --- a/src/main/java/org/opensearch/sdk/Extension.java +++ b/src/main/java/org/opensearch/sdk/Extension.java @@ -10,8 +10,11 @@ import java.io.File; import java.io.IOException; import java.net.URL; +import java.util.Collections; import java.util.List; +import org.opensearch.common.settings.Setting; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -36,6 +39,15 @@ public interface Extension { */ List getExtensionRestHandlers(); + /** + * Gets an optional list of custom {@link Setting} for the extension to register with OpenSearch. + * + * @return a list of custom settings this extension uses. + */ + default List> getSettings() { + return Collections.emptyList(); + } + /** * Helper method to read extension settings from a YAML file. * diff --git a/src/main/java/org/opensearch/sdk/ExtensionRestHandler.java b/src/main/java/org/opensearch/sdk/ExtensionRestHandler.java index e02203eb..eeb11f80 100644 --- a/src/main/java/org/opensearch/sdk/ExtensionRestHandler.java +++ b/src/main/java/org/opensearch/sdk/ExtensionRestHandler.java @@ -23,6 +23,8 @@ public interface ExtensionRestHandler { /** * The list of {@link Route}s that this ExtensionRestHandler is responsible for handling. + * + * @return The routes this handler will handle. */ List routes(); diff --git a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java index 5ae89766..f77b059c 100644 --- a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java +++ b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java @@ -22,8 +22,10 @@ import org.opensearch.extensions.rest.RegisterRestActionsRequest; import org.opensearch.extensions.rest.RestExecuteOnExtensionRequest; import org.opensearch.extensions.rest.RestExecuteOnExtensionResponse; +import org.opensearch.extensions.settings.RegisterCustomSettingsRequest; import org.opensearch.common.network.NetworkModule; import org.opensearch.common.network.NetworkService; +import org.opensearch.common.settings.Setting; import org.opensearch.common.settings.Settings; import org.opensearch.common.util.PageCacheRecycler; import org.opensearch.extensions.ExtensionBooleanResponse; @@ -45,7 +47,7 @@ import org.opensearch.sdk.handlers.ClusterSettingsResponseHandler; import org.opensearch.sdk.handlers.ClusterStateResponseHandler; import org.opensearch.sdk.handlers.LocalNodeResponseHandler; -import org.opensearch.sdk.handlers.RegisterRestActionsResponseHandler; +import org.opensearch.sdk.handlers.ExtensionStringResponseHandler; import org.opensearch.search.SearchModule; import org.opensearch.threadpool.ThreadPool; import org.opensearch.transport.ClusterConnectionManager; @@ -80,8 +82,11 @@ public class ExtensionsRunner { private String uniqueId; private DiscoveryNode opensearchNode; private TransportService extensionTransportService = null; - private ExtensionRestPathRegistry extensionRestPathRegistry = new ExtensionRestPathRegistry(); - + // The routes and classes which handle the REST requests + private final ExtensionRestPathRegistry extensionRestPathRegistry = new ExtensionRestPathRegistry(); + // Custom settings from the extension's getSettings + private final List> customSettings; + // Node name, host, and port private final Settings settings; private final TransportInterceptor NOOP_TRANSPORT_INTERCEPTOR = new TransportInterceptor() { }; @@ -104,6 +109,7 @@ public ExtensionsRunner() throws IOException { .put(TransportSettings.BIND_HOST.getKey(), extensionSettings.getHostAddress()) .put(TransportSettings.PORT.getKey(), extensionSettings.getHostPort()) .build(); + this.customSettings = Collections.emptyList(); } /** @@ -119,12 +125,14 @@ private ExtensionsRunner(Extension extension) throws IOException { .put(TransportSettings.BIND_HOST.getKey(), extensionSettings.getHostAddress()) .put(TransportSettings.PORT.getKey(), extensionSettings.getHostPort()) .build(); - // store rest handlers in the map + // store REST handlers in the registry for (ExtensionRestHandler extensionRestHandler : extension.getExtensionRestHandlers()) { for (Route route : extensionRestHandler.routes()) { extensionRestPathRegistry.registerHandler(route.getMethod(), route.getPath(), extensionRestHandler); } } + // save custom settings + this.customSettings = extension.getSettings(); // initialize the transport service this.initializeExtensionTransportService(this.getSettings()); // start listening on configured port and wait for connection from OpenSearch @@ -171,10 +179,11 @@ InitializeExtensionsResponse handleExtensionInitRequest(InitializeExtensionsRequ try { return new InitializeExtensionsResponse(settings.get(NODE_NAME_SETTING)); } finally { - // After sending successful response to initialization, send the REST API + // After sending successful response to initialization, send the REST API and Settings setOpensearchNode(opensearchNode); extensionTransportService.connectToNode(opensearchNode); sendRegisterRestActionsRequest(extensionTransportService); + sendRegisterCustomSettingsRequest(extensionTransportService); transportActions.sendRegisterTransportActionsRequest(extensionTransportService, opensearchNode); } } @@ -403,7 +412,7 @@ public void startTransportService(TransportService transportService) { public void sendRegisterRestActionsRequest(TransportService transportService) { List extensionRestPaths = extensionRestPathRegistry.getRegisteredPaths(); logger.info("Sending Register REST Actions request to OpenSearch for " + extensionRestPaths); - RegisterRestActionsResponseHandler registerActionsResponseHandler = new RegisterRestActionsResponseHandler(); + ExtensionStringResponseHandler registerActionsResponseHandler = new ExtensionStringResponseHandler(); try { transportService.sendRequest( opensearchNode, @@ -416,6 +425,26 @@ public void sendRegisterRestActionsRequest(TransportService transportService) { } } + /** + * Requests that OpenSearch register the custom settings for this extension. + * + * @param transportService The TransportService defining the connection to OpenSearch. + */ + public void sendRegisterCustomSettingsRequest(TransportService transportService) { + logger.info("Sending Settings request to OpenSearch"); + ExtensionStringResponseHandler registerCustomSettingsResponseHandler = new ExtensionStringResponseHandler(); + try { + transportService.sendRequest( + opensearchNode, + ExtensionsOrchestrator.REQUEST_EXTENSION_REGISTER_CUSTOM_SETTINGS, + new RegisterCustomSettingsRequest(getUniqueId(), customSettings), + registerCustomSettingsResponseHandler + ); + } catch (Exception e) { + logger.info("Failed to send Register Settings request to OpenSearch", e); + } + } + /** * Requests the cluster state from OpenSearch. The result will be handled by a {@link ClusterStateResponseHandler}. * @@ -509,7 +538,7 @@ private Settings getSettings() { * * @param timeout The timeout for the listener in milliseconds. A timeout of 0 means no timeout. */ - public static void startActionListener(int timeout) { + public void startActionListener(int timeout) { final ActionListener actionListener = new ActionListener(); actionListener.runActionListener(true, timeout); } diff --git a/src/main/java/org/opensearch/sdk/SDKClient.java b/src/main/java/org/opensearch/sdk/SDKClient.java index 8d84b058..735243bd 100644 --- a/src/main/java/org/opensearch/sdk/SDKClient.java +++ b/src/main/java/org/opensearch/sdk/SDKClient.java @@ -52,6 +52,7 @@ public OpenSearchClient initializeClient(String hostAddress, int port) throws IO } /** + * Close this client. * * @throws IOException if closing the restClient fails */ diff --git a/src/main/java/org/opensearch/sdk/TransportActions.java b/src/main/java/org/opensearch/sdk/TransportActions.java index 4f071014..49fc8ee9 100644 --- a/src/main/java/org/opensearch/sdk/TransportActions.java +++ b/src/main/java/org/opensearch/sdk/TransportActions.java @@ -15,7 +15,7 @@ import org.opensearch.cluster.node.DiscoveryNode; import org.opensearch.extensions.ExtensionsOrchestrator; import org.opensearch.extensions.RegisterTransportActionsRequest; -import org.opensearch.sdk.handlers.ExtensionResponseHandler; +import org.opensearch.sdk.handlers.ExtensionBooleanResponseHandler; import org.opensearch.transport.TransportService; import java.util.HashMap; @@ -30,6 +30,9 @@ public class TransportActions { /** * Constructor for TransportActions. Creates a map of transportActions for this extension. + * + * @param the TransportAction request + * @param the TransportAction response * @param transportActions is the list of actions the extension would like to register with OpenSearch. */ public TransportActions( @@ -46,7 +49,7 @@ public Transpor */ public void sendRegisterTransportActionsRequest(TransportService transportService, DiscoveryNode opensearchNode) { logger.info("Sending Register Transport Actions request to OpenSearch"); - ExtensionResponseHandler registerTransportActionsResponseHandler = new ExtensionResponseHandler(); + ExtensionBooleanResponseHandler registerTransportActionsResponseHandler = new ExtensionBooleanResponseHandler(); try { transportService.sendRequest( opensearchNode, diff --git a/src/main/java/org/opensearch/sdk/handlers/ExtensionResponseHandler.java b/src/main/java/org/opensearch/sdk/handlers/ExtensionBooleanResponseHandler.java similarity index 90% rename from src/main/java/org/opensearch/sdk/handlers/ExtensionResponseHandler.java rename to src/main/java/org/opensearch/sdk/handlers/ExtensionBooleanResponseHandler.java index e2b22a35..db7c0cab 100644 --- a/src/main/java/org/opensearch/sdk/handlers/ExtensionResponseHandler.java +++ b/src/main/java/org/opensearch/sdk/handlers/ExtensionBooleanResponseHandler.java @@ -20,8 +20,8 @@ /** * This class handles the response {{@link org.opensearch.extensions.ExtensionBooleanResponse }} from OpenSearch to Extension. */ -public class ExtensionResponseHandler implements TransportResponseHandler { - private static final Logger logger = LogManager.getLogger(ExtensionResponseHandler.class); +public class ExtensionBooleanResponseHandler implements TransportResponseHandler { + private static final Logger logger = LogManager.getLogger(ExtensionBooleanResponseHandler.class); @Override public void handleResponse(ExtensionBooleanResponse response) { diff --git a/src/main/java/org/opensearch/sdk/handlers/RegisterRestActionsResponseHandler.java b/src/main/java/org/opensearch/sdk/handlers/ExtensionStringResponseHandler.java similarity index 51% rename from src/main/java/org/opensearch/sdk/handlers/RegisterRestActionsResponseHandler.java rename to src/main/java/org/opensearch/sdk/handlers/ExtensionStringResponseHandler.java index d9f3e944..b257bbf6 100644 --- a/src/main/java/org/opensearch/sdk/handlers/RegisterRestActionsResponseHandler.java +++ b/src/main/java/org/opensearch/sdk/handlers/ExtensionStringResponseHandler.java @@ -10,29 +10,26 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.opensearch.common.io.stream.StreamInput; -import org.opensearch.extensions.rest.RegisterRestActionsResponse; -import org.opensearch.sdk.ExtensionsRunner; +import org.opensearch.extensions.ExtensionStringResponse; import org.opensearch.threadpool.ThreadPool; import org.opensearch.transport.TransportException; import org.opensearch.transport.TransportResponseHandler; -import org.opensearch.transport.TransportService; - import java.io.IOException; /** - * This class handles the response from OpenSearch to a {@link ExtensionsRunner#sendRegisterRestActionsRequest(TransportService)} call. + * This class handles the response from OpenSearch to call returning an {@link ExtensionStringResponse}. */ -public class RegisterRestActionsResponseHandler implements TransportResponseHandler { - private static final Logger logger = LogManager.getLogger(RegisterRestActionsResponseHandler.class); +public class ExtensionStringResponseHandler implements TransportResponseHandler { + private static final Logger logger = LogManager.getLogger(ExtensionStringResponseHandler.class); @Override - public void handleResponse(RegisterRestActionsResponse response) { + public void handleResponse(ExtensionStringResponse response) { logger.info("received {}", response.getResponse()); } @Override public void handleException(TransportException exp) { - logger.info("RegisterActionsRequest failed", exp); + logger.info("Request failed", exp); } @Override @@ -41,7 +38,7 @@ public String executor() { } @Override - public RegisterRestActionsResponse read(StreamInput in) throws IOException { - return new RegisterRestActionsResponse(in); + public ExtensionStringResponse read(StreamInput in) throws IOException { + return new ExtensionStringResponse(in); } } diff --git a/src/test/java/org/opensearch/sdk/TestExtensionTransportActionsAPI.java b/src/test/java/org/opensearch/sdk/TestExtensionTransportActionsAPI.java index 86f85b26..a998be53 100644 --- a/src/test/java/org/opensearch/sdk/TestExtensionTransportActionsAPI.java +++ b/src/test/java/org/opensearch/sdk/TestExtensionTransportActionsAPI.java @@ -13,7 +13,7 @@ import org.opensearch.common.settings.Settings; import org.opensearch.common.transport.TransportAddress; import org.opensearch.extensions.ExtensionsOrchestrator; -import org.opensearch.sdk.handlers.ExtensionResponseHandler; +import org.opensearch.sdk.handlers.ExtensionBooleanResponseHandler; import org.opensearch.tasks.Task; import org.opensearch.test.OpenSearchTestCase; import org.opensearch.transport.Transport; @@ -87,7 +87,7 @@ public void testRegisterTransportAction() { any(), eq(ExtensionsOrchestrator.REQUEST_EXTENSION_REGISTER_TRANSPORT_ACTIONS), any(), - any(ExtensionResponseHandler.class) + any(ExtensionBooleanResponseHandler.class) ); } } diff --git a/src/test/java/org/opensearch/sdk/TestExtensionsRunner.java b/src/test/java/org/opensearch/sdk/TestExtensionsRunner.java index eec549ad..5573e891 100644 --- a/src/test/java/org/opensearch/sdk/TestExtensionsRunner.java +++ b/src/test/java/org/opensearch/sdk/TestExtensionsRunner.java @@ -49,7 +49,7 @@ import org.opensearch.sdk.handlers.ClusterSettingsResponseHandler; import org.opensearch.sdk.handlers.ClusterStateResponseHandler; import org.opensearch.sdk.handlers.LocalNodeResponseHandler; -import org.opensearch.sdk.handlers.RegisterRestActionsResponseHandler; +import org.opensearch.sdk.handlers.ExtensionStringResponseHandler; import org.opensearch.test.OpenSearchTestCase; import org.opensearch.transport.Transport; import org.opensearch.transport.TransportService; @@ -198,6 +198,14 @@ public void testRegisterRestActionsRequest() { extensionsRunner.sendRegisterRestActionsRequest(transportService); - verify(transportService, times(1)).sendRequest(any(), anyString(), any(), any(RegisterRestActionsResponseHandler.class)); + verify(transportService, times(1)).sendRequest(any(), anyString(), any(), any(ExtensionStringResponseHandler.class)); + } + + @Test + public void testRegisterCustomSettingsRequest() { + + extensionsRunner.sendRegisterCustomSettingsRequest(transportService); + + verify(transportService, times(1)).sendRequest(any(), anyString(), any(), any(ExtensionStringResponseHandler.class)); } }