Merge pull request #17208 from jasontedor/install-plugin-permissions
Install plugin permissions
This commit is contained in:
commit
17dd60dd31
|
@ -660,7 +660,6 @@
|
|||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]node[/\\]internal[/\\]InternalSettingsPreparer.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]percolator[/\\]PercolatorQuery.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]plugins[/\\]DummyPluginInfo.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]plugins[/\\]InstallPluginCommand.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]plugins[/\\]PluginsService.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]plugins[/\\]RemovePluginCommand.java" checks="LineLength" />
|
||||
<suppress files="core[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]repositories[/\\]RepositoriesModule.java" checks="LineLength" />
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.elasticsearch.plugins;
|
|||
|
||||
import joptsimple.OptionSet;
|
||||
import joptsimple.OptionSpec;
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
import org.elasticsearch.Build;
|
||||
import org.elasticsearch.Version;
|
||||
|
@ -56,6 +55,7 @@ import java.util.HashSet;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
@ -183,11 +183,18 @@ class InstallPluginCommand extends Command {
|
|||
final String version = Version.CURRENT.toString();
|
||||
final String url;
|
||||
if (System.getProperty(PROPERTY_SUPPORT_STAGING_URLS, "false").equals("true")) {
|
||||
url = String.format(Locale.ROOT, "https://download.elastic.co/elasticsearch/staging/%1$s-%2$s/org/elasticsearch/plugin/%3$s/%1$s/%3$s-%1$s.zip",
|
||||
version, Build.CURRENT.shortHash(), pluginId);
|
||||
url = String.format(
|
||||
Locale.ROOT,
|
||||
"https://download.elastic.co/elasticsearch/staging/%1$s-%2$s/org/elasticsearch/plugin/%3$s/%1$s/%3$s-%1$s.zip",
|
||||
version,
|
||||
Build.CURRENT.shortHash(),
|
||||
pluginId);
|
||||
} else {
|
||||
url = String.format(Locale.ROOT, "https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/%1$s/%2$s/%1$s-%2$s.zip",
|
||||
pluginId, version);
|
||||
url = String.format(
|
||||
Locale.ROOT,
|
||||
"https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/%1$s/%2$s/%1$s-%2$s.zip",
|
||||
pluginId,
|
||||
version);
|
||||
}
|
||||
terminal.println("-> Downloading " + pluginId + " from elastic");
|
||||
return downloadZipAndChecksum(url, tmpDir);
|
||||
|
@ -243,21 +250,8 @@ class InstallPluginCommand extends Command {
|
|||
|
||||
private Path unzip(Path zip, Path pluginsDir) throws IOException, UserError {
|
||||
// unzip plugin to a staging temp dir
|
||||
final Path target;
|
||||
if (Constants.WINDOWS) {
|
||||
target = Files.createTempDirectory(pluginsDir, ".installing-");
|
||||
} else {
|
||||
Set<PosixFilePermission> perms = new HashSet<>();
|
||||
perms.add(PosixFilePermission.OWNER_EXECUTE);
|
||||
perms.add(PosixFilePermission.OWNER_READ);
|
||||
perms.add(PosixFilePermission.OWNER_WRITE);
|
||||
perms.add(PosixFilePermission.GROUP_READ);
|
||||
perms.add(PosixFilePermission.GROUP_EXECUTE);
|
||||
perms.add(PosixFilePermission.OTHERS_READ);
|
||||
perms.add(PosixFilePermission.OTHERS_EXECUTE);
|
||||
target = Files.createTempDirectory(pluginsDir, ".installing-", PosixFilePermissions.asFileAttribute(perms));
|
||||
}
|
||||
Files.createDirectories(target);
|
||||
|
||||
final Path target = stagingDirectory(pluginsDir);
|
||||
|
||||
boolean hasEsDir = false;
|
||||
// TODO: we should wrap this in a try/catch and try deleting the target dir on failure?
|
||||
|
@ -302,6 +296,39 @@ class InstallPluginCommand extends Command {
|
|||
return target;
|
||||
}
|
||||
|
||||
private Path stagingDirectory(Path pluginsDir) throws IOException {
|
||||
try {
|
||||
Set<PosixFilePermission> perms = new HashSet<>();
|
||||
perms.add(PosixFilePermission.OWNER_EXECUTE);
|
||||
perms.add(PosixFilePermission.OWNER_READ);
|
||||
perms.add(PosixFilePermission.OWNER_WRITE);
|
||||
perms.add(PosixFilePermission.GROUP_READ);
|
||||
perms.add(PosixFilePermission.GROUP_EXECUTE);
|
||||
perms.add(PosixFilePermission.OTHERS_READ);
|
||||
perms.add(PosixFilePermission.OTHERS_EXECUTE);
|
||||
return Files.createTempDirectory(pluginsDir, ".installing-", PosixFilePermissions.asFileAttribute(perms));
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Jimfs throws an IAE where it should throw an UOE
|
||||
// remove when google/jimfs#30 is integrated into Jimfs
|
||||
// and the Jimfs test dependency is upgraded to include
|
||||
// this pull request
|
||||
final StackTraceElement[] elements = e.getStackTrace();
|
||||
if (elements.length >= 1 &&
|
||||
elements[0].getClassName().equals("com.google.common.jimfs.AttributeService") &&
|
||||
elements[0].getMethodName().equals("setAttributeInternal")) {
|
||||
return stagingDirectoryWithoutPosixPermissions(pluginsDir);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
} catch (UnsupportedOperationException e) {
|
||||
return stagingDirectoryWithoutPosixPermissions(pluginsDir);
|
||||
}
|
||||
}
|
||||
|
||||
private Path stagingDirectoryWithoutPosixPermissions(Path pluginsDir) throws IOException {
|
||||
return Files.createTempDirectory(pluginsDir, ".installing-");
|
||||
}
|
||||
|
||||
/** Load information about the plugin, and verify it can be installed with no errors. */
|
||||
private PluginInfo verify(Terminal terminal, Path pluginRoot, boolean isBatch) throws Exception {
|
||||
// read and validate the plugin descriptor
|
||||
|
@ -328,7 +355,7 @@ class InstallPluginCommand extends Command {
|
|||
}
|
||||
|
||||
/** check a candidate plugin for jar hell before installing it */
|
||||
private void jarHellCheck(Path candidate, Path pluginsDir, boolean isolated) throws Exception {
|
||||
void jarHellCheck(Path candidate, Path pluginsDir, boolean isolated) throws Exception {
|
||||
// create list of current jars in classpath
|
||||
final List<URL> jars = new ArrayList<>();
|
||||
jars.addAll(Arrays.asList(JarHell.parseClassPath()));
|
||||
|
@ -367,7 +394,10 @@ class InstallPluginCommand extends Command {
|
|||
|
||||
final Path destination = env.pluginsFile().resolve(info.getName());
|
||||
if (Files.exists(destination)) {
|
||||
throw new UserError(ExitCodes.USAGE, "plugin directory " + destination.toAbsolutePath() + " already exists. To update the plugin, uninstall it first using 'remove " + info.getName() + "' command");
|
||||
throw new UserError(
|
||||
ExitCodes.USAGE,
|
||||
"plugin directory " + destination.toAbsolutePath() +
|
||||
" already exists. To update the plugin, uninstall it first using 'remove " + info.getName() + "' command");
|
||||
}
|
||||
|
||||
Path tmpBinDir = tmpRoot.resolve("bin");
|
||||
|
@ -404,30 +434,30 @@ class InstallPluginCommand extends Command {
|
|||
}
|
||||
Files.createDirectory(destBinDir);
|
||||
|
||||
Set<PosixFilePermission> perms = new HashSet<>();
|
||||
if (Constants.WINDOWS == false) {
|
||||
// setup file attributes for the installed files to those of the parent dir
|
||||
PosixFileAttributeView binAttrs = Files.getFileAttributeView(destBinDir.getParent(), PosixFileAttributeView.class);
|
||||
if (binAttrs != null) {
|
||||
perms = new HashSet<>(binAttrs.readAttributes().permissions());
|
||||
// setting execute bits, since this just means "the file is executable", and actual execution requires read
|
||||
perms.add(PosixFilePermission.OWNER_EXECUTE);
|
||||
perms.add(PosixFilePermission.GROUP_EXECUTE);
|
||||
perms.add(PosixFilePermission.OTHERS_EXECUTE);
|
||||
}
|
||||
// setup file attributes for the installed files to those of the parent dir
|
||||
final Set<PosixFilePermission> perms = new HashSet<>();
|
||||
final PosixFileAttributeView binAttributeView = Files.getFileAttributeView(destBinDir.getParent(), PosixFileAttributeView.class);
|
||||
if (binAttributeView != null) {
|
||||
perms.addAll(binAttributeView.readAttributes().permissions());
|
||||
// setting execute bits, since this just means "the file is executable", and actual execution requires read
|
||||
perms.add(PosixFilePermission.OWNER_EXECUTE);
|
||||
perms.add(PosixFilePermission.GROUP_EXECUTE);
|
||||
perms.add(PosixFilePermission.OTHERS_EXECUTE);
|
||||
}
|
||||
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(tmpBinDir)) {
|
||||
for (Path srcFile : stream) {
|
||||
if (Files.isDirectory(srcFile)) {
|
||||
throw new UserError(ExitCodes.DATA_ERROR, "Directories not allowed in bin dir for plugin " + info.getName() + ", found " + srcFile.getFileName());
|
||||
throw new UserError(
|
||||
ExitCodes.DATA_ERROR,
|
||||
"Directories not allowed in bin dir for plugin " + info.getName() + ", found " + srcFile.getFileName());
|
||||
}
|
||||
|
||||
Path destFile = destBinDir.resolve(tmpBinDir.relativize(srcFile));
|
||||
Files.copy(srcFile, destFile);
|
||||
|
||||
if (perms.isEmpty() == false) {
|
||||
PosixFileAttributeView view = Files.getFileAttributeView(destFile, PosixFileAttributeView.class);
|
||||
final PosixFileAttributeView view = Files.getFileAttributeView(destFile, PosixFileAttributeView.class);
|
||||
if (view != null) {
|
||||
view.setPermissions(perms);
|
||||
}
|
||||
}
|
||||
|
@ -446,15 +476,12 @@ class InstallPluginCommand extends Command {
|
|||
|
||||
// create the plugin's config dir "if necessary"
|
||||
Files.createDirectories(destConfigDir);
|
||||
|
||||
final PosixFileAttributes destConfigDirAttributes;
|
||||
if (Constants.WINDOWS) {
|
||||
destConfigDirAttributes = null;
|
||||
} else {
|
||||
destConfigDirAttributes =
|
||||
Files.getFileAttributeView(destConfigDir.getParent(), PosixFileAttributeView.class).readAttributes();
|
||||
final PosixFileAttributeView destConfigDirAttributesView =
|
||||
Files.getFileAttributeView(destConfigDir.getParent(), PosixFileAttributeView.class);
|
||||
final PosixFileAttributes destConfigDirAttributes =
|
||||
destConfigDirAttributesView != null ? destConfigDirAttributesView.readAttributes() : null;
|
||||
if (destConfigDirAttributes != null) {
|
||||
setOwnerGroup(destConfigDir, destConfigDirAttributes);
|
||||
|
||||
}
|
||||
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(tmpConfigDir)) {
|
||||
|
@ -466,7 +493,7 @@ class InstallPluginCommand extends Command {
|
|||
Path destFile = destConfigDir.resolve(tmpConfigDir.relativize(srcFile));
|
||||
if (Files.exists(destFile) == false) {
|
||||
Files.copy(srcFile, destFile);
|
||||
if (Constants.WINDOWS == false) {
|
||||
if (destConfigDirAttributes != null) {
|
||||
setOwnerGroup(destFile, destConfigDirAttributes);
|
||||
}
|
||||
}
|
||||
|
@ -475,8 +502,10 @@ class InstallPluginCommand extends Command {
|
|||
IOUtils.rm(tmpConfigDir); // clean up what we just copied
|
||||
}
|
||||
|
||||
private static void setOwnerGroup(Path path, PosixFileAttributes attributes) throws IOException {
|
||||
private static void setOwnerGroup(final Path path, final PosixFileAttributes attributes) throws IOException {
|
||||
Objects.requireNonNull(attributes);
|
||||
PosixFileAttributeView fileAttributeView = Files.getFileAttributeView(path, PosixFileAttributeView.class);
|
||||
assert fileAttributeView != null;
|
||||
fileAttributeView.setOwner(attributes.owner());
|
||||
fileAttributeView.setGroup(attributes.group());
|
||||
}
|
||||
|
|
|
@ -19,6 +19,22 @@
|
|||
|
||||
package org.elasticsearch.plugins;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import com.google.common.jimfs.Configuration;
|
||||
import com.google.common.jimfs.Jimfs;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.SuppressForbidden;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cli.MockTerminal;
|
||||
import org.elasticsearch.cli.UserError;
|
||||
import org.elasticsearch.common.io.PathUtils;
|
||||
import org.elasticsearch.common.io.PathUtilsForTesting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.PosixPermissionsResetter;
|
||||
import org.junit.After;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -26,6 +42,7 @@ import java.net.URL;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
|
@ -36,46 +53,100 @@ import java.nio.file.attribute.BasicFileAttributes;
|
|||
import java.nio.file.attribute.PosixFileAttributeView;
|
||||
import java.nio.file.attribute.PosixFileAttributes;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cli.MockTerminal;
|
||||
import org.elasticsearch.cli.UserError;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.PosixPermissionsResetter;
|
||||
import org.junit.BeforeClass;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
|
||||
@LuceneTestCase.SuppressFileSystems("*")
|
||||
public class InstallPluginCommandTests extends ESTestCase {
|
||||
|
||||
private static boolean isPosix;
|
||||
private final Function<String, Path> temp;
|
||||
|
||||
@BeforeClass
|
||||
public static void checkPosix() throws IOException {
|
||||
isPosix = Files.getFileAttributeView(createTempFile(), PosixFileAttributeView.class) != null;
|
||||
private final FileSystem fs;
|
||||
private final boolean isPosix;
|
||||
private final boolean isReal;
|
||||
private final String javaIoTmpdir;
|
||||
|
||||
@SuppressForbidden(reason = "sets java.io.tmpdir")
|
||||
public InstallPluginCommandTests(FileSystem fs, Function<String, Path> temp) {
|
||||
this.fs = fs;
|
||||
this.temp = temp;
|
||||
this.isPosix = fs.supportedFileAttributeViews().contains("posix");
|
||||
this.isReal = fs == PathUtils.getDefaultFileSystem();
|
||||
PathUtilsForTesting.installMock(fs);
|
||||
javaIoTmpdir = System.getProperty("java.io.tmpdir");
|
||||
System.setProperty("java.io.tmpdir", temp.apply("tmpdir").toString());
|
||||
}
|
||||
|
||||
@After
|
||||
@SuppressForbidden(reason = "resets java.io.tmpdir")
|
||||
public void tearDown() throws Exception {
|
||||
System.setProperty("java.io.tmpdir", javaIoTmpdir);
|
||||
PathUtilsForTesting.teardown();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() {
|
||||
class Parameter {
|
||||
private final FileSystem fileSystem;
|
||||
private final Function<String, Path> temp;
|
||||
|
||||
public Parameter(FileSystem fileSystem, String root) {
|
||||
this(fileSystem, s -> {
|
||||
try {
|
||||
return Files.createTempDirectory(fileSystem.getPath(root), s);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Parameter(FileSystem fileSystem, Function<String, Path> temp) {
|
||||
this.fileSystem = fileSystem;
|
||||
this.temp = temp;
|
||||
}
|
||||
}
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(new Parameter(Jimfs.newFileSystem(Configuration.windows()), "c:\\"));
|
||||
parameters.add(new Parameter(Jimfs.newFileSystem(toPosix(Configuration.osX())), "/"));
|
||||
parameters.add(new Parameter(Jimfs.newFileSystem(toPosix(Configuration.unix())), "/"));
|
||||
parameters.add(new Parameter(PathUtils.getDefaultFileSystem(), LuceneTestCase::createTempDir ));
|
||||
return parameters.stream().map(p -> new Object[] { p.fileSystem, p.temp }).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Configuration toPosix(Configuration configuration) {
|
||||
return configuration.toBuilder().setAttributeViews("basic", "owner", "posix", "unix").build();
|
||||
}
|
||||
|
||||
/** Creates a test environment with bin, config and plugins directories. */
|
||||
static Environment createEnv() throws IOException {
|
||||
Path home = createTempDir();
|
||||
static Environment createEnv(FileSystem fs, Function<String, Path> temp) throws IOException {
|
||||
Path home = temp.apply("install-plugin-command-tests");
|
||||
Files.createDirectories(home.resolve("bin"));
|
||||
Files.createFile(home.resolve("bin").resolve("elasticsearch"));
|
||||
Files.createDirectories(home.resolve("config"));
|
||||
Files.createFile(home.resolve("config").resolve("elasticsearch.yml"));
|
||||
Files.createDirectories(home.resolve("plugins"));
|
||||
Path plugins = Files.createDirectories(home.resolve("plugins"));
|
||||
assertTrue(Files.exists(plugins));
|
||||
Settings settings = Settings.builder()
|
||||
.put("path.home", home)
|
||||
.build();
|
||||
return new Environment(settings);
|
||||
}
|
||||
|
||||
static Path createPluginDir(Function<String, Path> temp) throws IOException {
|
||||
return temp.apply("pluginDir");
|
||||
}
|
||||
|
||||
/** creates a fake jar file with empty class files */
|
||||
static void writeJar(Path jar, String... classes) throws IOException {
|
||||
try (ZipOutputStream stream = new ZipOutputStream(Files.newOutputStream(jar))) {
|
||||
|
@ -115,14 +186,40 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
static MockTerminal installPlugin(String pluginUrl, Environment env) throws Exception {
|
||||
return installPlugin(pluginUrl, env, false);
|
||||
}
|
||||
|
||||
static MockTerminal installPlugin(String pluginUrl, Environment env, boolean jarHellCheck) throws Exception {
|
||||
MockTerminal terminal = new MockTerminal();
|
||||
new InstallPluginCommand(env).execute(terminal, pluginUrl, true);
|
||||
new InstallPluginCommand(env) {
|
||||
@Override
|
||||
void jarHellCheck(Path candidate, Path pluginsDir, boolean isolated) throws Exception {
|
||||
if (jarHellCheck) {
|
||||
super.jarHellCheck(candidate, pluginsDir, isolated);
|
||||
}
|
||||
}
|
||||
}.execute(terminal, pluginUrl, true);
|
||||
return terminal;
|
||||
}
|
||||
|
||||
void assertPlugin(String name, Path original, Environment env) throws IOException {
|
||||
Path got = env.pluginsFile().resolve(name);
|
||||
assertTrue("dir " + name + " exists", Files.exists(got));
|
||||
|
||||
if (isPosix) {
|
||||
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(got);
|
||||
assertThat(
|
||||
perms,
|
||||
containsInAnyOrder(
|
||||
PosixFilePermission.OWNER_READ,
|
||||
PosixFilePermission.OWNER_WRITE,
|
||||
PosixFilePermission.OWNER_EXECUTE,
|
||||
PosixFilePermission.GROUP_READ,
|
||||
PosixFilePermission.GROUP_EXECUTE,
|
||||
PosixFilePermission.OTHERS_READ,
|
||||
PosixFilePermission.OTHERS_EXECUTE));
|
||||
}
|
||||
|
||||
assertTrue("jar was copied", Files.exists(got.resolve("plugin.jar")));
|
||||
assertFalse("bin was not copied", Files.exists(got.resolve("bin")));
|
||||
assertFalse("config was not copied", Files.exists(got.resolve("config")));
|
||||
|
@ -152,6 +249,16 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
Path configDir = env.configFile().resolve(name);
|
||||
assertTrue("config dir exists", Files.exists(configDir));
|
||||
assertTrue("config is a dir", Files.isDirectory(configDir));
|
||||
|
||||
if (isPosix) {
|
||||
Path configRoot = env.configFile();
|
||||
PosixFileAttributes configAttributes =
|
||||
Files.getFileAttributeView(configRoot, PosixFileAttributeView.class).readAttributes();
|
||||
PosixFileAttributes attributes = Files.getFileAttributeView(configDir, PosixFileAttributeView.class).readAttributes();
|
||||
assertThat(attributes.owner(), equalTo(configAttributes.owner()));
|
||||
assertThat(attributes.group(), equalTo(configAttributes.group()));
|
||||
}
|
||||
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(configDir)) {
|
||||
for (Path file : stream) {
|
||||
assertFalse("not a dir", Files.isDirectory(file));
|
||||
|
@ -172,16 +279,16 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testSomethingWorks() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
String pluginZip = createPlugin("fake", pluginDir);
|
||||
installPlugin(pluginZip, env);
|
||||
assertPlugin("fake", pluginDir, env);
|
||||
}
|
||||
|
||||
public void testSpaceInUrl() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
String pluginZip = createPlugin("fake", pluginDir);
|
||||
Path pluginZipWithSpaces = createTempFile("foo bar", ".zip");
|
||||
try (InputStream in = new URL(pluginZip).openStream()) {
|
||||
|
@ -192,28 +299,30 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testMalformedUrlNotMaven() throws Exception {
|
||||
Environment env = createEnv(fs, temp);
|
||||
// has two colons, so it appears similar to maven coordinates
|
||||
MalformedURLException e = expectThrows(MalformedURLException.class, () -> {
|
||||
installPlugin("://host:1234", createEnv());
|
||||
installPlugin("://host:1234", env);
|
||||
});
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("no protocol"));
|
||||
}
|
||||
|
||||
public void testPluginsDirMissing() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Files.delete(env.pluginsFile());
|
||||
Path pluginDir = createTempDir();
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
String pluginZip = createPlugin("fake", pluginDir);
|
||||
installPlugin(pluginZip, env);
|
||||
assertPlugin("fake", pluginDir, env);
|
||||
}
|
||||
|
||||
public void testPluginsDirReadOnly() throws Exception {
|
||||
assumeTrue("posix filesystem", isPosix);
|
||||
Environment env = createEnv();
|
||||
assumeTrue("posix and filesystem", isPosix && isReal);
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
try (PosixPermissionsResetter pluginsAttrs = new PosixPermissionsResetter(env.pluginsFile())) {
|
||||
pluginsAttrs.setPermissions(new HashSet<>());
|
||||
String pluginZip = createPlugin("fake", createTempDir());
|
||||
String pluginZip = createPlugin("fake", pluginDir);
|
||||
IOException e = expectThrows(IOException.class, () -> {
|
||||
installPlugin(pluginZip, env);
|
||||
});
|
||||
|
@ -223,8 +332,9 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testBuiltinModule() throws Exception {
|
||||
Environment env = createEnv();
|
||||
String pluginZip = createPlugin("lang-groovy", createTempDir());
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
String pluginZip = createPlugin("lang-groovy", pluginDir);
|
||||
UserError e = expectThrows(UserError.class, () -> {
|
||||
installPlugin(pluginZip, env);
|
||||
});
|
||||
|
@ -233,24 +343,26 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testJarHell() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
writeJar(pluginDir.resolve("other.jar"), "FakePlugin");
|
||||
String pluginZip = createPlugin("fake", pluginDir); // adds plugin.jar with FakePlugin
|
||||
// jar hell test needs a real filesystem
|
||||
assumeTrue("real filesystem", isReal);
|
||||
Environment environment = createEnv(fs, temp);
|
||||
Path pluginDirectory = createPluginDir(temp);
|
||||
writeJar(pluginDirectory.resolve("other.jar"), "FakePlugin");
|
||||
String pluginZip = createPlugin("fake", pluginDirectory); // adds plugin.jar with FakePlugin
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () -> {
|
||||
installPlugin(pluginZip, env);
|
||||
installPlugin(pluginZip, environment, true);
|
||||
});
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("jar hell"));
|
||||
assertInstallCleaned(env);
|
||||
assertInstallCleaned(environment);
|
||||
}
|
||||
|
||||
public void testIsolatedPlugins() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Environment env = createEnv(fs, temp);
|
||||
// these both share the same FakePlugin class
|
||||
Path pluginDir1 = createTempDir();
|
||||
Path pluginDir1 = createPluginDir(temp);
|
||||
String pluginZip1 = createPlugin("fake1", pluginDir1);
|
||||
installPlugin(pluginZip1, env);
|
||||
Path pluginDir2 = createTempDir();
|
||||
Path pluginDir2 = createPluginDir(temp);
|
||||
String pluginZip2 = createPlugin("fake2", pluginDir2);
|
||||
installPlugin(pluginZip2, env);
|
||||
assertPlugin("fake1", pluginDir1, env);
|
||||
|
@ -258,8 +370,9 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testPurgatoryJarHell() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir1 = createTempDir();
|
||||
assumeTrue("real filesystem", isReal);
|
||||
Environment environment = createEnv(fs, temp);
|
||||
Path pluginDir1 = createPluginDir(temp);
|
||||
PluginTestUtil.writeProperties(pluginDir1,
|
||||
"description", "fake desc",
|
||||
"name", "fake1",
|
||||
|
@ -270,9 +383,9 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
"isolated", "false");
|
||||
writeJar(pluginDir1.resolve("plugin.jar"), "FakePlugin");
|
||||
String pluginZip1 = writeZip(pluginDir1, "elasticsearch");
|
||||
installPlugin(pluginZip1, env);
|
||||
installPlugin(pluginZip1, environment);
|
||||
|
||||
Path pluginDir2 = createTempDir();
|
||||
Path pluginDir2 = createPluginDir(temp);
|
||||
PluginTestUtil.writeProperties(pluginDir2,
|
||||
"description", "fake desc",
|
||||
"name", "fake2",
|
||||
|
@ -284,15 +397,16 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
writeJar(pluginDir2.resolve("plugin.jar"), "FakePlugin");
|
||||
String pluginZip2 = writeZip(pluginDir2, "elasticsearch");
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () -> {
|
||||
installPlugin(pluginZip2, env);
|
||||
installPlugin(pluginZip2, environment, true);
|
||||
});
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("jar hell"));
|
||||
assertInstallCleaned(env);
|
||||
assertInstallCleaned(environment);
|
||||
}
|
||||
|
||||
public void testExistingPlugin() throws Exception {
|
||||
Environment env = createEnv();
|
||||
String pluginZip = createPlugin("fake", createTempDir());
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
String pluginZip = createPlugin("fake", pluginDir);
|
||||
installPlugin(pluginZip, env);
|
||||
UserError e = expectThrows(UserError.class, () -> {
|
||||
installPlugin(pluginZip, env);
|
||||
|
@ -302,8 +416,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testBin() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path binDir = pluginDir.resolve("bin");
|
||||
Files.createDirectory(binDir);
|
||||
Files.createFile(binDir.resolve("somescript"));
|
||||
|
@ -313,8 +427,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testBinNotDir() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path binDir = pluginDir.resolve("bin");
|
||||
Files.createFile(binDir);
|
||||
String pluginZip = createPlugin("fake", pluginDir);
|
||||
|
@ -326,8 +440,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testBinContainsDir() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path dirInBinDir = pluginDir.resolve("bin").resolve("foo");
|
||||
Files.createDirectories(dirInBinDir);
|
||||
Files.createFile(dirInBinDir.resolve("somescript"));
|
||||
|
@ -340,8 +454,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testBinConflict() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path binDir = pluginDir.resolve("bin");
|
||||
Files.createDirectory(binDir);
|
||||
Files.createFile(binDir.resolve("somescript"));
|
||||
|
@ -355,8 +469,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
|
||||
public void testBinPermissions() throws Exception {
|
||||
assumeTrue("posix filesystem", isPosix);
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path binDir = pluginDir.resolve("bin");
|
||||
Files.createDirectory(binDir);
|
||||
Files.createFile(binDir.resolve("somescript"));
|
||||
|
@ -372,8 +486,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testConfig() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path configDir = pluginDir.resolve("config");
|
||||
Files.createDirectory(configDir);
|
||||
Files.createFile(configDir.resolve("custom.yaml"));
|
||||
|
@ -383,11 +497,11 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testExistingConfig() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path envConfigDir = env.configFile().resolve("fake");
|
||||
Files.createDirectories(envConfigDir);
|
||||
Files.write(envConfigDir.resolve("custom.yaml"), "existing config".getBytes(StandardCharsets.UTF_8));
|
||||
Path pluginDir = createTempDir();
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path configDir = pluginDir.resolve("config");
|
||||
Files.createDirectory(configDir);
|
||||
Files.write(configDir.resolve("custom.yaml"), "new config".getBytes(StandardCharsets.UTF_8));
|
||||
|
@ -402,8 +516,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testConfigNotDir() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path configDir = pluginDir.resolve("config");
|
||||
Files.createFile(configDir);
|
||||
String pluginZip = createPlugin("fake", pluginDir);
|
||||
|
@ -415,8 +529,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testConfigContainsDir() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path dirInConfigDir = pluginDir.resolve("config").resolve("foo");
|
||||
Files.createDirectories(dirInConfigDir);
|
||||
Files.createFile(dirInConfigDir.resolve("myconfig.yml"));
|
||||
|
@ -429,8 +543,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testConfigConflict() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Path configDir = pluginDir.resolve("config");
|
||||
Files.createDirectory(configDir);
|
||||
Files.createFile(configDir.resolve("myconfig.yml"));
|
||||
|
@ -443,8 +557,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testMissingDescriptor() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Files.createFile(pluginDir.resolve("fake.yml"));
|
||||
String pluginZip = writeZip(pluginDir, "elasticsearch");
|
||||
NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> {
|
||||
|
@ -455,8 +569,8 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testMissingDirectory() throws Exception {
|
||||
Environment env = createEnv();
|
||||
Path pluginDir = createTempDir();
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path pluginDir = createPluginDir(temp);
|
||||
Files.createFile(pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES));
|
||||
String pluginZip = writeZip(pluginDir, null);
|
||||
UserError e = expectThrows(UserError.class, () -> {
|
||||
|
@ -467,13 +581,14 @@ public class InstallPluginCommandTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testZipRelativeOutsideEntryName() throws Exception {
|
||||
Environment env = createEnv(fs, temp);
|
||||
Path zip = createTempDir().resolve("broken.zip");
|
||||
try (ZipOutputStream stream = new ZipOutputStream(Files.newOutputStream(zip))) {
|
||||
stream.putNextEntry(new ZipEntry("elasticsearch/../blah"));
|
||||
}
|
||||
String pluginZip = zip.toUri().toURL().toString();
|
||||
IOException e = expectThrows(IOException.class, () -> {
|
||||
installPlugin(pluginZip, createEnv());
|
||||
installPlugin(pluginZip, env);
|
||||
});
|
||||
assertTrue(e.getMessage(), e.getMessage().contains("resolving outside of plugin directory"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue