From 8db43c01079aaec4f5ca5c9adb89364e63eb9bbe Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Wed, 29 Jun 2016 14:55:31 -0400 Subject: [PATCH] Move RestHandler registration to ActionModule and ActionPlugin `RestHandler`s are highly tied to actions so registering them in the same place makes sense. Removes the need to for plugins to check if they are in transport client mode before registering a RestHandler - `getRestHandlers` isn't called at all in transport client mode. This caused guice to throw a massive fit about the circular dependency between NodeClient and the allocation deciders. I broke the circular dependency by registering the actions map with the node client after instantiation. --- .../elasticsearch/action/ActionModule.java | 279 +++++++++++++++++- .../elasticsearch/client/node/NodeClient.java | 16 +- .../metadata/IndexNameExpressionResolver.java | 2 - .../elasticsearch/common/NamedRegistry.java | 2 +- .../common/network/NetworkModule.java | 266 ----------------- .../java/org/elasticsearch/node/Node.java | 11 +- .../elasticsearch/plugins/ActionPlugin.java | 34 +++ .../elasticsearch/rest/RestController.java | 2 - .../action/ActionModuleTests.java | 129 ++++++++ .../client/node/NodeClientHeadersTests.java | 4 +- .../common/network/NetworkModuleTests.java | 29 -- .../TestResponseHeaderPlugin.java | 13 +- .../migration/migrate_5_0/plugins.asciidoc | 3 + .../script/mustache/MustachePlugin.java | 15 +- .../percolator/PercolatorPlugin.java | 12 +- .../index/reindex/ReindexPlugin.java | 11 +- 16 files changed, 488 insertions(+), 340 deletions(-) create mode 100644 core/src/test/java/org/elasticsearch/action/ActionModuleTests.java diff --git a/core/src/main/java/org/elasticsearch/action/ActionModule.java b/core/src/main/java/org/elasticsearch/action/ActionModule.java index f5c83e272ce..5ce7aaa4d95 100644 --- a/core/src/main/java/org/elasticsearch/action/ActionModule.java +++ b/core/src/main/java/org/elasticsearch/action/ActionModule.java @@ -194,14 +194,120 @@ import org.elasticsearch.common.NamedRegistry; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.multibindings.MapBinder; import org.elasticsearch.common.inject.multibindings.Multibinder; +import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.ActionPlugin; import org.elasticsearch.plugins.ActionPlugin.ActionHandler; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestHandler; +import org.elasticsearch.rest.action.admin.cluster.allocation.RestClusterAllocationExplainAction; +import org.elasticsearch.rest.action.admin.cluster.health.RestClusterHealthAction; +import org.elasticsearch.rest.action.admin.cluster.node.hotthreads.RestNodesHotThreadsAction; +import org.elasticsearch.rest.action.admin.cluster.node.info.RestNodesInfoAction; +import org.elasticsearch.rest.action.admin.cluster.node.stats.RestNodesStatsAction; +import org.elasticsearch.rest.action.admin.cluster.node.tasks.RestCancelTasksAction; +import org.elasticsearch.rest.action.admin.cluster.node.tasks.RestGetTaskAction; +import org.elasticsearch.rest.action.admin.cluster.node.tasks.RestListTasksAction; +import org.elasticsearch.rest.action.admin.cluster.repositories.delete.RestDeleteRepositoryAction; +import org.elasticsearch.rest.action.admin.cluster.repositories.get.RestGetRepositoriesAction; +import org.elasticsearch.rest.action.admin.cluster.repositories.put.RestPutRepositoryAction; +import org.elasticsearch.rest.action.admin.cluster.repositories.verify.RestVerifyRepositoryAction; +import org.elasticsearch.rest.action.admin.cluster.reroute.RestClusterRerouteAction; +import org.elasticsearch.rest.action.admin.cluster.settings.RestClusterGetSettingsAction; +import org.elasticsearch.rest.action.admin.cluster.settings.RestClusterUpdateSettingsAction; +import org.elasticsearch.rest.action.admin.cluster.shards.RestClusterSearchShardsAction; +import org.elasticsearch.rest.action.admin.cluster.snapshots.create.RestCreateSnapshotAction; +import org.elasticsearch.rest.action.admin.cluster.snapshots.delete.RestDeleteSnapshotAction; +import org.elasticsearch.rest.action.admin.cluster.snapshots.get.RestGetSnapshotsAction; +import org.elasticsearch.rest.action.admin.cluster.snapshots.restore.RestRestoreSnapshotAction; +import org.elasticsearch.rest.action.admin.cluster.snapshots.status.RestSnapshotsStatusAction; +import org.elasticsearch.rest.action.admin.cluster.state.RestClusterStateAction; +import org.elasticsearch.rest.action.admin.cluster.stats.RestClusterStatsAction; +import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteStoredScriptAction; +import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetStoredScriptAction; +import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutStoredScriptAction; +import org.elasticsearch.rest.action.admin.cluster.tasks.RestPendingClusterTasksAction; +import org.elasticsearch.rest.action.admin.indices.RestRolloverIndexAction; +import org.elasticsearch.rest.action.admin.indices.RestShrinkIndexAction; +import org.elasticsearch.rest.action.admin.indices.alias.RestIndicesAliasesAction; +import org.elasticsearch.rest.action.admin.indices.alias.delete.RestIndexDeleteAliasesAction; +import org.elasticsearch.rest.action.admin.indices.alias.get.RestGetAliasesAction; +import org.elasticsearch.rest.action.admin.indices.alias.head.RestAliasesExistAction; +import org.elasticsearch.rest.action.admin.indices.alias.put.RestIndexPutAliasAction; +import org.elasticsearch.rest.action.admin.indices.analyze.RestAnalyzeAction; +import org.elasticsearch.rest.action.admin.indices.cache.clear.RestClearIndicesCacheAction; +import org.elasticsearch.rest.action.admin.indices.close.RestCloseIndexAction; +import org.elasticsearch.rest.action.admin.indices.create.RestCreateIndexAction; +import org.elasticsearch.rest.action.admin.indices.delete.RestDeleteIndexAction; +import org.elasticsearch.rest.action.admin.indices.exists.indices.RestIndicesExistsAction; +import org.elasticsearch.rest.action.admin.indices.exists.types.RestTypesExistsAction; +import org.elasticsearch.rest.action.admin.indices.flush.RestFlushAction; +import org.elasticsearch.rest.action.admin.indices.flush.RestSyncedFlushAction; +import org.elasticsearch.rest.action.admin.indices.forcemerge.RestForceMergeAction; +import org.elasticsearch.rest.action.admin.indices.get.RestGetIndicesAction; +import org.elasticsearch.rest.action.admin.indices.mapping.get.RestGetFieldMappingAction; +import org.elasticsearch.rest.action.admin.indices.mapping.get.RestGetMappingAction; +import org.elasticsearch.rest.action.admin.indices.mapping.put.RestPutMappingAction; +import org.elasticsearch.rest.action.admin.indices.open.RestOpenIndexAction; +import org.elasticsearch.rest.action.admin.indices.recovery.RestRecoveryAction; +import org.elasticsearch.rest.action.admin.indices.refresh.RestRefreshAction; +import org.elasticsearch.rest.action.admin.indices.segments.RestIndicesSegmentsAction; +import org.elasticsearch.rest.action.admin.indices.settings.RestGetSettingsAction; +import org.elasticsearch.rest.action.admin.indices.settings.RestUpdateSettingsAction; +import org.elasticsearch.rest.action.admin.indices.shards.RestIndicesShardStoresAction; +import org.elasticsearch.rest.action.admin.indices.stats.RestIndicesStatsAction; +import org.elasticsearch.rest.action.admin.indices.template.delete.RestDeleteIndexTemplateAction; +import org.elasticsearch.rest.action.admin.indices.template.get.RestGetIndexTemplateAction; +import org.elasticsearch.rest.action.admin.indices.template.head.RestHeadIndexTemplateAction; +import org.elasticsearch.rest.action.admin.indices.template.put.RestPutIndexTemplateAction; +import org.elasticsearch.rest.action.admin.indices.upgrade.RestUpgradeAction; +import org.elasticsearch.rest.action.admin.indices.validate.query.RestValidateQueryAction; +import org.elasticsearch.rest.action.bulk.RestBulkAction; +import org.elasticsearch.rest.action.cat.AbstractCatAction; +import org.elasticsearch.rest.action.cat.RestAliasAction; +import org.elasticsearch.rest.action.cat.RestAllocationAction; +import org.elasticsearch.rest.action.cat.RestCatAction; +import org.elasticsearch.rest.action.cat.RestFielddataAction; +import org.elasticsearch.rest.action.cat.RestHealthAction; +import org.elasticsearch.rest.action.cat.RestIndicesAction; +import org.elasticsearch.rest.action.cat.RestMasterAction; +import org.elasticsearch.rest.action.cat.RestNodeAttrsAction; +import org.elasticsearch.rest.action.cat.RestNodesAction; +import org.elasticsearch.rest.action.cat.RestPluginsAction; +import org.elasticsearch.rest.action.cat.RestRepositoriesAction; +import org.elasticsearch.rest.action.cat.RestSegmentsAction; +import org.elasticsearch.rest.action.cat.RestShardsAction; +import org.elasticsearch.rest.action.cat.RestSnapshotAction; +import org.elasticsearch.rest.action.cat.RestTasksAction; +import org.elasticsearch.rest.action.cat.RestThreadPoolAction; +import org.elasticsearch.rest.action.delete.RestDeleteAction; +import org.elasticsearch.rest.action.explain.RestExplainAction; +import org.elasticsearch.rest.action.fieldstats.RestFieldStatsAction; +import org.elasticsearch.rest.action.get.RestGetAction; +import org.elasticsearch.rest.action.get.RestGetSourceAction; +import org.elasticsearch.rest.action.get.RestHeadAction; +import org.elasticsearch.rest.action.get.RestMultiGetAction; +import org.elasticsearch.rest.action.index.RestIndexAction; +import org.elasticsearch.rest.action.ingest.RestDeletePipelineAction; +import org.elasticsearch.rest.action.ingest.RestGetPipelineAction; +import org.elasticsearch.rest.action.ingest.RestPutPipelineAction; +import org.elasticsearch.rest.action.ingest.RestSimulatePipelineAction; +import org.elasticsearch.rest.action.main.RestMainAction; +import org.elasticsearch.rest.action.search.RestClearScrollAction; +import org.elasticsearch.rest.action.search.RestMultiSearchAction; +import org.elasticsearch.rest.action.search.RestSearchAction; +import org.elasticsearch.rest.action.search.RestSearchScrollAction; +import org.elasticsearch.rest.action.suggest.RestSuggestAction; +import org.elasticsearch.rest.action.termvectors.RestMultiTermVectorsAction; +import org.elasticsearch.rest.action.termvectors.RestTermVectorsAction; +import org.elasticsearch.rest.action.update.RestUpdateAction; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import static java.util.Collections.unmodifiableList; import static java.util.Collections.unmodifiableMap; @@ -212,21 +318,27 @@ import static java.util.Collections.unmodifiableMap; public class ActionModule extends AbstractModule { private final boolean transportClient; + private final Settings settings; + private final List actionPlugins; private final Map> actions; private final List> actionFilters; private final AutoCreateIndex autoCreateIndex; private final DestructiveOperations destructiveOperations; + private final RestController restController; public ActionModule(boolean ingestEnabled, boolean transportClient, Settings settings, IndexNameExpressionResolver resolver, ClusterSettings clusterSettings, List actionPlugins) { this.transportClient = transportClient; + this.settings = settings; + this.actionPlugins = actionPlugins; actions = setupActions(actionPlugins); actionFilters = setupActionFilters(actionPlugins, ingestEnabled); autoCreateIndex = transportClient ? null : new AutoCreateIndex(settings, resolver); destructiveOperations = new DestructiveOperations(settings, clusterSettings); + restController = new RestController(settings); } - private Map> setupActions(List actionPlugins) { + static Map> setupActions(List actionPlugins) { // Subclass NamedRegistry for easy registration class ActionRegistry extends NamedRegistry> { public ActionRegistry() { @@ -357,6 +469,149 @@ public class ActionModule extends AbstractModule { return unmodifiableList(filters); } + static Set> setupRestHandlers(List actionPlugins) { + Set> handlers = new HashSet<>(); + registerRestHandler(handlers, RestMainAction.class); + registerRestHandler(handlers, RestNodesInfoAction.class); + registerRestHandler(handlers, RestNodesStatsAction.class); + registerRestHandler(handlers, RestNodesHotThreadsAction.class); + registerRestHandler(handlers, RestClusterAllocationExplainAction.class); + registerRestHandler(handlers, RestClusterStatsAction.class); + registerRestHandler(handlers, RestClusterStateAction.class); + registerRestHandler(handlers, RestClusterHealthAction.class); + registerRestHandler(handlers, RestClusterUpdateSettingsAction.class); + registerRestHandler(handlers, RestClusterGetSettingsAction.class); + registerRestHandler(handlers, RestClusterRerouteAction.class); + registerRestHandler(handlers, RestClusterSearchShardsAction.class); + registerRestHandler(handlers, RestPendingClusterTasksAction.class); + registerRestHandler(handlers, RestPutRepositoryAction.class); + registerRestHandler(handlers, RestGetRepositoriesAction.class); + registerRestHandler(handlers, RestDeleteRepositoryAction.class); + registerRestHandler(handlers, RestVerifyRepositoryAction.class); + registerRestHandler(handlers, RestGetSnapshotsAction.class); + registerRestHandler(handlers, RestCreateSnapshotAction.class); + registerRestHandler(handlers, RestRestoreSnapshotAction.class); + registerRestHandler(handlers, RestDeleteSnapshotAction.class); + registerRestHandler(handlers, RestSnapshotsStatusAction.class); + + registerRestHandler(handlers, RestIndicesExistsAction.class); + registerRestHandler(handlers, RestTypesExistsAction.class); + registerRestHandler(handlers, RestGetIndicesAction.class); + registerRestHandler(handlers, RestIndicesStatsAction.class); + registerRestHandler(handlers, RestIndicesSegmentsAction.class); + registerRestHandler(handlers, RestIndicesShardStoresAction.class); + registerRestHandler(handlers, RestGetAliasesAction.class); + registerRestHandler(handlers, RestAliasesExistAction.class); + registerRestHandler(handlers, RestIndexDeleteAliasesAction.class); + registerRestHandler(handlers, RestIndexPutAliasAction.class); + registerRestHandler(handlers, RestIndicesAliasesAction.class); + registerRestHandler(handlers, RestCreateIndexAction.class); + registerRestHandler(handlers, RestShrinkIndexAction.class); + registerRestHandler(handlers, RestRolloverIndexAction.class); + registerRestHandler(handlers, RestDeleteIndexAction.class); + registerRestHandler(handlers, RestCloseIndexAction.class); + registerRestHandler(handlers, RestOpenIndexAction.class); + + registerRestHandler(handlers, RestUpdateSettingsAction.class); + registerRestHandler(handlers, RestGetSettingsAction.class); + + registerRestHandler(handlers, RestAnalyzeAction.class); + registerRestHandler(handlers, RestGetIndexTemplateAction.class); + registerRestHandler(handlers, RestPutIndexTemplateAction.class); + registerRestHandler(handlers, RestDeleteIndexTemplateAction.class); + registerRestHandler(handlers, RestHeadIndexTemplateAction.class); + + registerRestHandler(handlers, RestPutMappingAction.class); + registerRestHandler(handlers, RestGetMappingAction.class); + registerRestHandler(handlers, RestGetFieldMappingAction.class); + + registerRestHandler(handlers, RestRefreshAction.class); + registerRestHandler(handlers, RestFlushAction.class); + registerRestHandler(handlers, RestSyncedFlushAction.class); + registerRestHandler(handlers, RestForceMergeAction.class); + registerRestHandler(handlers, RestUpgradeAction.class); + registerRestHandler(handlers, RestClearIndicesCacheAction.class); + + registerRestHandler(handlers, RestIndexAction.class); + registerRestHandler(handlers, RestGetAction.class); + registerRestHandler(handlers, RestGetSourceAction.class); + registerRestHandler(handlers, RestHeadAction.Document.class); + registerRestHandler(handlers, RestHeadAction.Source.class); + registerRestHandler(handlers, RestMultiGetAction.class); + registerRestHandler(handlers, RestDeleteAction.class); + registerRestHandler(handlers, org.elasticsearch.rest.action.count.RestCountAction.class); + registerRestHandler(handlers, RestSuggestAction.class); + registerRestHandler(handlers, RestTermVectorsAction.class); + registerRestHandler(handlers, RestMultiTermVectorsAction.class); + registerRestHandler(handlers, RestBulkAction.class); + registerRestHandler(handlers, RestUpdateAction.class); + + registerRestHandler(handlers, RestSearchAction.class); + registerRestHandler(handlers, RestSearchScrollAction.class); + registerRestHandler(handlers, RestClearScrollAction.class); + registerRestHandler(handlers, RestMultiSearchAction.class); + + registerRestHandler(handlers, RestValidateQueryAction.class); + + registerRestHandler(handlers, RestExplainAction.class); + + registerRestHandler(handlers, RestRecoveryAction.class); + + // Scripts API + registerRestHandler(handlers, RestGetStoredScriptAction.class); + registerRestHandler(handlers, RestPutStoredScriptAction.class); + registerRestHandler(handlers, RestDeleteStoredScriptAction.class); + + registerRestHandler(handlers, RestFieldStatsAction.class); + + // Tasks API + registerRestHandler(handlers, RestListTasksAction.class); + registerRestHandler(handlers, RestGetTaskAction.class); + registerRestHandler(handlers, RestCancelTasksAction.class); + + // Ingest API + registerRestHandler(handlers, RestPutPipelineAction.class); + registerRestHandler(handlers, RestGetPipelineAction.class); + registerRestHandler(handlers, RestDeletePipelineAction.class); + registerRestHandler(handlers, RestSimulatePipelineAction.class); + + // CAT API + registerRestHandler(handlers, RestCatAction.class); + registerRestHandler(handlers, RestAllocationAction.class); + registerRestHandler(handlers, RestShardsAction.class); + registerRestHandler(handlers, RestMasterAction.class); + registerRestHandler(handlers, RestNodesAction.class); + registerRestHandler(handlers, RestTasksAction.class); + registerRestHandler(handlers, RestIndicesAction.class); + registerRestHandler(handlers, RestSegmentsAction.class); + // Fully qualified to prevent interference with rest.action.count.RestCountAction + registerRestHandler(handlers, org.elasticsearch.rest.action.cat.RestCountAction.class); + // Fully qualified to prevent interference with rest.action.indices.RestRecoveryAction + registerRestHandler(handlers, org.elasticsearch.rest.action.cat.RestRecoveryAction.class); + registerRestHandler(handlers, RestHealthAction.class); + registerRestHandler(handlers, org.elasticsearch.rest.action.cat.RestPendingClusterTasksAction.class); + registerRestHandler(handlers, RestAliasAction.class); + registerRestHandler(handlers, RestThreadPoolAction.class); + registerRestHandler(handlers, RestPluginsAction.class); + registerRestHandler(handlers, RestFielddataAction.class); + registerRestHandler(handlers, RestNodeAttrsAction.class); + registerRestHandler(handlers, RestRepositoriesAction.class); + registerRestHandler(handlers, RestSnapshotAction.class); + for (ActionPlugin plugin : actionPlugins) { + for (Class handler : plugin.getRestHandlers()) { + registerRestHandler(handlers, handler); + } + } + return handlers; + } + + private static void registerRestHandler(Set> handlers, Class handler) { + if (handlers.contains(handler)) { + throw new IllegalArgumentException("can't register the same [rest_handler] more than once for [" + handler.getName() + "]"); + } + handlers.add(handler); + } + @Override protected void configure() { Multibinder actionFilterMultibinder = Multibinder.newSetBinder(binder(), ActionFilter.class); @@ -374,11 +629,12 @@ public class ActionModule extends AbstractModule { for (Map.Entry> entry : actions.entrySet()) { actionsBinder.addBinding(entry.getKey()).toInstance(entry.getValue().getAction()); } - // register GenericAction -> transportAction Map that can be injected to instances. - // also register any supporting classes if (false == transportClient) { + // Supporting classes only used when not a transport client bind(AutoCreateIndex.class).toInstance(autoCreateIndex); bind(TransportLivenessAction.class).asEagerSingleton(); + + // register GenericAction -> transportAction Map used by NodeClient @SuppressWarnings("rawtypes") MapBinder transportActionsBinder = MapBinder.newMapBinder(binder(), GenericAction.class, TransportAction.class); @@ -390,6 +646,23 @@ public class ActionModule extends AbstractModule { bind(supportAction).asEagerSingleton(); } } + + // Bind the RestController which is required (by Node) even if rest isn't enabled. + bind(RestController.class).toInstance(restController); + + // Setup the RestHandlers + if (NetworkModule.HTTP_ENABLED.get(settings)) { + Multibinder restHandlers = Multibinder.newSetBinder(binder(), RestHandler.class); + Multibinder catHandlers = Multibinder.newSetBinder(binder(), AbstractCatAction.class); + for (Class handler : setupRestHandlers(actionPlugins)) { + bind(handler).asEagerSingleton(); + if (AbstractCatAction.class.isAssignableFrom(handler)) { + catHandlers.addBinding().to(handler.asSubclass(AbstractCatAction.class)); + } else { + restHandlers.addBinding().to(handler); + } + } + } } } } diff --git a/core/src/main/java/org/elasticsearch/client/node/NodeClient.java b/core/src/main/java/org/elasticsearch/client/node/NodeClient.java index 3e9bed9e25d..59909df428b 100644 --- a/core/src/main/java/org/elasticsearch/client/node/NodeClient.java +++ b/core/src/main/java/org/elasticsearch/client/node/NodeClient.java @@ -27,25 +27,24 @@ import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.GenericAction; import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.client.support.AbstractClient; -import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.threadpool.ThreadPool; import java.util.Map; -import static java.util.Collections.unmodifiableMap; - /** * */ public class NodeClient extends AbstractClient { - private final Map actions; + private Map actions; - @Inject - public NodeClient(Settings settings, ThreadPool threadPool, Map actions) { + public NodeClient(Settings settings, ThreadPool threadPool) { super(settings, threadPool); - this.actions = unmodifiableMap(actions); + } + + public void intialize(Map actions) { + this.actions = actions; } @Override @@ -57,6 +56,9 @@ public class NodeClient extends AbstractClient { @Override public , Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder> void doExecute( Action action, Request request, ActionListener listener) { + if (actions == null) { + throw new IllegalStateException("NodeClient has not been initialized"); + } TransportAction transportAction = actions.get(action); if (transportAction == null) { throw new IllegalStateException("failed to find action [" + action + "] to execute"); diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java b/core/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java index 2abbea04d51..4eefac0f17f 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java @@ -27,7 +27,6 @@ import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.component.AbstractComponent; -import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.joda.DateMathParser; import org.elasticsearch.common.joda.FormatDateTimeFormatter; import org.elasticsearch.common.regex.Regex; @@ -57,7 +56,6 @@ public class IndexNameExpressionResolver extends AbstractComponent { private final List expressionResolvers; private final DateMathExpressionResolver dateMathExpressionResolver; - @Inject public IndexNameExpressionResolver(Settings settings) { super(settings); expressionResolvers = Arrays.asList( diff --git a/core/src/main/java/org/elasticsearch/common/NamedRegistry.java b/core/src/main/java/org/elasticsearch/common/NamedRegistry.java index 7573b5268fd..c326da7a495 100644 --- a/core/src/main/java/org/elasticsearch/common/NamedRegistry.java +++ b/core/src/main/java/org/elasticsearch/common/NamedRegistry.java @@ -45,7 +45,7 @@ public class NamedRegistry { requireNonNull(name, "name is required"); requireNonNull(t, targetName + " is required"); if (registry.putIfAbsent(name, t) != null) { - throw new IllegalArgumentException(targetName + " for name " + name + " already registered"); + throw new IllegalArgumentException(targetName + " for name [" + name + "] already registered"); } } diff --git a/core/src/main/java/org/elasticsearch/common/network/NetworkModule.java b/core/src/main/java/org/elasticsearch/common/network/NetworkModule.java index b0287ad153a..2b94f224b9c 100644 --- a/core/src/main/java/org/elasticsearch/common/network/NetworkModule.java +++ b/core/src/main/java/org/elasticsearch/common/network/NetworkModule.java @@ -41,109 +41,6 @@ import org.elasticsearch.common.util.ExtensionPoint; import org.elasticsearch.http.HttpServer; import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.http.netty.NettyHttpServerTransport; -import org.elasticsearch.rest.RestController; -import org.elasticsearch.rest.RestHandler; -import org.elasticsearch.rest.action.admin.cluster.allocation.RestClusterAllocationExplainAction; -import org.elasticsearch.rest.action.admin.cluster.health.RestClusterHealthAction; -import org.elasticsearch.rest.action.admin.cluster.node.hotthreads.RestNodesHotThreadsAction; -import org.elasticsearch.rest.action.admin.cluster.node.info.RestNodesInfoAction; -import org.elasticsearch.rest.action.admin.cluster.node.stats.RestNodesStatsAction; -import org.elasticsearch.rest.action.admin.cluster.node.tasks.RestCancelTasksAction; -import org.elasticsearch.rest.action.admin.cluster.node.tasks.RestGetTaskAction; -import org.elasticsearch.rest.action.admin.cluster.node.tasks.RestListTasksAction; -import org.elasticsearch.rest.action.admin.cluster.repositories.delete.RestDeleteRepositoryAction; -import org.elasticsearch.rest.action.admin.cluster.repositories.get.RestGetRepositoriesAction; -import org.elasticsearch.rest.action.admin.cluster.repositories.put.RestPutRepositoryAction; -import org.elasticsearch.rest.action.admin.cluster.repositories.verify.RestVerifyRepositoryAction; -import org.elasticsearch.rest.action.admin.cluster.reroute.RestClusterRerouteAction; -import org.elasticsearch.rest.action.admin.cluster.settings.RestClusterGetSettingsAction; -import org.elasticsearch.rest.action.admin.cluster.settings.RestClusterUpdateSettingsAction; -import org.elasticsearch.rest.action.admin.cluster.shards.RestClusterSearchShardsAction; -import org.elasticsearch.rest.action.admin.cluster.snapshots.create.RestCreateSnapshotAction; -import org.elasticsearch.rest.action.admin.cluster.snapshots.delete.RestDeleteSnapshotAction; -import org.elasticsearch.rest.action.admin.cluster.snapshots.get.RestGetSnapshotsAction; -import org.elasticsearch.rest.action.admin.cluster.snapshots.restore.RestRestoreSnapshotAction; -import org.elasticsearch.rest.action.admin.cluster.snapshots.status.RestSnapshotsStatusAction; -import org.elasticsearch.rest.action.admin.cluster.state.RestClusterStateAction; -import org.elasticsearch.rest.action.admin.cluster.stats.RestClusterStatsAction; -import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteStoredScriptAction; -import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetStoredScriptAction; -import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutStoredScriptAction; -import org.elasticsearch.rest.action.admin.cluster.tasks.RestPendingClusterTasksAction; -import org.elasticsearch.rest.action.admin.indices.RestRolloverIndexAction; -import org.elasticsearch.rest.action.admin.indices.RestShrinkIndexAction; -import org.elasticsearch.rest.action.admin.indices.alias.RestIndicesAliasesAction; -import org.elasticsearch.rest.action.admin.indices.alias.delete.RestIndexDeleteAliasesAction; -import org.elasticsearch.rest.action.admin.indices.alias.get.RestGetAliasesAction; -import org.elasticsearch.rest.action.admin.indices.alias.head.RestAliasesExistAction; -import org.elasticsearch.rest.action.admin.indices.alias.put.RestIndexPutAliasAction; -import org.elasticsearch.rest.action.admin.indices.analyze.RestAnalyzeAction; -import org.elasticsearch.rest.action.admin.indices.cache.clear.RestClearIndicesCacheAction; -import org.elasticsearch.rest.action.admin.indices.close.RestCloseIndexAction; -import org.elasticsearch.rest.action.admin.indices.create.RestCreateIndexAction; -import org.elasticsearch.rest.action.admin.indices.delete.RestDeleteIndexAction; -import org.elasticsearch.rest.action.admin.indices.exists.indices.RestIndicesExistsAction; -import org.elasticsearch.rest.action.admin.indices.exists.types.RestTypesExistsAction; -import org.elasticsearch.rest.action.admin.indices.flush.RestFlushAction; -import org.elasticsearch.rest.action.admin.indices.flush.RestSyncedFlushAction; -import org.elasticsearch.rest.action.admin.indices.forcemerge.RestForceMergeAction; -import org.elasticsearch.rest.action.admin.indices.get.RestGetIndicesAction; -import org.elasticsearch.rest.action.admin.indices.mapping.get.RestGetFieldMappingAction; -import org.elasticsearch.rest.action.admin.indices.mapping.get.RestGetMappingAction; -import org.elasticsearch.rest.action.admin.indices.mapping.put.RestPutMappingAction; -import org.elasticsearch.rest.action.admin.indices.open.RestOpenIndexAction; -import org.elasticsearch.rest.action.admin.indices.recovery.RestRecoveryAction; -import org.elasticsearch.rest.action.admin.indices.refresh.RestRefreshAction; -import org.elasticsearch.rest.action.admin.indices.segments.RestIndicesSegmentsAction; -import org.elasticsearch.rest.action.admin.indices.settings.RestGetSettingsAction; -import org.elasticsearch.rest.action.admin.indices.settings.RestUpdateSettingsAction; -import org.elasticsearch.rest.action.admin.indices.shards.RestIndicesShardStoresAction; -import org.elasticsearch.rest.action.admin.indices.stats.RestIndicesStatsAction; -import org.elasticsearch.rest.action.admin.indices.template.delete.RestDeleteIndexTemplateAction; -import org.elasticsearch.rest.action.admin.indices.template.get.RestGetIndexTemplateAction; -import org.elasticsearch.rest.action.admin.indices.template.head.RestHeadIndexTemplateAction; -import org.elasticsearch.rest.action.admin.indices.template.put.RestPutIndexTemplateAction; -import org.elasticsearch.rest.action.admin.indices.upgrade.RestUpgradeAction; -import org.elasticsearch.rest.action.admin.indices.validate.query.RestValidateQueryAction; -import org.elasticsearch.rest.action.bulk.RestBulkAction; -import org.elasticsearch.rest.action.cat.AbstractCatAction; -import org.elasticsearch.rest.action.cat.RestAliasAction; -import org.elasticsearch.rest.action.cat.RestAllocationAction; -import org.elasticsearch.rest.action.cat.RestCatAction; -import org.elasticsearch.rest.action.cat.RestFielddataAction; -import org.elasticsearch.rest.action.cat.RestHealthAction; -import org.elasticsearch.rest.action.cat.RestIndicesAction; -import org.elasticsearch.rest.action.cat.RestMasterAction; -import org.elasticsearch.rest.action.cat.RestNodeAttrsAction; -import org.elasticsearch.rest.action.cat.RestNodesAction; -import org.elasticsearch.rest.action.cat.RestPluginsAction; -import org.elasticsearch.rest.action.cat.RestRepositoriesAction; -import org.elasticsearch.rest.action.cat.RestSegmentsAction; -import org.elasticsearch.rest.action.cat.RestShardsAction; -import org.elasticsearch.rest.action.cat.RestSnapshotAction; -import org.elasticsearch.rest.action.cat.RestTasksAction; -import org.elasticsearch.rest.action.cat.RestThreadPoolAction; -import org.elasticsearch.rest.action.delete.RestDeleteAction; -import org.elasticsearch.rest.action.explain.RestExplainAction; -import org.elasticsearch.rest.action.fieldstats.RestFieldStatsAction; -import org.elasticsearch.rest.action.get.RestGetAction; -import org.elasticsearch.rest.action.get.RestGetSourceAction; -import org.elasticsearch.rest.action.get.RestHeadAction; -import org.elasticsearch.rest.action.get.RestMultiGetAction; -import org.elasticsearch.rest.action.index.RestIndexAction; -import org.elasticsearch.rest.action.ingest.RestDeletePipelineAction; -import org.elasticsearch.rest.action.ingest.RestGetPipelineAction; -import org.elasticsearch.rest.action.ingest.RestPutPipelineAction; -import org.elasticsearch.rest.action.ingest.RestSimulatePipelineAction; -import org.elasticsearch.rest.action.main.RestMainAction; -import org.elasticsearch.rest.action.search.RestClearScrollAction; -import org.elasticsearch.rest.action.search.RestMultiSearchAction; -import org.elasticsearch.rest.action.search.RestSearchAction; -import org.elasticsearch.rest.action.search.RestSearchScrollAction; -import org.elasticsearch.rest.action.suggest.RestSuggestAction; -import org.elasticsearch.rest.action.termvectors.RestMultiTermVectorsAction; -import org.elasticsearch.rest.action.termvectors.RestTermVectorsAction; -import org.elasticsearch.rest.action.update.RestUpdateAction; import org.elasticsearch.tasks.RawTaskStatus; import org.elasticsearch.tasks.Task; import org.elasticsearch.transport.Transport; @@ -151,9 +48,6 @@ import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.local.LocalTransport; import org.elasticsearch.transport.netty.NettyTransport; -import java.util.Arrays; -import java.util.List; - /** * A module to handle registering and binding all network related classes. */ @@ -171,140 +65,6 @@ public class NetworkModule extends AbstractModule { Setting.simpleString(TRANSPORT_SERVICE_TYPE_KEY, Property.NodeScope); public static final Setting TRANSPORT_TYPE_SETTING = Setting.simpleString(TRANSPORT_TYPE_KEY, Property.NodeScope); - - - private static final List> builtinRestHandlers = Arrays.asList( - RestMainAction.class, - RestNodesInfoAction.class, - RestNodesStatsAction.class, - RestNodesHotThreadsAction.class, - RestClusterAllocationExplainAction.class, - RestClusterStatsAction.class, - RestClusterStateAction.class, - RestClusterHealthAction.class, - RestClusterUpdateSettingsAction.class, - RestClusterGetSettingsAction.class, - RestClusterRerouteAction.class, - RestClusterSearchShardsAction.class, - RestPendingClusterTasksAction.class, - RestPutRepositoryAction.class, - RestGetRepositoriesAction.class, - RestDeleteRepositoryAction.class, - RestVerifyRepositoryAction.class, - RestGetSnapshotsAction.class, - RestCreateSnapshotAction.class, - RestRestoreSnapshotAction.class, - RestDeleteSnapshotAction.class, - RestSnapshotsStatusAction.class, - - RestIndicesExistsAction.class, - RestTypesExistsAction.class, - RestGetIndicesAction.class, - RestIndicesStatsAction.class, - RestIndicesSegmentsAction.class, - RestIndicesShardStoresAction.class, - RestGetAliasesAction.class, - RestAliasesExistAction.class, - RestIndexDeleteAliasesAction.class, - RestIndexPutAliasAction.class, - RestIndicesAliasesAction.class, - RestCreateIndexAction.class, - RestShrinkIndexAction.class, - RestRolloverIndexAction.class, - RestDeleteIndexAction.class, - RestCloseIndexAction.class, - RestOpenIndexAction.class, - - RestUpdateSettingsAction.class, - RestGetSettingsAction.class, - - RestAnalyzeAction.class, - RestGetIndexTemplateAction.class, - RestPutIndexTemplateAction.class, - RestDeleteIndexTemplateAction.class, - RestHeadIndexTemplateAction.class, - - RestPutMappingAction.class, - RestGetMappingAction.class, - RestGetFieldMappingAction.class, - - RestRefreshAction.class, - RestFlushAction.class, - RestSyncedFlushAction.class, - RestForceMergeAction.class, - RestUpgradeAction.class, - RestClearIndicesCacheAction.class, - - RestIndexAction.class, - RestGetAction.class, - RestGetSourceAction.class, - RestHeadAction.Document.class, - RestHeadAction.Source.class, - RestMultiGetAction.class, - RestDeleteAction.class, - org.elasticsearch.rest.action.count.RestCountAction.class, - RestSuggestAction.class, - RestTermVectorsAction.class, - RestMultiTermVectorsAction.class, - RestBulkAction.class, - RestUpdateAction.class, - - RestSearchAction.class, - RestSearchScrollAction.class, - RestClearScrollAction.class, - RestMultiSearchAction.class, - - RestValidateQueryAction.class, - - RestExplainAction.class, - - RestRecoveryAction.class, - - // Scripts API - RestGetStoredScriptAction.class, - RestPutStoredScriptAction.class, - RestDeleteStoredScriptAction.class, - - RestFieldStatsAction.class, - - // no abstract cat action - RestCatAction.class, - - // Tasks API - RestListTasksAction.class, - RestGetTaskAction.class, - RestCancelTasksAction.class, - - // Ingest API - RestPutPipelineAction.class, - RestGetPipelineAction.class, - RestDeletePipelineAction.class, - RestSimulatePipelineAction.class - ); - - private static final List> builtinCatHandlers = Arrays.asList( - RestAllocationAction.class, - RestShardsAction.class, - RestMasterAction.class, - RestNodesAction.class, - RestTasksAction.class, - RestIndicesAction.class, - RestSegmentsAction.class, - // Fully qualified to prevent interference with rest.action.count.RestCountAction - org.elasticsearch.rest.action.cat.RestCountAction.class, - // Fully qualified to prevent interference with rest.action.indices.RestRecoveryAction - org.elasticsearch.rest.action.cat.RestRecoveryAction.class, - RestHealthAction.class, - org.elasticsearch.rest.action.cat.RestPendingClusterTasksAction.class, - RestAliasAction.class, - RestThreadPoolAction.class, - RestPluginsAction.class, - RestFielddataAction.class, - RestNodeAttrsAction.class, - RestRepositoriesAction.class, - RestSnapshotAction.class - ); - private final NetworkService networkService; private final Settings settings; private final boolean transportClient; @@ -313,9 +73,6 @@ public class NetworkModule extends AbstractModule { private final ExtensionPoint.SelectedType transportServiceTypes = new ExtensionPoint.SelectedType<>("transport_service", TransportService.class); private final ExtensionPoint.SelectedType transportTypes = new ExtensionPoint.SelectedType<>("transport", Transport.class); private final ExtensionPoint.SelectedType httpTransportTypes = new ExtensionPoint.SelectedType<>("http_transport", HttpServerTransport.class); - private final ExtensionPoint.ClassSet restHandlers = new ExtensionPoint.ClassSet<>("rest_handler", RestHandler.class); - // we must separate the cat rest handlers so RestCatAction can collect them... - private final ExtensionPoint.ClassSet catHandlers = new ExtensionPoint.ClassSet<>("cat_handler", AbstractCatAction.class); private final NamedWriteableRegistry namedWriteableRegistry; /** @@ -340,13 +97,6 @@ public class NetworkModule extends AbstractModule { if (transportClient == false) { registerHttpTransport(NETTY_TRANSPORT, NettyHttpServerTransport.class); - - for (Class catAction : builtinCatHandlers) { - catHandlers.registerExtension(catAction); - } - for (Class restAction : builtinRestHandlers) { - restHandlers.registerExtension(restAction); - } } } @@ -373,19 +123,6 @@ public class NetworkModule extends AbstractModule { httpTransportTypes.registerExtension(name, clazz); } - /** Adds an additional rest action. */ - // TODO: change this further to eliminate the middle man, ie RestController, and just register method and path here - public void registerRestHandler(Class clazz) { - if (transportClient) { - throw new IllegalArgumentException("Cannot register rest handler " + clazz.getName() + " for transport client"); - } - if (AbstractCatAction.class.isAssignableFrom(clazz)) { - catHandlers.registerExtension(clazz.asSubclass(AbstractCatAction.class)); - } else { - restHandlers.registerExtension(clazz); - } - } - public void registerTaskStatus(String name, Writeable.Reader reader) { namedWriteableRegistry.register(Task.Status.class, name, reader); } @@ -430,9 +167,6 @@ public class NetworkModule extends AbstractModule { bind(HttpServer.class).asEagerSingleton(); httpTransportTypes.bindType(binder(), settings, HTTP_TYPE_SETTING.getKey(), NETTY_TRANSPORT); } - bind(RestController.class).asEagerSingleton(); - catHandlers.bind(binder()); - restHandlers.bind(binder()); // Bind the AllocationCommandRegistry so RestClusterRerouteAction can get it. bind(AllocationCommandRegistry.class).toInstance(allocationCommandRegistry); } diff --git a/core/src/main/java/org/elasticsearch/node/Node.java b/core/src/main/java/org/elasticsearch/node/Node.java index 211ff9ffe65..1d18f696163 100644 --- a/core/src/main/java/org/elasticsearch/node/Node.java +++ b/core/src/main/java/org/elasticsearch/node/Node.java @@ -26,6 +26,8 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchTimeoutException; import org.elasticsearch.Version; import org.elasticsearch.action.ActionModule; +import org.elasticsearch.action.GenericAction; +import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.client.Client; import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.cluster.ClusterModule; @@ -42,6 +44,7 @@ import org.elasticsearch.common.StopWatch; import org.elasticsearch.common.component.Lifecycle; import org.elasticsearch.common.component.LifecycleComponent; import org.elasticsearch.common.inject.Injector; +import org.elasticsearch.common.inject.Key; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.inject.ModulesBuilder; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; @@ -122,6 +125,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -165,7 +169,7 @@ public class Node implements Closeable { private final Environment environment; private final NodeEnvironment nodeEnvironment; private final PluginsService pluginsService; - private final Client client; + private final NodeClient client; /** * Constructs a node with the given settings. @@ -275,9 +279,10 @@ public class Node implements Closeable { BigArrays bigArrays = createBigArrays(settings, circuitBreakerService); resourcesToClose.add(bigArrays); modules.add(settingsModule); + client = new NodeClient(settings, threadPool); modules.add(b -> { b.bind(PluginsService.class).toInstance(pluginsService); - b.bind(Client.class).to(NodeClient.class).asEagerSingleton(); + b.bind(Client.class).toInstance(client); b.bind(Environment.class).toInstance(environment); b.bind(ThreadPool.class).toInstance(threadPool); b.bind(NodeEnvironment.class).toInstance(nodeEnvironment); @@ -290,7 +295,7 @@ public class Node implements Closeable { } ); injector = modules.createInjector(); - client = injector.getInstance(Client.class); + client.intialize(injector.getInstance(new Key>() {})); success = true; } catch (IOException ex) { throw new ElasticsearchException("failed to bind service", ex); diff --git a/core/src/main/java/org/elasticsearch/plugins/ActionPlugin.java b/core/src/main/java/org/elasticsearch/plugins/ActionPlugin.java index 0d4ee16ab89..f05c6654393 100644 --- a/core/src/main/java/org/elasticsearch/plugins/ActionPlugin.java +++ b/core/src/main/java/org/elasticsearch/plugins/ActionPlugin.java @@ -25,8 +25,11 @@ import org.elasticsearch.action.GenericAction; import org.elasticsearch.action.support.ActionFilter; import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.action.support.TransportActions; +import org.elasticsearch.common.Strings; +import org.elasticsearch.rest.RestHandler; import java.util.List; +import java.util.Objects; import static java.util.Collections.emptyList; @@ -55,6 +58,12 @@ public interface ActionPlugin { default List> getActionFilters() { return emptyList(); } + /** + * Rest handlers added by this plugin. + */ + default List> getRestHandlers() { + return emptyList(); + } public static final class ActionHandler, Response extends ActionResponse> { private final GenericAction action; @@ -83,5 +92,30 @@ public interface ActionPlugin { public Class[] getSupportTransportActions() { return supportTransportActions; } + + @Override + public String toString() { + StringBuilder b = new StringBuilder().append(action.name()).append(" is handled by ").append(transportAction.getName()); + if (supportTransportActions.length > 0) { + b.append('[').append(Strings.arrayToCommaDelimitedString(supportTransportActions)).append(']'); + } + return b.toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null || obj.getClass() != ActionHandler.class) { + return false; + } + ActionHandler other = (ActionHandler) obj; + return Objects.equals(action, other.action) + && Objects.equals(transportAction, other.transportAction) + && Objects.deepEquals(supportTransportActions, other.supportTransportActions); + } + + @Override + public int hashCode() { + return Objects.hash(action, transportAction, supportTransportActions); + } } } diff --git a/core/src/main/java/org/elasticsearch/rest/RestController.java b/core/src/main/java/org/elasticsearch/rest/RestController.java index be72ed19c40..e8212ff09c6 100644 --- a/core/src/main/java/org/elasticsearch/rest/RestController.java +++ b/core/src/main/java/org/elasticsearch/rest/RestController.java @@ -22,7 +22,6 @@ package org.elasticsearch.rest; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.component.AbstractLifecycleComponent; -import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.path.PathTrie; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; @@ -59,7 +58,6 @@ public class RestController extends AbstractLifecycleComponent { // non volatile since the assumption is that pre processors are registered on startup private RestFilter[] filters = new RestFilter[0]; - @Inject public RestController(Settings settings) { super(settings); } diff --git a/core/src/test/java/org/elasticsearch/action/ActionModuleTests.java b/core/src/test/java/org/elasticsearch/action/ActionModuleTests.java new file mode 100644 index 00000000000..4b9a833e8c4 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/action/ActionModuleTests.java @@ -0,0 +1,129 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action; + +import org.elasticsearch.action.main.MainAction; +import org.elasticsearch.action.main.TransportMainAction; +import org.elasticsearch.action.support.ActionFilters; +import org.elasticsearch.action.support.TransportAction; +import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.plugins.ActionPlugin; +import org.elasticsearch.plugins.ActionPlugin.ActionHandler; +import org.elasticsearch.rest.RestChannel; +import org.elasticsearch.rest.RestHandler; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.action.main.RestMainAction; +import org.elasticsearch.tasks.TaskManager; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.threadpool.ThreadPool; + +import java.util.List; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.hasItem; + +public class ActionModuleTests extends ESTestCase { + public void testSetupActionsContainsKnownBuiltin() { + assertThat(ActionModule.setupActions(emptyList()), + hasEntry(MainAction.INSTANCE.name(), new ActionHandler<>(MainAction.INSTANCE, TransportMainAction.class))); + } + + public void testPluginCantOverwriteBuiltinAction() { + ActionPlugin dupsMainAction = new ActionPlugin() { + @Override + public List, ? extends ActionResponse>> getActions() { + return singletonList(new ActionHandler<>(MainAction.INSTANCE, TransportMainAction.class)); + } + }; + Exception e = expectThrows(IllegalArgumentException.class, () -> ActionModule.setupActions(singletonList(dupsMainAction))); + assertEquals("action for name [" + MainAction.NAME + "] already registered", e.getMessage()); + } + + public void testPluginCanRegisterAction() { + class FakeRequest extends ActionRequest { + @Override + public ActionRequestValidationException validate() { + return null; + } + } + class FakeTransportAction extends TransportAction { + protected FakeTransportAction(Settings settings, String actionName, ThreadPool threadPool, ActionFilters actionFilters, + IndexNameExpressionResolver indexNameExpressionResolver, TaskManager taskManager) { + super(settings, actionName, threadPool, actionFilters, indexNameExpressionResolver, taskManager); + } + + @Override + protected void doExecute(FakeRequest request, ActionListener listener) { + } + } + class FakeAction extends GenericAction { + protected FakeAction() { + super("fake"); + } + + @Override + public ActionResponse newResponse() { + return null; + } + } + FakeAction action = new FakeAction(); + ActionPlugin registersFakeAction = new ActionPlugin() { + @Override + public List, ? extends ActionResponse>> getActions() { + return singletonList(new ActionHandler<>(action, FakeTransportAction.class)); + } + }; + assertThat(ActionModule.setupActions(singletonList(registersFakeAction)), + hasEntry("fake", new ActionHandler<>(action, FakeTransportAction.class))); + } + + public void testSetupRestHandlerContainsKnownBuiltin() { + assertThat(ActionModule.setupRestHandlers(emptyList()), hasItem(RestMainAction.class)); + } + + public void testPluginCantOverwriteBuiltinRestHandler() { + ActionPlugin dupsMainAction = new ActionPlugin() { + @Override + public List> getRestHandlers() { + return singletonList(RestMainAction.class); + } + }; + Exception e = expectThrows(IllegalArgumentException.class, () -> ActionModule.setupRestHandlers(singletonList(dupsMainAction))); + assertEquals("can't register the same [rest_handler] more than once for [" + RestMainAction.class.getName() + "]", e.getMessage()); + } + + public void testPluginCanRegisterRestHandler() { + class FakeHandler implements RestHandler { + @Override + public void handleRequest(RestRequest request, RestChannel channel) throws Exception { + } + } + ActionPlugin registersFakeHandler = new ActionPlugin() { + @Override + public List> getRestHandlers() { + return singletonList(FakeHandler.class); + } + }; + assertThat(ActionModule.setupRestHandlers(singletonList(registersFakeHandler)), hasItem(FakeHandler.class)); + } +} diff --git a/core/src/test/java/org/elasticsearch/client/node/NodeClientHeadersTests.java b/core/src/test/java/org/elasticsearch/client/node/NodeClientHeadersTests.java index f69c8f2da0b..04f7b73b1f2 100644 --- a/core/src/test/java/org/elasticsearch/client/node/NodeClientHeadersTests.java +++ b/core/src/test/java/org/elasticsearch/client/node/NodeClientHeadersTests.java @@ -46,7 +46,9 @@ public class NodeClientHeadersTests extends AbstractClientHeadersTestCase { protected Client buildClient(Settings headersSettings, GenericAction[] testedActions) { Settings settings = HEADER_SETTINGS; Actions actions = new Actions(settings, threadPool, testedActions); - return new NodeClient(settings, threadPool, actions); + NodeClient client = new NodeClient(settings, threadPool); + client.intialize(actions); + return client; } private static class Actions extends HashMap { diff --git a/core/src/test/java/org/elasticsearch/common/network/NetworkModuleTests.java b/core/src/test/java/org/elasticsearch/common/network/NetworkModuleTests.java index d54edbcaa9d..749ffa3c9d9 100644 --- a/core/src/test/java/org/elasticsearch/common/network/NetworkModuleTests.java +++ b/core/src/test/java/org/elasticsearch/common/network/NetworkModuleTests.java @@ -36,11 +36,8 @@ import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.http.HttpStats; import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.rest.RestChannel; -import org.elasticsearch.rest.RestHandler; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.action.cat.AbstractCatAction; -import org.elasticsearch.rest.action.cat.RestNodesAction; -import org.elasticsearch.rest.action.main.RestMainAction; import org.elasticsearch.tasks.Task; import org.elasticsearch.test.transport.AssertingLocalTransport; import org.elasticsearch.transport.Transport; @@ -163,32 +160,6 @@ public class NetworkModuleTests extends ModuleTestCase { assertFalse(module.isTransportClient()); } - public void testRegisterRestHandler() { - Settings settings = Settings.EMPTY; - NetworkModule module = new NetworkModule(new NetworkService(settings), settings, false, new NamedWriteableRegistry()); - module.registerRestHandler(FakeRestHandler.class); - // also check a builtin is bound - assertSetMultiBinding(module, RestHandler.class, FakeRestHandler.class, RestMainAction.class); - - // check registration not allowed for transport only - module = new NetworkModule(new NetworkService(settings), settings, true, new NamedWriteableRegistry()); - try { - module.registerRestHandler(FakeRestHandler.class); - fail(); - } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().contains("Cannot register rest handler")); - assertTrue(e.getMessage().contains("for transport client")); - } - } - - public void testRegisterCatRestHandler() { - Settings settings = Settings.EMPTY; - NetworkModule module = new NetworkModule(new NetworkService(settings), settings, false, new NamedWriteableRegistry()); - module.registerRestHandler(FakeCatRestHandler.class); - // also check a builtin is bound - assertSetMultiBinding(module, AbstractCatAction.class, FakeCatRestHandler.class, RestNodesAction.class); - } - public void testRegisterTaskStatus() { NamedWriteableRegistry registry = new NamedWriteableRegistry(); Settings settings = Settings.EMPTY; diff --git a/core/src/test/java/org/elasticsearch/plugins/responseheader/TestResponseHeaderPlugin.java b/core/src/test/java/org/elasticsearch/plugins/responseheader/TestResponseHeaderPlugin.java index 701d1154587..9dfd5b6a93a 100644 --- a/core/src/test/java/org/elasticsearch/plugins/responseheader/TestResponseHeaderPlugin.java +++ b/core/src/test/java/org/elasticsearch/plugins/responseheader/TestResponseHeaderPlugin.java @@ -19,12 +19,17 @@ package org.elasticsearch.plugins.responseheader; -import org.elasticsearch.common.network.NetworkModule; +import org.elasticsearch.plugins.ActionPlugin; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.rest.RestHandler; -public class TestResponseHeaderPlugin extends Plugin { +import java.util.List; - public void onModule(NetworkModule module) { - module.registerRestHandler(TestResponseHeaderRestAction.class); +import static java.util.Collections.singletonList; + +public class TestResponseHeaderPlugin extends Plugin implements ActionPlugin { + @Override + public List> getRestHandlers() { + return singletonList(TestResponseHeaderRestAction.class); } } diff --git a/docs/reference/migration/migrate_5_0/plugins.asciidoc b/docs/reference/migration/migrate_5_0/plugins.asciidoc index e1e8e6c614b..2826c822d15 100644 --- a/docs/reference/migration/migrate_5_0/plugins.asciidoc +++ b/docs/reference/migration/migrate_5_0/plugins.asciidoc @@ -137,3 +137,6 @@ Plugins that register custom mappers should implement Plugins that register custom actions should implement `ActionPlugin` and remove their `onModule(ActionModule)` implementation. + +Plugins that register custom `RestHandler`s should implement `ActionPlugin` and +remove their `onModule(NetworkModule)` implemnetation. diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustachePlugin.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustachePlugin.java index 50bae57887c..d3ffa13cd54 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustachePlugin.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustachePlugin.java @@ -25,11 +25,11 @@ import org.elasticsearch.action.search.template.MultiSearchTemplateAction; import org.elasticsearch.action.search.template.SearchTemplateAction; import org.elasticsearch.action.search.template.TransportMultiSearchTemplateAction; import org.elasticsearch.action.search.template.TransportSearchTemplateAction; -import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.ActionPlugin; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.ScriptPlugin; +import org.elasticsearch.rest.RestHandler; import org.elasticsearch.rest.action.search.template.RestDeleteSearchTemplateAction; import org.elasticsearch.rest.action.search.template.RestGetSearchTemplateAction; import org.elasticsearch.rest.action.search.template.RestMultiSearchTemplateAction; @@ -54,14 +54,9 @@ public class MustachePlugin extends Plugin implements ScriptPlugin, ActionPlugin new ActionHandler<>(MultiSearchTemplateAction.INSTANCE, TransportMultiSearchTemplateAction.class)); } - public void onModule(NetworkModule module) { - if (module.isTransportClient() == false) { - module.registerRestHandler(RestSearchTemplateAction.class); - module.registerRestHandler(RestMultiSearchTemplateAction.class); - module.registerRestHandler(RestGetSearchTemplateAction.class); - module.registerRestHandler(RestPutSearchTemplateAction.class); - module.registerRestHandler(RestDeleteSearchTemplateAction.class); - module.registerRestHandler(RestRenderSearchTemplateAction.class); - } + @Override + public List> getRestHandlers() { + return Arrays.asList(RestSearchTemplateAction.class, RestMultiSearchTemplateAction.class, RestGetSearchTemplateAction.class, + RestPutSearchTemplateAction.class, RestDeleteSearchTemplateAction.class, RestRenderSearchTemplateAction.class); } } diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorPlugin.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorPlugin.java index 87fc6726c56..a15acf67c02 100644 --- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorPlugin.java +++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorPlugin.java @@ -23,13 +23,13 @@ import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionResponse; import org.elasticsearch.client.Client; import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.plugins.ActionPlugin; import org.elasticsearch.plugins.MapperPlugin; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.rest.RestHandler; import org.elasticsearch.search.SearchModule; import java.util.Arrays; @@ -41,11 +41,9 @@ public class PercolatorPlugin extends Plugin implements MapperPlugin, ActionPlug public static final String NAME = "percolator"; - private final boolean transportClientMode; private final Settings settings; public PercolatorPlugin(Settings settings) { - this.transportClientMode = transportClientMode(settings); this.settings = settings; } @@ -55,11 +53,9 @@ public class PercolatorPlugin extends Plugin implements MapperPlugin, ActionPlug new ActionHandler<>(MultiPercolateAction.INSTANCE, TransportMultiPercolateAction.class)); } - public void onModule(NetworkModule module) { - if (transportClientMode == false) { - module.registerRestHandler(RestPercolateAction.class); - module.registerRestHandler(RestMultiPercolateAction.class); - } + @Override + public List> getRestHandlers() { + return Arrays.asList(RestPercolateAction.class, RestMultiPercolateAction.class); } public void onModule(SearchModule module) { diff --git a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/ReindexPlugin.java b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/ReindexPlugin.java index 89e6c1cc753..5a7b81a7124 100644 --- a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/ReindexPlugin.java +++ b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/ReindexPlugin.java @@ -24,6 +24,7 @@ import org.elasticsearch.action.ActionResponse; import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.plugins.ActionPlugin; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.rest.RestHandler; import java.util.Arrays; import java.util.List; @@ -39,11 +40,13 @@ public class ReindexPlugin extends Plugin implements ActionPlugin { new ActionHandler<>(RethrottleAction.INSTANCE, TransportRethrottleAction.class)); } + @Override + public List> getRestHandlers() { + return Arrays.asList(RestReindexAction.class, RestUpdateByQueryAction.class, RestDeleteByQueryAction.class, + RestRethrottleAction.class); + } + public void onModule(NetworkModule networkModule) { - networkModule.registerRestHandler(RestReindexAction.class); - networkModule.registerRestHandler(RestUpdateByQueryAction.class); - networkModule.registerRestHandler(RestDeleteByQueryAction.class); - networkModule.registerRestHandler(RestRethrottleAction.class); networkModule.registerTaskStatus(BulkByScrollTask.Status.NAME, BulkByScrollTask.Status::new); } }