Skip to content

Commit

Permalink
Plugins: Remove intermediate "elasticsearch" directory within plugin …
Browse files Browse the repository at this point in the history
…zips (#28589)

This commit removes the extra layer of all plugin files existing under
"elasticsearch" within plugin zips. This simplifies building plugin zips
and removes the need for special logic of modules vs plugins.
  • Loading branch information
rjernst authored Feb 12, 2018
1 parent 4e0c146 commit 65f1dd4
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@ class MetaPluginBuildPlugin implements Plugin<Project> {

// create the actual bundle task, which zips up all the files for the plugin
Zip bundle = project.tasks.create(name: 'bundlePlugin', type: Zip, dependsOn: [buildProperties]) {
into('elasticsearch') {
from(buildProperties.descriptorOutput.parentFile) {
// plugin properties file
include(buildProperties.descriptorOutput.name)
}
from(buildProperties.descriptorOutput.parentFile) {
// plugin properties file
include(buildProperties.descriptorOutput.name)
}
// due to how the renames work for each bundled plugin, we must exclude empty dirs or every subdir
// within bundled plugin zips will show up at the root as an empty dir
Expand All @@ -85,10 +83,8 @@ class MetaPluginBuildPlugin implements Plugin<Project> {
dependsOn bundledPluginProject.bundlePlugin
from(project.zipTree(bundledPluginProject.bundlePlugin.outputs.files.singleFile)) {
eachFile { FileCopyDetails details ->
// paths in the individual plugins begin with elasticsearch, and we want to add in the
// bundled plugin name between that and each filename
details.relativePath = new RelativePath(true, 'elasticsearch', bundledPluginProjectName,
details.relativePath.toString().replace('elasticsearch/', ''))
// we want each path to have the plugin name interjected
details.relativePath = new RelativePath(true, bundledPluginProjectName, details.relativePath.toString())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,6 @@ public class PluginBuildPlugin extends BuildPlugin {
include 'config/**'
include 'bin/**'
}
if (project.path.startsWith(':modules:') == false) {
into('elasticsearch')
}
}
project.assemble.dependsOn(bundle)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,17 +462,15 @@ private Path unzip(Path zip, Path pluginsDir) throws IOException, UserException
final Path target = stagingDirectory(pluginsDir);
pathsToDeleteOnShutdown.add(target);

boolean hasEsDir = false;
try (ZipInputStream zipInput = new ZipInputStream(Files.newInputStream(zip))) {
ZipEntry entry;
byte[] buffer = new byte[8192];
while ((entry = zipInput.getNextEntry()) != null) {
if (entry.getName().startsWith("elasticsearch/") == false) {
// only extract the elasticsearch directory
continue;
if (entry.getName().startsWith("elasticsearch/")) {
throw new UserException(PLUGIN_MALFORMED, "This plugin was built with an older plugin structure." +
" Contact the plugin author to remove the intermediate \"elasticsearch\" directory within the plugin zip.");
}
hasEsDir = true;
Path targetFile = target.resolve(entry.getName().substring("elasticsearch/".length()));
Path targetFile = target.resolve(entry.getName());

// Using the entry name as a path can result in an entry outside of the plugin dir,
// either if the name starts with the root of the filesystem, or it is a relative
Expand All @@ -499,13 +497,11 @@ private Path unzip(Path zip, Path pluginsDir) throws IOException, UserException
}
zipInput.closeEntry();
}
}
Files.delete(zip);
if (hasEsDir == false) {
} catch (UserException e) {
IOUtils.rm(target);
throw new UserException(PLUGIN_MALFORMED,
"`elasticsearch` directory is missing in the plugin zip");
throw e;
}
Files.delete(zip);
return target;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,12 @@ static void writePluginSecurityPolicy(Path pluginDir, String... permissions) thr

static Path createPlugin(String name, Path structure, String... additionalProps) throws IOException {
writePlugin(name, structure, additionalProps);
return writeZip(structure, "elasticsearch");
return writeZip(structure, null);
}

static Path createMetaPlugin(String name, Path structure) throws IOException {
writeMetaPlugin(name, structure);
return writeZip(structure, "elasticsearch");
return writeZip(structure, null);
}

void installPlugin(String pluginUrl, Path home) throws Exception {
Expand Down Expand Up @@ -811,7 +811,7 @@ public void testMissingDescriptor() throws Exception {
Path pluginDir = metaDir.resolve("fake");
Files.createDirectory(pluginDir);
Files.createFile(pluginDir.resolve("fake.yml"));
String pluginZip = writeZip(pluginDir, "elasticsearch").toUri().toURL().toString();
String pluginZip = writeZip(pluginDir, null).toUri().toURL().toString();
NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> installPlugin(pluginZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("plugin-descriptor.properties"));
assertInstallCleaned(env.v2());
Expand All @@ -822,35 +822,36 @@ public void testMissingDescriptor() throws Exception {
assertInstallCleaned(env.v2());
}

public void testMissingDirectory() throws Exception {
public void testContainsIntermediateDirectory() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp);
Files.createFile(pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES));
String pluginZip = writeZip(pluginDir, null).toUri().toURL().toString();
String pluginZip = writeZip(pluginDir, "elasticsearch").toUri().toURL().toString();
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("`elasticsearch` directory is missing in the plugin zip"));
assertThat(e.getMessage(), containsString("This plugin was built with an older plugin structure"));
assertInstallCleaned(env.v2());
}

public void testMissingDirectoryMeta() throws Exception {
public void testContainsIntermediateDirectoryMeta() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp);
Files.createFile(pluginDir.resolve(MetaPluginInfo.ES_META_PLUGIN_PROPERTIES));
String pluginZip = writeZip(pluginDir, null).toUri().toURL().toString();
String pluginZip = writeZip(pluginDir, "elasticsearch").toUri().toURL().toString();
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("`elasticsearch` directory is missing in the plugin zip"));
assertThat(e.getMessage(), containsString("This plugin was built with an older plugin structure"));
assertInstallCleaned(env.v2());
}

public void testZipRelativeOutsideEntryName() throws Exception {
Tuple<Path, 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"));
stream.putNextEntry(new ZipEntry("../blah"));
}
String pluginZip = zip.toUri().toURL().toString();
UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1()));
assertTrue(e.getMessage(), e.getMessage().contains("resolving outside of plugin directory"));
assertInstallCleaned(env.v2());
}

public void testOfficialPluginsHelpSorted() throws Exception {
Expand Down

0 comments on commit 65f1dd4

Please sign in to comment.