diff --git a/src/main/java/org/opensearch/sdk/ExtensionSettings.java b/src/main/java/org/opensearch/sdk/ExtensionSettings.java index 5d93663c..8c7a0043 100644 --- a/src/main/java/org/opensearch/sdk/ExtensionSettings.java +++ b/src/main/java/org/opensearch/sdk/ExtensionSettings.java @@ -49,10 +49,12 @@ public class ExtensionSettings { private String extensionName; + private String shortExtensionName; private String hostAddress; private String hostPort; private String opensearchAddress; private String opensearchPort; + private Map securitySettings; /** * A set of keys for security settings related to SSL transport, keystore and truststore files, and hostname verification. @@ -83,8 +85,6 @@ public class ExtensionSettings { SSL_TRANSPORT_TRUSTSTORE_TYPE ); - private Map securitySettings; - /** * Jackson requires a no-arg constructor. */ @@ -97,14 +97,23 @@ private ExtensionSettings() { * Instantiate this class using the specified parameters. * * @param extensionName The extension name. Provided to OpenSearch as a response to initialization query. Must match the defined extension name in OpenSearch. + * @param shortExtensionName The shortened name for the extension * @param hostAddress The IP Address to bind this extension to. * @param hostPort The port to bind this extension to. * @param opensearchAddress The IP Address on which OpenSearch is running. * @param opensearchPort The port on which OpenSearch is running. */ - public ExtensionSettings(String extensionName, String hostAddress, String hostPort, String opensearchAddress, String opensearchPort) { + public ExtensionSettings( + String extensionName, + String shortExtensionName, + String hostAddress, + String hostPort, + String opensearchAddress, + String opensearchPort + ) { super(); this.extensionName = extensionName; + this.shortExtensionName = shortExtensionName; this.hostAddress = hostAddress; this.hostPort = hostPort; this.opensearchAddress = opensearchAddress; @@ -116,6 +125,7 @@ public ExtensionSettings(String extensionName, String hostAddress, String hostPo * Instantiate this class using the specified parameters. * * @param extensionName The extension name. Provided to OpenSearch as a response to initialization query. Must match the defined extension name in OpenSearch. + * @param shortExtensionName The shortened name for the extension * @param hostAddress The IP Address to bind this extension to. * @param hostPort The port to bind this extension to. * @param opensearchAddress The IP Address on which OpenSearch is running. @@ -124,13 +134,14 @@ public ExtensionSettings(String extensionName, String hostAddress, String hostPo */ public ExtensionSettings( String extensionName, + String shortExtensionName, String hostAddress, String hostPort, String opensearchAddress, String opensearchPort, Map securitySettings ) { - this(extensionName, hostAddress, hostPort, opensearchAddress, opensearchPort); + this(extensionName, shortExtensionName, hostAddress, hostPort, opensearchAddress, opensearchPort); this.securitySettings = securitySettings; } @@ -142,6 +153,10 @@ public String getExtensionName() { return extensionName; } + public String getShortExtensionName() { + return shortExtensionName; + } + /** * Returns the host address associated with this object. * @return The host address as a string. @@ -203,6 +218,8 @@ public Map getSecuritySettings() { public String toString() { return "ExtensionSettings{extensionName=" + extensionName + + ", shortName=" + + shortExtensionName + ", hostAddress=" + hostAddress + ", hostPort=" @@ -242,6 +259,7 @@ public static ExtensionSettings readSettingsFromYaml(String extensionSettingsPat } return new ExtensionSettings( extensionMap.get("extensionName").toString(), + extensionMap.get("shortExtensionName").toString(), extensionMap.get("hostAddress").toString(), extensionMap.get("hostPort").toString(), extensionMap.get("opensearchAddress").toString(), diff --git a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java index 8f73e799..72818a9e 100644 --- a/src/main/java/org/opensearch/sdk/ExtensionsRunner.java +++ b/src/main/java/org/opensearch/sdk/ExtensionsRunner.java @@ -20,6 +20,7 @@ import org.opensearch.cluster.metadata.IndexNameExpressionResolver; import org.opensearch.common.io.stream.NamedWriteableRegistry; import org.opensearch.extensions.rest.ExtensionRestRequest; +import org.opensearch.extensions.rest.RouteHandler; import org.opensearch.common.settings.Setting; import org.opensearch.common.settings.Settings; import org.opensearch.core.xcontent.NamedXContentRegistry; @@ -28,6 +29,7 @@ import org.opensearch.extensions.ExtensionsManager; import org.opensearch.extensions.UpdateSettingsRequest; import org.opensearch.extensions.action.ExtensionActionRequest; +import org.opensearch.rest.RestHandler; import org.opensearch.sdk.action.SDKActionModule; import org.opensearch.sdk.api.ActionExtension; import org.opensearch.sdk.handlers.ExtensionActionRequestHandler; @@ -36,6 +38,7 @@ import org.opensearch.sdk.handlers.ExtensionsInitRequestHandler; import org.opensearch.sdk.handlers.ExtensionsRestRequestHandler; import org.opensearch.sdk.handlers.UpdateSettingsRequestHandler; +import org.opensearch.sdk.rest.BaseExtensionRestHandler; import org.opensearch.sdk.rest.ExtensionRestHandler; import org.opensearch.sdk.rest.ExtensionRestPathRegistry; import org.opensearch.tasks.TaskManager; @@ -52,6 +55,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @@ -232,7 +236,16 @@ protected ExtensionsRunner(Extension extension) throws IOException { if (extension instanceof ActionExtension) { // store REST handlers in the registry for (ExtensionRestHandler extensionRestHandler : ((ActionExtension) extension).getExtensionRestHandlers()) { - extensionRestPathRegistry.registerHandler(extensionRestHandler); + if (extensionRestHandler instanceof BaseExtensionRestHandler) { + ((BaseExtensionRestHandler) extensionRestHandler).setExtensionShortName(extensionSettings.getShortExtensionName()); + } + for (RestHandler.Route route : extensionRestHandler.routes()) { + Optional routeActionName = Optional.empty(); + if (route instanceof RouteHandler && ((RouteHandler) route).name() != null) { + routeActionName = Optional.of(((RouteHandler) route).name()); + } + extensionRestPathRegistry.registerHandler(route.getMethod(), route.getPath(), routeActionName, extensionRestHandler); + } } } } diff --git a/src/main/java/org/opensearch/sdk/rest/BaseExtensionRestHandler.java b/src/main/java/org/opensearch/sdk/rest/BaseExtensionRestHandler.java index bb616bf9..37dd6314 100644 --- a/src/main/java/org/opensearch/sdk/rest/BaseExtensionRestHandler.java +++ b/src/main/java/org/opensearch/sdk/rest/BaseExtensionRestHandler.java @@ -14,6 +14,8 @@ import java.util.List; import java.util.Optional; import java.util.Set; + +import org.opensearch.extensions.rest.RouteHandler; import org.opensearch.rest.BaseRestHandler; import static org.opensearch.rest.RestStatus.INTERNAL_SERVER_ERROR; import static org.opensearch.rest.RestStatus.NOT_FOUND; @@ -38,6 +40,9 @@ * Provides convenience methods to reduce boilerplate code in an {@link ExtensionRestHandler} implementation. */ public abstract class BaseExtensionRestHandler implements ExtensionRestHandler { + + private String extensionShortName; + /** * Constant for JSON content type */ @@ -80,6 +85,19 @@ protected List replacedRouteHandlers() { return Collections.emptyList(); } + public void setExtensionShortName(String extensionShortName) { + this.extensionShortName = extensionShortName; + } + + /** + * Generates a name for the handler prepended with the extension's shortName + * @param name The human-readable name for a route registered by this extension + * @return Returns a name prepended with the extension's shortName + */ + protected String routePrefix(String name) { + return extensionShortName + ":" + name; + } + @Override public List replacedRoutes() { return List.copyOf(replacedRouteHandlers()); @@ -223,36 +241,6 @@ protected ExtensionRestResponse createEmptyJsonResponse(RestRequest request, Res return new ExtensionRestResponse(request, status, JSON_CONTENT_TYPE, "{}"); } - /** - * A subclass of {@link Route} that includes a handler method for that route. - */ - public static class RouteHandler extends Route { - - private final Function responseHandler; - - /** - * Handle the method and path with the specified handler. - * - * @param method The {@link Method} to handle. - * @param path The path to handle. - * @param handler The method which handles the method and path. - */ - public RouteHandler(Method method, String path, Function handler) { - super(method, path); - this.responseHandler = handler; - } - - /** - * Executes the handler for this route. - * - * @param request The request to handle - * @return the {@link ExtensionRestResponse} result from the handler for this route. - */ - public ExtensionRestResponse handleRequest(RestRequest request) { - return responseHandler.apply(request); - } - } - /** * A subclass of {@link DeprecatedRoute} that includes a handler method for that route. */ diff --git a/src/main/java/org/opensearch/sdk/rest/ExtensionRestPathRegistry.java b/src/main/java/org/opensearch/sdk/rest/ExtensionRestPathRegistry.java index 3dd76950..615a68f9 100644 --- a/src/main/java/org/opensearch/sdk/rest/ExtensionRestPathRegistry.java +++ b/src/main/java/org/opensearch/sdk/rest/ExtensionRestPathRegistry.java @@ -11,10 +11,12 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import org.opensearch.common.Nullable; import org.opensearch.common.logging.DeprecationLogger; import org.opensearch.common.path.PathTrie; +import org.opensearch.extensions.rest.RouteHandler; import org.opensearch.rest.RestRequest.Method; import org.opensearch.rest.RestUtils; import org.opensearch.sdk.rest.BaseExtensionRestHandler.ExtensionDeprecationRestHandler; @@ -38,7 +40,13 @@ public class ExtensionRestPathRegistry { * @param restHandler The RestHandler to register routes. */ public void registerHandler(ExtensionRestHandler restHandler) { - restHandler.routes().forEach(route -> registerHandler(route.getMethod(), route.getPath(), restHandler)); + restHandler.routes().forEach(route -> { + Optional routeActionName = Optional.empty(); + if (route instanceof RouteHandler && ((RouteHandler) route).name() != null) { + routeActionName = Optional.of(((RouteHandler) route).name()); + } + registerHandler(route.getMethod(), route.getPath(), routeActionName, restHandler); + }); restHandler.deprecatedRoutes() .forEach(route -> registerAsDeprecatedHandler(route.getMethod(), route.getPath(), restHandler, route.getDeprecationMessage())); restHandler.replacedRoutes() @@ -57,20 +65,21 @@ public void registerHandler(ExtensionRestHandler restHandler) { * Registers a REST handler to be executed when one of the provided methods and path match the request. * * @param path Path to handle (e.g., "/{index}/{type}/_bulk") - * @param handler The handler to actually execute + * @param extensionRestHandler The handler to actually execute + * @param name The name corresponding to this handler * @param method GET, POST, etc. */ - private void registerHandler(Method method, String path, ExtensionRestHandler extensionRestHandler) { + public void registerHandler(Method method, String path, Optional name, ExtensionRestHandler extensionRestHandler) { pathTrie.insertOrUpdate( path, new SDKMethodHandlers(path, extensionRestHandler, method), (mHandlers, newMHandler) -> mHandlers.addMethods(extensionRestHandler, method) ); if (extensionRestHandler instanceof ExtensionDeprecationRestHandler) { - registeredDeprecatedPaths.add(restPathToString(method, path)); + registeredDeprecatedPaths.add(restPathToString(method, path, name)); registeredDeprecatedPaths.add(((ExtensionDeprecationRestHandler) extensionRestHandler).getDeprecationMessage()); } else { - registeredPaths.add(restPathToString(method, path)); + registeredPaths.add(restPathToString(method, path, name)); } } @@ -85,7 +94,12 @@ private void registerHandler(Method method, String path, ExtensionRestHandler ex private void registerAsDeprecatedHandler(Method method, String path, ExtensionRestHandler handler, String deprecationMessage) { assert (handler instanceof ExtensionDeprecationRestHandler) == false; - registerHandler(method, path, new ExtensionDeprecationRestHandler(handler, deprecationMessage, deprecationLogger)); + registerHandler( + method, + path, + Optional.empty(), + new ExtensionDeprecationRestHandler(handler, deprecationMessage, deprecationLogger) + ); } /** @@ -129,7 +143,7 @@ private void registerWithDeprecatedHandler( + path + "] instead."; - registerHandler(method, path, handler); + registerHandler(method, path, Optional.empty(), handler); registerAsDeprecatedHandler(deprecatedMethod, deprecatedPath, handler, deprecationMessage); } @@ -171,9 +185,13 @@ public List getRegisteredDeprecatedPaths() { * * @param method the method. * @param path the path. + * @param name the name corresponding to this route. * @return A string appending the method and path. */ - public static String restPathToString(Method method, String path) { + public static String restPathToString(Method method, String path, Optional name) { + if (name.isPresent()) { + return method.name() + " " + path + " " + name.get(); + } return method.name() + " " + path; } } diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java index 8673d48c..a94fd6b0 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestHelloAction.java @@ -15,6 +15,7 @@ import org.opensearch.common.xcontent.XContentType; import org.opensearch.common.xcontent.json.JsonXContent; import org.opensearch.extensions.rest.ExtensionRestResponse; +import org.opensearch.extensions.rest.RouteHandler; import org.opensearch.rest.RestRequest; import org.opensearch.sdk.rest.BaseExtensionRestHandler; import org.opensearch.sdk.rest.ExtensionRestHandler; @@ -50,13 +51,18 @@ public class RestHelloAction extends BaseExtensionRestHandler { private List worldAdjectives = new ArrayList<>(); private Random rand = new Random(); + /** + * Instantiate this action + */ + public RestHelloAction() {} + @Override public List routeHandlers() { return List.of( - new RouteHandler(GET, "/hello", handleGetRequest), - new RouteHandler(POST, "/hello", handlePostRequest), - new RouteHandler(PUT, "/hello/{name}", handlePutRequest), - new RouteHandler(DELETE, "/goodbye", handleDeleteRequest) + new RouteHandler(routePrefix("greet"), GET, "/hello", handleGetRequest), + new RouteHandler(routePrefix("greet_with_adjective"), POST, "/hello", handlePostRequest), + new RouteHandler(routePrefix("greet_with_name"), PUT, "/hello/{name}", handlePutRequest), + new RouteHandler(routePrefix("goodbye"), DELETE, "/goodbye", handleDeleteRequest) ); } diff --git a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java index cf4952f7..ee5b775b 100644 --- a/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java +++ b/src/main/java/org/opensearch/sdk/sample/helloworld/rest/RestRemoteHelloAction.java @@ -14,6 +14,7 @@ import org.opensearch.extensions.ExtensionsManager; import org.opensearch.extensions.action.RemoteExtensionActionResponse; import org.opensearch.extensions.rest.ExtensionRestResponse; +import org.opensearch.extensions.rest.RouteHandler; import org.opensearch.rest.RestRequest; import org.opensearch.sdk.ExtensionsRunner; import org.opensearch.sdk.SDKClient; diff --git a/src/main/resources/sample/helloworld-settings.yml b/src/main/resources/sample/helloworld-settings.yml index 15cdbdcf..a21e6032 100644 --- a/src/main/resources/sample/helloworld-settings.yml +++ b/src/main/resources/sample/helloworld-settings.yml @@ -1,4 +1,5 @@ extensionName: hello-world +shortExtensionName: hw hostAddress: 127.0.0.1 hostPort: 4500 opensearchAddress: 127.0.0.1 diff --git a/src/test/java/org/opensearch/sdk/ExtensionsRunnerForTest.java b/src/test/java/org/opensearch/sdk/ExtensionsRunnerForTest.java index 4c3a8963..5a841893 100644 --- a/src/test/java/org/opensearch/sdk/ExtensionsRunnerForTest.java +++ b/src/test/java/org/opensearch/sdk/ExtensionsRunnerForTest.java @@ -17,6 +17,7 @@ public class ExtensionsRunnerForTest extends ExtensionsRunner { public static final String NODE_NAME = "sample-extension"; + public static final String NODE_SHORT_NAME = "abbr"; public static final String NODE_HOST = "127.0.0.1"; public static final String NODE_PORT = "4532"; @@ -26,7 +27,7 @@ public class ExtensionsRunnerForTest extends ExtensionsRunner { * @throws IOException if the runner failed to read settings or API. */ public ExtensionsRunnerForTest() throws IOException { - super(new BaseExtension(new ExtensionSettings(NODE_NAME, NODE_HOST, NODE_PORT, "127.0.0.1", "9200")) { + super(new BaseExtension(new ExtensionSettings(NODE_NAME, NODE_SHORT_NAME, NODE_HOST, NODE_PORT, "127.0.0.1", "9200")) { }); } diff --git a/src/test/java/org/opensearch/sdk/TestExtensionSettings.java b/src/test/java/org/opensearch/sdk/TestExtensionSettings.java index b6edc8b4..e48934b8 100644 --- a/src/test/java/org/opensearch/sdk/TestExtensionSettings.java +++ b/src/test/java/org/opensearch/sdk/TestExtensionSettings.java @@ -29,6 +29,7 @@ public void setUp() throws Exception { @Test public void testSettingsStrings() { assertEquals("sample-extension", extensionSettings.getExtensionName()); + assertEquals("se", extensionSettings.getShortExtensionName()); assertEquals("127.0.0.1", extensionSettings.getHostAddress()); assertEquals("4532", extensionSettings.getHostPort()); assertEquals("127.0.0.1", extensionSettings.getOpensearchAddress()); @@ -42,8 +43,9 @@ public void testSettingsStrings() { @Test public void testConstructorWithArgs() { - ExtensionSettings settings = new ExtensionSettings("foo", "bar", "baz", "os", "port"); + ExtensionSettings settings = new ExtensionSettings("foo", "abbr", "bar", "baz", "os", "port"); assertEquals("foo", settings.getExtensionName()); + assertEquals("abbr", settings.getShortExtensionName()); assertEquals("bar", settings.getHostAddress()); assertEquals("baz", settings.getHostPort()); assertEquals("os", settings.getOpensearchAddress()); diff --git a/src/test/java/org/opensearch/sdk/TestSDKClient.java b/src/test/java/org/opensearch/sdk/TestSDKClient.java index 0be408f6..ee0cac5e 100644 --- a/src/test/java/org/opensearch/sdk/TestSDKClient.java +++ b/src/test/java/org/opensearch/sdk/TestSDKClient.java @@ -57,7 +57,7 @@ @SuppressWarnings("deprecation") public class TestSDKClient extends OpenSearchTestCase { private SDKClient sdkClient; - private final ExtensionSettings extensionSettings = new ExtensionSettings("", "", "", "localhost", "9200"); + private final ExtensionSettings extensionSettings = new ExtensionSettings("", "", "", "", "localhost", "9200"); @Override @BeforeEach diff --git a/src/test/java/org/opensearch/sdk/rest/TestBaseExtensionRestHandler.java b/src/test/java/org/opensearch/sdk/rest/TestBaseExtensionRestHandler.java index 7fa02c83..dba21124 100644 --- a/src/test/java/org/opensearch/sdk/rest/TestBaseExtensionRestHandler.java +++ b/src/test/java/org/opensearch/sdk/rest/TestBaseExtensionRestHandler.java @@ -17,6 +17,7 @@ import org.junit.jupiter.api.Test; import org.opensearch.common.bytes.BytesArray; import org.opensearch.extensions.rest.ExtensionRestResponse; +import org.opensearch.extensions.rest.RouteHandler; import org.opensearch.rest.RestHandler.Route; import org.opensearch.rest.RestRequest; import org.opensearch.rest.RestRequest.Method; diff --git a/src/test/java/org/opensearch/sdk/rest/TestExtensionRestPathRegistry.java b/src/test/java/org/opensearch/sdk/rest/TestExtensionRestPathRegistry.java index 8d794cb7..b74f1416 100644 --- a/src/test/java/org/opensearch/sdk/rest/TestExtensionRestPathRegistry.java +++ b/src/test/java/org/opensearch/sdk/rest/TestExtensionRestPathRegistry.java @@ -10,6 +10,7 @@ package org.opensearch.sdk.rest; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -181,6 +182,11 @@ public void testGetRegisteredReplacedPaths() { @Test public void testRestPathToString() { - assertEquals("GET /foo", ExtensionRestPathRegistry.restPathToString(Method.GET, "/foo")); + assertEquals("GET /foo", ExtensionRestPathRegistry.restPathToString(Method.GET, "/foo", Optional.empty())); + } + + @Test + public void testRestPathWithNameToString() { + assertEquals("GET /foo foo", ExtensionRestPathRegistry.restPathToString(Method.GET, "/foo", Optional.of("foo"))); } } diff --git a/src/test/java/org/opensearch/sdk/sample/helloworld/TestHelloWorldExtension.java b/src/test/java/org/opensearch/sdk/sample/helloworld/TestHelloWorldExtension.java index 451de7be..d7489131 100644 --- a/src/test/java/org/opensearch/sdk/sample/helloworld/TestHelloWorldExtension.java +++ b/src/test/java/org/opensearch/sdk/sample/helloworld/TestHelloWorldExtension.java @@ -57,7 +57,7 @@ public class TestHelloWorldExtension extends OpenSearchTestCase { private SDKClient sdkClient; private SDKRestClient sdkRestClient; private OpenSearchAsyncClient javaAsyncClient; - private final ExtensionSettings extensionSettings = new ExtensionSettings("", "", "", "localhost", "9200"); + private final ExtensionSettings extensionSettings = new ExtensionSettings("", "hw", "", "", "localhost", "9200"); static class UnregisteredAction extends ActionType { public static final String NAME = "helloworld/unregistered"; @@ -108,7 +108,7 @@ public void tearDown() throws Exception { public void testExtensionSettings() { // This effectively tests the Extension interface helper method ExtensionSettings extensionSettings = extension.getExtensionSettings(); - ExtensionSettings expected = new ExtensionSettings("hello-world", "127.0.0.1", "4532", "127.0.0.1", "9200"); + ExtensionSettings expected = new ExtensionSettings("hello-world", "hw", "127.0.0.1", "4532", "127.0.0.1", "9200"); assertEquals(expected.getExtensionName(), extensionSettings.getExtensionName()); assertEquals(expected.getHostAddress(), extensionSettings.getHostAddress()); assertEquals(expected.getHostPort(), extensionSettings.getHostPort()); diff --git a/src/test/resources/extension.yml b/src/test/resources/extension.yml index 2d31b0f4..8150d393 100644 --- a/src/test/resources/extension.yml +++ b/src/test/resources/extension.yml @@ -1,4 +1,5 @@ extensionName: sample-extension +shortExtensionName: se hostAddress: 127.0.0.1 hostPort: 4532 opensearchAddress: 127.0.0.1