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.
This commit is contained in:
Ryan Ernst 2018-03-11 09:01:27 -07:00 committed by GitHub
parent 4f644d04a3
commit 4216fc9f64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 35 deletions

View File

@ -42,6 +42,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
@ -77,6 +78,7 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
// This plugin will NOT have a controller daemon // This plugin will NOT have a controller daemon
Path plugin = environment.pluginsFile().resolve("a_plugin"); Path plugin = environment.pluginsFile().resolve("a_plugin");
Files.createDirectories(environment.modulesFile());
Files.createDirectories(plugin); Files.createDirectories(plugin);
PluginTestUtil.writePluginProperties( PluginTestUtil.writePluginProperties(
plugin, plugin,
@ -97,7 +99,12 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
/** /**
* Two plugins - one with a controller daemon and one without. * 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 * 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. * 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); Environment environment = TestEnvironment.newEnvironment(settings);
// this plugin will have a controller daemon // 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); Files.createDirectories(plugin);
PluginTestUtil.writePluginProperties( PluginTestUtil.writePluginProperties(
plugin, plugin,
"description", "test_plugin", "description", "test_plugin",
"version", Version.CURRENT.toString(), "version", Version.CURRENT.toString(),
"elasticsearch.version", Version.CURRENT.toString(), "elasticsearch.version", Version.CURRENT.toString(),
"name", "test_plugin", "name", "test_plugin",
"java.version", "1.8", "java.version", "1.8",
"classname", "TestPlugin", "classname", "TestPlugin",
"has.native.controller", "true"); "has.native.controller", "true");
Path controllerProgram = Platforms.nativeControllerPath(plugin); Path controllerProgram = Platforms.nativeControllerPath(plugin);
createControllerProgram(controllerProgram); createControllerProgram(controllerProgram);
// this plugin will not have a controller daemon // 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); Files.createDirectories(otherPlugin);
PluginTestUtil.writePluginProperties( PluginTestUtil.writePluginProperties(
otherPlugin, otherPlugin,
"description", "other_plugin", "description", "other_plugin",
"version", Version.CURRENT.toString(), "version", Version.CURRENT.toString(),
"elasticsearch.version", Version.CURRENT.toString(), "elasticsearch.version", Version.CURRENT.toString(),
"name", "other_plugin", "name", "other_plugin",
"java.version", "1.8", "java.version", "1.8",
"classname", "OtherPlugin", "classname", "OtherPlugin",
"has.native.controller", "false"); "has.native.controller", "false");
Spawner spawner = new Spawner(); Spawner spawner = new Spawner();
spawner.spawnNativePluginControllers(environment); spawner.spawnNativePluginControllers(environment);
@ -150,7 +159,7 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
assertThat(processes, hasSize(1)); assertThat(processes, hasSize(1));
Process process = processes.get(0); Process process = processes.get(0);
final InputStreamReader in = final InputStreamReader in =
new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8); new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8);
try (BufferedReader stdoutReader = new BufferedReader(in)) { try (BufferedReader stdoutReader = new BufferedReader(in)) {
String line = stdoutReader.readLine(); String line = stdoutReader.readLine();
assertEquals("I am alive", line); assertEquals("I am alive", line);
@ -181,6 +190,7 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
Environment environment = TestEnvironment.newEnvironment(settings); Environment environment = TestEnvironment.newEnvironment(settings);
Path metaPlugin = environment.pluginsFile().resolve("meta_plugin"); Path metaPlugin = environment.pluginsFile().resolve("meta_plugin");
Files.createDirectories(environment.modulesFile());
Files.createDirectories(metaPlugin); Files.createDirectories(metaPlugin);
PluginTestUtil.writeMetaPluginProperties( PluginTestUtil.writeMetaPluginProperties(
metaPlugin, metaPlugin,
@ -279,6 +289,7 @@ public class SpawnerNoBootstrapTests extends LuceneTestCase {
final Environment environment = TestEnvironment.newEnvironment(settings); final Environment environment = TestEnvironment.newEnvironment(settings);
Files.createDirectories(environment.modulesFile());
Files.createDirectories(environment.pluginsFile()); Files.createDirectories(environment.pluginsFile());
final Path desktopServicesStore = environment.pluginsFile().resolve(".DS_Store"); final Path desktopServicesStore = environment.pluginsFile().resolve(".DS_Store");

View File

@ -163,16 +163,8 @@ final class Security {
Map<String,Policy> map = new HashMap<>(); Map<String,Policy> map = new HashMap<>();
// collect up set of plugins and modules by listing directories. // collect up set of plugins and modules by listing directories.
Set<Path> pluginsAndModules = new LinkedHashSet<>(PluginsService.findPluginDirs(environment.pluginsFile())); 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 // now process each one
for (Path plugin : pluginsAndModules) { for (Path plugin : pluginsAndModules) {
Path policyFile = plugin.resolve(PluginInfo.ES_PLUGIN_POLICY); Path policyFile = plugin.resolve(PluginInfo.ES_PLUGIN_POLICY);

View File

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