Skip to content

Commit e45a7b1

Browse files
authored
Split plugin loading into two different phases to support entitlements (#116998) (#117215)
This change loads all the modules and creates the module layers for plugins prior to entitlement checking during the 2nd phase of bootstrap initialization. This will allow us to know what modules exist for both validation and checking prior to actually loading any plugin classes (in a follow up change). There are now two classes: PluginsLoader which does the module loading and layer creation PluginsService which uses a PluginsLoader to create the main plugin classes and start the plugins
1 parent ad3903d commit e45a7b1

File tree

13 files changed

+591
-437
lines changed

13 files changed

+591
-437
lines changed

benchmarks/src/main/java/org/elasticsearch/benchmark/script/ScriptScoreBenchmark.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType;
3535
import org.elasticsearch.indices.breaker.CircuitBreakerService;
3636
import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
37+
import org.elasticsearch.plugins.PluginsLoader;
3738
import org.elasticsearch.plugins.PluginsService;
3839
import org.elasticsearch.plugins.ScriptPlugin;
3940
import org.elasticsearch.script.DocReader;
@@ -76,8 +77,7 @@ public class ScriptScoreBenchmark {
7677
private final PluginsService pluginsService = new PluginsService(
7778
Settings.EMPTY,
7879
null,
79-
null,
80-
Path.of(System.getProperty("plugins.dir"))
80+
new PluginsLoader(null, Path.of(System.getProperty("plugins.dir")))
8181
);
8282
private final ScriptModule scriptModule = new ScriptModule(Settings.EMPTY, pluginsService.filterPlugins(ScriptPlugin.class).toList());
8383

server/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.elasticsearch.core.SuppressForbidden;
1818
import org.elasticsearch.env.Environment;
1919
import org.elasticsearch.node.NodeValidationException;
20+
import org.elasticsearch.plugins.PluginsLoader;
2021

2122
import java.io.PrintStream;
2223

@@ -42,6 +43,9 @@ class Bootstrap {
4243
// the loaded settings for the node, not valid until after phase 2 of initialization
4344
private final SetOnce<Environment> nodeEnv = new SetOnce<>();
4445

46+
// loads information about plugins required for entitlements in phase 2, used by plugins service in phase 3
47+
private final SetOnce<PluginsLoader> pluginsLoader = new SetOnce<>();
48+
4549
Bootstrap(PrintStream out, PrintStream err, ServerArgs args) {
4650
this.out = out;
4751
this.err = err;
@@ -72,6 +76,14 @@ Environment environment() {
7276
return nodeEnv.get();
7377
}
7478

79+
void setPluginsLoader(PluginsLoader pluginsLoader) {
80+
this.pluginsLoader.set(pluginsLoader);
81+
}
82+
83+
PluginsLoader pluginsLoader() {
84+
return pluginsLoader.get();
85+
}
86+
7587
void exitWithNodeValidationException(NodeValidationException e) {
7688
Logger logger = LogManager.getLogger(Elasticsearch.class);
7789
logger.error("node validation exception\n{}", e.getMessage());

server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.elasticsearch.nativeaccess.NativeAccess;
4242
import org.elasticsearch.node.Node;
4343
import org.elasticsearch.node.NodeValidationException;
44+
import org.elasticsearch.plugins.PluginsLoader;
4445

4546
import java.io.IOException;
4647
import java.io.InputStream;
@@ -199,6 +200,9 @@ private static void initPhase2(Bootstrap bootstrap) throws IOException {
199200
VectorUtil.class
200201
);
201202

203+
// load the plugin Java modules and layers now for use in entitlements
204+
bootstrap.setPluginsLoader(new PluginsLoader(nodeEnv.modulesFile(), nodeEnv.pluginsFile()));
205+
202206
if (Boolean.parseBoolean(System.getProperty("es.entitlements.enabled"))) {
203207
logger.info("Bootstrapping Entitlements");
204208
EntitlementBootstrap.bootstrap();
@@ -244,7 +248,7 @@ private static void ensureInitialized(Class<?>... classes) {
244248
private static void initPhase3(Bootstrap bootstrap) throws IOException, NodeValidationException {
245249
checkLucene();
246250

247-
Node node = new Node(bootstrap.environment()) {
251+
Node node = new Node(bootstrap.environment(), bootstrap.pluginsLoader()) {
248252
@Override
249253
protected void validateNodeBeforeAcceptingRequests(
250254
final BootstrapContext context,

server/src/main/java/org/elasticsearch/node/Node.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import org.elasticsearch.plugins.ClusterPlugin;
7474
import org.elasticsearch.plugins.MetadataUpgrader;
7575
import org.elasticsearch.plugins.Plugin;
76+
import org.elasticsearch.plugins.PluginsLoader;
7677
import org.elasticsearch.plugins.PluginsService;
7778
import org.elasticsearch.readiness.ReadinessService;
7879
import org.elasticsearch.repositories.RepositoriesService;
@@ -196,8 +197,8 @@ public class Node implements Closeable {
196197
*
197198
* @param environment the initial environment for this node, which will be added to by plugins
198199
*/
199-
public Node(Environment environment) {
200-
this(NodeConstruction.prepareConstruction(environment, new NodeServiceProvider(), true));
200+
public Node(Environment environment, PluginsLoader pluginsLoader) {
201+
this(NodeConstruction.prepareConstruction(environment, pluginsLoader, new NodeServiceProvider(), true));
201202
}
202203

203204
/**

server/src/main/java/org/elasticsearch/node/NodeConstruction.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@
165165
import org.elasticsearch.plugins.NetworkPlugin;
166166
import org.elasticsearch.plugins.PersistentTaskPlugin;
167167
import org.elasticsearch.plugins.Plugin;
168+
import org.elasticsearch.plugins.PluginsLoader;
168169
import org.elasticsearch.plugins.PluginsService;
169170
import org.elasticsearch.plugins.RecoveryPlannerPlugin;
170171
import org.elasticsearch.plugins.ReloadablePlugin;
@@ -260,14 +261,15 @@ class NodeConstruction {
260261
*/
261262
static NodeConstruction prepareConstruction(
262263
Environment initialEnvironment,
264+
PluginsLoader pluginsLoader,
263265
NodeServiceProvider serviceProvider,
264266
boolean forbidPrivateIndexSettings
265267
) {
266268
List<Closeable> closeables = new ArrayList<>();
267269
try {
268270
NodeConstruction constructor = new NodeConstruction(closeables);
269271

270-
Settings settings = constructor.createEnvironment(initialEnvironment, serviceProvider);
272+
Settings settings = constructor.createEnvironment(initialEnvironment, serviceProvider, pluginsLoader);
271273
constructor.loadLoggingDataProviders();
272274
TelemetryProvider telemetryProvider = constructor.createTelemetryProvider(settings);
273275
ThreadPool threadPool = constructor.createThreadPool(settings, telemetryProvider.getMeterRegistry());
@@ -400,7 +402,7 @@ private static <T> Optional<T> getSinglePlugin(Stream<T> plugins, Class<T> plugi
400402
return Optional.of(plugin);
401403
}
402404

403-
private Settings createEnvironment(Environment initialEnvironment, NodeServiceProvider serviceProvider) {
405+
private Settings createEnvironment(Environment initialEnvironment, NodeServiceProvider serviceProvider, PluginsLoader pluginsLoader) {
404406
// Pass the node settings to the DeprecationLogger class so that it can have the deprecation.skip_deprecated_settings setting:
405407
Settings envSettings = initialEnvironment.settings();
406408
DeprecationLogger.initialize(envSettings);
@@ -473,7 +475,7 @@ private Settings createEnvironment(Environment initialEnvironment, NodeServicePr
473475
(e, apmConfig) -> logger.error("failed to delete temporary APM config file [{}], reason: [{}]", apmConfig, e.getMessage())
474476
);
475477

476-
pluginsService = serviceProvider.newPluginService(initialEnvironment, envSettings);
478+
pluginsService = serviceProvider.newPluginService(initialEnvironment, pluginsLoader);
477479
modules.bindToInstance(PluginsService.class, pluginsService);
478480
Settings settings = Node.mergePluginSettings(pluginsService.pluginMap(), envSettings);
479481

server/src/main/java/org/elasticsearch/node/NodeServiceProvider.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.elasticsearch.indices.IndicesService;
2828
import org.elasticsearch.indices.breaker.CircuitBreakerService;
2929
import org.elasticsearch.indices.recovery.RecoverySettings;
30+
import org.elasticsearch.plugins.PluginsLoader;
3031
import org.elasticsearch.plugins.PluginsService;
3132
import org.elasticsearch.readiness.ReadinessService;
3233
import org.elasticsearch.script.ScriptContext;
@@ -51,9 +52,9 @@
5152
*/
5253
class NodeServiceProvider {
5354

54-
PluginsService newPluginService(Environment environment, Settings settings) {
55+
PluginsService newPluginService(Environment initialEnvironment, PluginsLoader pluginsLoader) {
5556
// this creates a PluginsService with an empty list of classpath plugins
56-
return new PluginsService(settings, environment.configFile(), environment.modulesFile(), environment.pluginsFile());
57+
return new PluginsService(initialEnvironment.settings(), initialEnvironment.configFile(), pluginsLoader);
5758
}
5859

5960
ScriptService newScriptService(

0 commit comments

Comments
 (0)