Răsfoiți Sursa

Plugins: Allow modules to spawn controllers (#28968)

This commit makes the controller spawner also look under modules. It
also fixes a bug in module security policy loading where the module is a
meta plugin.
Ryan Ernst 7 ani în urmă
părinte
comite
4216fc9f64

+ 31 - 20
qa/no-bootstrap-tests/src/test/java/org/elasticsearch/bootstrap/SpawnerNoBootstrapTests.java

@@ -42,6 +42,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
@@ -77,6 +78,7 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
 
         // This plugin will NOT have a controller daemon
         Path plugin = environment.pluginsFile().resolve("a_plugin");
+        Files.createDirectories(environment.modulesFile());
         Files.createDirectories(plugin);
         PluginTestUtil.writePluginProperties(
                 plugin,
@@ -97,7 +99,12 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
     /**
      * Two plugins - one with a controller daemon and one without.
      */
-    public void testControllerSpawn() throws IOException, InterruptedException {
+    public void testControllerSpawn() throws Exception {
+        assertControllerSpawns(Environment::pluginsFile);
+        assertControllerSpawns(Environment::modulesFile);
+    }
+
+    private void assertControllerSpawns(Function<Environment, Path> pluginsDirFinder) throws Exception {
         /*
          * On Windows you can not directly run a batch file - you have to run cmd.exe with the batch
          * file as an argument and that's out of the remit of the controller daemon process spawner.
@@ -112,32 +119,34 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
         Environment environment = TestEnvironment.newEnvironment(settings);
 
         // this plugin will have a controller daemon
-        Path plugin = environment.pluginsFile().resolve("test_plugin");
+        Path plugin = pluginsDirFinder.apply(environment).resolve("test_plugin");
+        Files.createDirectories(environment.modulesFile());
+        Files.createDirectories(environment.pluginsFile());
         Files.createDirectories(plugin);
         PluginTestUtil.writePluginProperties(
-                plugin,
-                "description", "test_plugin",
-                "version", Version.CURRENT.toString(),
-                "elasticsearch.version", Version.CURRENT.toString(),
-                "name", "test_plugin",
-                "java.version", "1.8",
-                "classname", "TestPlugin",
-                "has.native.controller", "true");
+            plugin,
+            "description", "test_plugin",
+            "version", Version.CURRENT.toString(),
+            "elasticsearch.version", Version.CURRENT.toString(),
+            "name", "test_plugin",
+            "java.version", "1.8",
+            "classname", "TestPlugin",
+            "has.native.controller", "true");
         Path controllerProgram = Platforms.nativeControllerPath(plugin);
         createControllerProgram(controllerProgram);
 
         // this plugin will not have a controller daemon
-        Path otherPlugin = environment.pluginsFile().resolve("other_plugin");
+        Path otherPlugin = pluginsDirFinder.apply(environment).resolve("other_plugin");
         Files.createDirectories(otherPlugin);
         PluginTestUtil.writePluginProperties(
-                otherPlugin,
-                "description", "other_plugin",
-                "version", Version.CURRENT.toString(),
-                "elasticsearch.version", Version.CURRENT.toString(),
-                "name", "other_plugin",
-                "java.version", "1.8",
-                "classname", "OtherPlugin",
-                "has.native.controller", "false");
+            otherPlugin,
+            "description", "other_plugin",
+            "version", Version.CURRENT.toString(),
+            "elasticsearch.version", Version.CURRENT.toString(),
+            "name", "other_plugin",
+            "java.version", "1.8",
+            "classname", "OtherPlugin",
+            "has.native.controller", "false");
 
         Spawner spawner = new Spawner();
         spawner.spawnNativePluginControllers(environment);
@@ -150,7 +159,7 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
         assertThat(processes, hasSize(1));
         Process process = processes.get(0);
         final InputStreamReader in =
-                new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8);
+            new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8);
         try (BufferedReader stdoutReader = new BufferedReader(in)) {
             String line = stdoutReader.readLine();
             assertEquals("I am alive", line);
@@ -181,6 +190,7 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
         Environment environment = TestEnvironment.newEnvironment(settings);
 
         Path metaPlugin = environment.pluginsFile().resolve("meta_plugin");
+        Files.createDirectories(environment.modulesFile());
         Files.createDirectories(metaPlugin);
         PluginTestUtil.writeMetaPluginProperties(
             metaPlugin,
@@ -279,6 +289,7 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
 
         final Environment environment = TestEnvironment.newEnvironment(settings);
 
+        Files.createDirectories(environment.modulesFile());
         Files.createDirectories(environment.pluginsFile());
 
         final Path desktopServicesStore = environment.pluginsFile().resolve(".DS_Store");

+ 1 - 9
server/src/main/java/org/elasticsearch/bootstrap/Security.java

@@ -163,16 +163,8 @@ final class Security {
         Map<String,Policy> map = new HashMap<>();
         // collect up set of plugins and modules by listing directories.
         Set<Path> pluginsAndModules = new LinkedHashSet<>(PluginsService.findPluginDirs(environment.pluginsFile()));
+        pluginsAndModules.addAll(PluginsService.findPluginDirs(environment.modulesFile()));
 
-        if (Files.exists(environment.modulesFile())) {
-            try (DirectoryStream<Path> stream = Files.newDirectoryStream(environment.modulesFile())) {
-                for (Path module : stream) {
-                    if (pluginsAndModules.add(module) == false) {
-                        throw new IllegalStateException("duplicate module: " + module);
-                    }
-                }
-            }
-        }
         // now process each one
         for (Path plugin : pluginsAndModules) {
             Path policyFile = plugin.resolve(PluginInfo.ES_PLUGIN_POLICY);

+ 10 - 6
server/src/main/java/org/elasticsearch/bootstrap/Spawner.java

@@ -63,15 +63,20 @@ final class Spawner implements Closeable {
         if (!spawned.compareAndSet(false, true)) {
             throw new IllegalStateException("native controllers already spawned");
         }
-        final Path pluginsFile = environment.pluginsFile();
-        if (!Files.exists(pluginsFile)) {
-            throw new IllegalStateException("plugins directory [" + pluginsFile + "] not found");
+        spawnControllers(environment.pluginsFile(), "plugins", environment.tmpFile());
+        spawnControllers(environment.modulesFile(), "modules", environment.tmpFile());
+    }
+
+    /** Spawn controllers in plugins found within the given directory. */
+    private void spawnControllers(Path pluginsDir, String type, Path tmpDir) throws IOException {
+        if (!Files.exists(pluginsDir)) {
+            throw new IllegalStateException(type + " directory [" + pluginsDir + "] not found");
         }
         /*
          * For each plugin, attempt to spawn the controller daemon. Silently ignore any plugin that
          * don't include a controller for the correct platform.
          */
-        List<Path> paths = PluginsService.findPluginDirs(pluginsFile);
+        List<Path> paths = PluginsService.findPluginDirs(pluginsDir);
         for (Path plugin : paths) {
             final PluginInfo info = PluginInfo.readFromProperties(plugin);
             final Path spawnPath = Platforms.nativeControllerPath(plugin);
@@ -85,8 +90,7 @@ final class Spawner implements Closeable {
                     plugin.getFileName());
                 throw new IllegalArgumentException(message);
             }
-            final Process process =
-                spawnNativePluginController(spawnPath, environment.tmpFile());
+            final Process process = spawnNativePluginController(spawnPath, tmpDir);
             processes.add(process);
         }
     }