Format projects under :distribution:tools (#51292)

Backport of #51226. Opt-in the sub-projects of :distribution:tools for
automatic formatting.
This commit is contained in:
Rory Hunter 2020-01-22 11:19:17 +00:00 committed by GitHub
parent 421aa14972
commit 1009f92b03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 834 additions and 602 deletions

View File

@ -107,6 +107,9 @@ subprojects {
// switched to an exclude list, and eventualy removed completely. // switched to an exclude list, and eventualy removed completely.
def projectPathsToFormat = [ def projectPathsToFormat = [
':build-tools', ':build-tools',
':distribution:tools:java-version-checker',
':distribution:tools:launchers',
':distribution:tools:plugin-cli',
':x-pack:plugin:autoscaling', ':x-pack:plugin:autoscaling',
':x-pack:plugin:enrich' ':x-pack:plugin:enrich'
] ]

View File

@ -27,8 +27,7 @@ import java.util.Locale;
*/ */
final class JavaVersionChecker { final class JavaVersionChecker {
private JavaVersionChecker() { private JavaVersionChecker() {}
}
/** /**
* The main entry point. The exit code is 0 if the Java version is at least 1.8, otherwise the exit code is 1. * The main entry point. The exit code is 0 if the Java version is at least 1.8, otherwise the exit code is 1.
@ -42,17 +41,19 @@ final class JavaVersionChecker {
} }
if (JavaVersion.compare(JavaVersion.CURRENT, JavaVersion.JAVA_8) < 0) { if (JavaVersion.compare(JavaVersion.CURRENT, JavaVersion.JAVA_8) < 0) {
final String message = String.format( final String message = String.format(
Locale.ROOT, Locale.ROOT,
"the minimum required Java version is 8; your Java version from [%s] does not meet this requirement", "the minimum required Java version is 8; your Java version from [%s] does not meet this requirement",
System.getProperty("java.home")); System.getProperty("java.home")
);
errPrintln(message); errPrintln(message);
exit(1); exit(1);
} }
if (JavaVersion.compare(JavaVersion.CURRENT, JavaVersion.JAVA_11) < 0) { if (JavaVersion.compare(JavaVersion.CURRENT, JavaVersion.JAVA_11) < 0) {
final String message = String.format( final String message = String.format(
Locale.ROOT, Locale.ROOT,
"future versions of Elasticsearch will require Java 11; your Java version from [%s] does not meet this requirement", "future versions of Elasticsearch will require Java 11; your Java version from [%s] does not meet this requirement",
System.getProperty("java.home")); System.getProperty("java.home")
);
errPrintln(message); errPrintln(message);
} }
exit(0); exit(0);

View File

@ -78,14 +78,18 @@ final class JvmErgonomics {
return ergonomicChoices; return ergonomicChoices;
} }
private static final Pattern OPTION = private static final Pattern OPTION = Pattern.compile(
Pattern.compile("^\\s*\\S+\\s+(?<flag>\\S+)\\s+:?=\\s+(?<value>\\S+)?\\s+\\{[^}]+?\\}(\\s+\\{[^}]+})?"); "^\\s*\\S+\\s+(?<flag>\\S+)\\s+:?=\\s+(?<value>\\S+)?\\s+\\{[^}]+?\\}(\\s+\\{[^}]+})?"
);
static Map<String, Optional<String>> finalJvmOptions( static Map<String, Optional<String>> finalJvmOptions(final List<String> userDefinedJvmOptions) throws InterruptedException,
final List<String> userDefinedJvmOptions) throws InterruptedException, IOException { IOException {
return Collections.unmodifiableMap(flagsFinal(userDefinedJvmOptions).stream() return Collections.unmodifiableMap(
.map(OPTION::matcher).filter(Matcher::matches) flagsFinal(userDefinedJvmOptions).stream()
.collect(Collectors.toMap(m -> m.group("flag"), m -> Optional.ofNullable(m.group("value"))))); .map(OPTION::matcher)
.filter(Matcher::matches)
.collect(Collectors.toMap(m -> m.group("flag"), m -> Optional.ofNullable(m.group("value"))))
);
} }
private static List<String> flagsFinal(final List<String> userDefinedJvmOptions) throws InterruptedException, IOException { private static List<String> flagsFinal(final List<String> userDefinedJvmOptions) throws InterruptedException, IOException {
@ -98,23 +102,24 @@ final class JvmErgonomics {
* without having to implement our own JVM option parsing logic. * without having to implement our own JVM option parsing logic.
*/ */
final String java = Paths.get(System.getProperty("java.home"), "bin", "java").toString(); final String java = Paths.get(System.getProperty("java.home"), "bin", "java").toString();
final List<String> command = final List<String> command = Collections.unmodifiableList(
Collections.unmodifiableList( Stream.of(Stream.of(java), userDefinedJvmOptions.stream(), Stream.of("-XX:+PrintFlagsFinal"), Stream.of("-version"))
Stream.of(Stream.of(java), userDefinedJvmOptions.stream(), Stream.of("-XX:+PrintFlagsFinal"), Stream.of("-version")) .reduce(Stream::concat)
.reduce(Stream::concat) .get()
.get() .collect(Collectors.toList())
.collect(Collectors.toList())); );
final Process process = new ProcessBuilder().command(command).start(); final Process process = new ProcessBuilder().command(command).start();
final List<String> output = readLinesFromInputStream(process.getInputStream()); final List<String> output = readLinesFromInputStream(process.getInputStream());
final List<String> error = readLinesFromInputStream(process.getErrorStream()); final List<String> error = readLinesFromInputStream(process.getErrorStream());
final int status = process.waitFor(); final int status = process.waitFor();
if (status != 0) { if (status != 0) {
final String message = String.format( final String message = String.format(
Locale.ROOT, Locale.ROOT,
"starting java failed with [%d]\noutput:\n%s\nerror:\n%s", "starting java failed with [%d]\noutput:\n%s\nerror:\n%s",
status, status,
String.join("\n", output), String.join("\n", output),
String.join("\n", error)); String.join("\n", error)
);
throw new RuntimeException(message); throw new RuntimeException(message);
} else { } else {
return output; return output;
@ -122,8 +127,7 @@ final class JvmErgonomics {
} }
private static List<String> readLinesFromInputStream(final InputStream is) throws IOException { private static List<String> readLinesFromInputStream(final InputStream is) throws IOException {
try (InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8); try (InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8); BufferedReader br = new BufferedReader(isr)) {
BufferedReader br = new BufferedReader(isr)) {
return Collections.unmodifiableList(br.lines().collect(Collectors.toList())); return Collections.unmodifiableList(br.lines().collect(Collectors.toList()));
} }
} }

View File

@ -59,40 +59,41 @@ final class JvmOptionsParser {
} }
final List<String> jvmOptions = new ArrayList<>(); final List<String> jvmOptions = new ArrayList<>();
final SortedMap<Integer, String> invalidLines = new TreeMap<>(); final SortedMap<Integer, String> invalidLines = new TreeMap<>();
try (InputStream is = Files.newInputStream(Paths.get(args[0])); try (
Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8); InputStream is = Files.newInputStream(Paths.get(args[0]));
BufferedReader br = new BufferedReader(reader)) { Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
parse( BufferedReader br = new BufferedReader(reader)
JavaVersion.majorVersion(JavaVersion.CURRENT), ) {
br, parse(JavaVersion.majorVersion(JavaVersion.CURRENT), br, new JvmOptionConsumer() {
new JvmOptionConsumer() { @Override
@Override public void accept(final String jvmOption) {
public void accept(final String jvmOption) { jvmOptions.add(jvmOption);
jvmOptions.add(jvmOption); }
} }, new InvalidLineConsumer() {
}, @Override
new InvalidLineConsumer() { public void accept(final int lineNumber, final String line) {
@Override invalidLines.put(lineNumber, line);
public void accept(final int lineNumber, final String line) { }
invalidLines.put(lineNumber, line); });
}
});
} }
if (invalidLines.isEmpty()) { if (invalidLines.isEmpty()) {
// now append the JVM options from ES_JAVA_OPTS // now append the JVM options from ES_JAVA_OPTS
final String environmentJvmOptions = System.getenv("ES_JAVA_OPTS"); final String environmentJvmOptions = System.getenv("ES_JAVA_OPTS");
if (environmentJvmOptions != null) { if (environmentJvmOptions != null) {
jvmOptions.addAll(Arrays.stream(environmentJvmOptions.split("\\s+")) jvmOptions.addAll(
.filter(s -> s.trim().isEmpty() == false) Arrays.stream(environmentJvmOptions.split("\\s+")).filter(s -> s.trim().isEmpty() == false).collect(Collectors.toList())
.collect(Collectors.toList())); );
} }
final List<String> substitutedJvmOptions = final List<String> substitutedJvmOptions = substitutePlaceholders(
substitutePlaceholders(jvmOptions, Collections.singletonMap("ES_TMPDIR", System.getenv("ES_TMPDIR"))); jvmOptions,
Collections.singletonMap("ES_TMPDIR", System.getenv("ES_TMPDIR"))
);
final List<String> ergonomicJvmOptions = JvmErgonomics.choose(substitutedJvmOptions); final List<String> ergonomicJvmOptions = JvmErgonomics.choose(substitutedJvmOptions);
final List<String> systemJvmOptions = SystemJvmOptions.systemJvmOptions(); final List<String> systemJvmOptions = SystemJvmOptions.systemJvmOptions();
final List<String> finalJvmOptions = final List<String> finalJvmOptions = new ArrayList<>(
new ArrayList<>(systemJvmOptions.size() + substitutedJvmOptions.size() + ergonomicJvmOptions.size()); systemJvmOptions.size() + substitutedJvmOptions.size() + ergonomicJvmOptions.size()
);
finalJvmOptions.addAll(systemJvmOptions); // add the system JVM options first so that they can be overridden finalJvmOptions.addAll(systemJvmOptions); // add the system JVM options first so that they can be overridden
finalJvmOptions.addAll(substitutedJvmOptions); finalJvmOptions.addAll(substitutedJvmOptions);
finalJvmOptions.addAll(ergonomicJvmOptions); finalJvmOptions.addAll(ergonomicJvmOptions);
@ -101,21 +102,23 @@ final class JvmOptionsParser {
Launchers.exit(0); Launchers.exit(0);
} else { } else {
final String errorMessage = String.format( final String errorMessage = String.format(
Locale.ROOT, Locale.ROOT,
"encountered [%d] error%s parsing [%s]", "encountered [%d] error%s parsing [%s]",
invalidLines.size(), invalidLines.size(),
invalidLines.size() == 1 ? "" : "s", invalidLines.size() == 1 ? "" : "s",
args[0]); args[0]
);
Launchers.errPrintln(errorMessage); Launchers.errPrintln(errorMessage);
int count = 0; int count = 0;
for (final Map.Entry<Integer, String> entry : invalidLines.entrySet()) { for (final Map.Entry<Integer, String> entry : invalidLines.entrySet()) {
count++; count++;
final String message = String.format( final String message = String.format(
Locale.ROOT, Locale.ROOT,
"[%d]: encountered improperly formatted JVM option line [%s] on line number [%d]", "[%d]: encountered improperly formatted JVM option line [%s] on line number [%d]",
count, count,
entry.getValue(), entry.getValue(),
entry.getKey()); entry.getKey()
);
Launchers.errPrintln(message); Launchers.errPrintln(message);
} }
Launchers.exit(1); Launchers.exit(1);
@ -123,21 +126,19 @@ final class JvmOptionsParser {
} }
static List<String> substitutePlaceholders(final List<String> jvmOptions, final Map<String, String> substitutions) { static List<String> substitutePlaceholders(final List<String> jvmOptions, final Map<String, String> substitutions) {
final Map<String, String> placeholderSubstitutions = final Map<String, String> placeholderSubstitutions = substitutions.entrySet()
substitutions.entrySet().stream().collect(Collectors.toMap(e -> "${" + e.getKey() + "}", Map.Entry::getValue)); .stream()
return jvmOptions.stream() .collect(Collectors.toMap(e -> "${" + e.getKey() + "}", Map.Entry::getValue));
.map( return jvmOptions.stream().map(jvmOption -> {
jvmOption -> { String actualJvmOption = jvmOption;
String actualJvmOption = jvmOption; int start = jvmOption.indexOf("${");
int start = jvmOption.indexOf("${"); if (start >= 0 && jvmOption.indexOf('}', start) > 0) {
if (start >= 0 && jvmOption.indexOf('}', start) > 0) { for (final Map.Entry<String, String> placeholderSubstitution : placeholderSubstitutions.entrySet()) {
for (final Map.Entry<String, String> placeholderSubstitution : placeholderSubstitutions.entrySet()) { actualJvmOption = actualJvmOption.replace(placeholderSubstitution.getKey(), placeholderSubstitution.getValue());
actualJvmOption = actualJvmOption.replace(placeholderSubstitution.getKey(), placeholderSubstitution.getValue()); }
} }
} return actualJvmOption;
return actualJvmOption; }).collect(Collectors.toList());
})
.collect(Collectors.toList());
} }
/** /**
@ -223,10 +224,11 @@ final class JvmOptionsParser {
* @throws IOException if an I/O exception occurs reading from the buffered reader * @throws IOException if an I/O exception occurs reading from the buffered reader
*/ */
static void parse( static void parse(
final int javaMajorVersion, final int javaMajorVersion,
final BufferedReader br, final BufferedReader br,
final JvmOptionConsumer jvmOptionConsumer, final JvmOptionConsumer jvmOptionConsumer,
final InvalidLineConsumer invalidLineConsumer) throws IOException { final InvalidLineConsumer invalidLineConsumer
) throws IOException {
int lineNumber = 0; int lineNumber = 0;
while (true) { while (true) {
final String line = br.readLine(); final String line = br.readLine();

View File

@ -28,42 +28,45 @@ import java.util.List;
final class SystemJvmOptions { final class SystemJvmOptions {
static List<String> systemJvmOptions() { static List<String> systemJvmOptions() {
return Collections.unmodifiableList(Arrays.asList( return Collections.unmodifiableList(
/* Arrays.asList(
* Cache ttl in seconds for positive DNS lookups noting that this overrides the JDK security property networkaddress.cache.ttl; /*
* can be set to -1 to cache forever. * Cache ttl in seconds for positive DNS lookups noting that this overrides the JDK security property
*/ * networkaddress.cache.ttl; can be set to -1 to cache forever.
"-Des.networkaddress.cache.ttl=60", */
/* "-Des.networkaddress.cache.ttl=60",
* Cache ttl in seconds for negative DNS lookups noting that this overrides the JDK security property /*
* networkaddress.cache.negative ttl; set to -1 to cache forever. * Cache ttl in seconds for negative DNS lookups noting that this overrides the JDK security property
*/ * networkaddress.cache.negative ttl; set to -1 to cache forever.
"-Des.networkaddress.cache.negative.ttl=10", */
// pre-touch JVM emory pages during initialization "-Des.networkaddress.cache.negative.ttl=10",
"-XX:+AlwaysPreTouch", // pre-touch JVM emory pages during initialization
// explicitly set the stack size "-XX:+AlwaysPreTouch",
"-Xss1m", // explicitly set the stack size
// set to headless, just in case, "-Xss1m",
"-Djava.awt.headless=true", // set to headless, just in case,
// ensure UTF-8 encoding by default (e.g., filenames) "-Djava.awt.headless=true",
"-Dfile.encoding=UTF-8", // ensure UTF-8 encoding by default (e.g., filenames)
// use our provided JNA always versus the system one "-Dfile.encoding=UTF-8",
"-Djna.nosys=true", // use our provided JNA always versus the system one
/* "-Djna.nosys=true",
* Turn off a JDK optimization that throws away stack traces for common exceptions because stack traces are important for /*
* debugging. * Turn off a JDK optimization that throws away stack traces for common exceptions because stack traces are important for
*/ * debugging.
"-XX:-OmitStackTraceInFastThrow", */
// flags to configure Netty "-XX:-OmitStackTraceInFastThrow",
"-Dio.netty.noUnsafe=true", // flags to configure Netty
"-Dio.netty.noKeySetOptimization=true", "-Dio.netty.noUnsafe=true",
"-Dio.netty.recycler.maxCapacityPerThread=0", "-Dio.netty.noKeySetOptimization=true",
"-Dio.netty.allocator.numDirectArenas=0", "-Dio.netty.recycler.maxCapacityPerThread=0",
// log4j 2 "-Dio.netty.allocator.numDirectArenas=0",
"-Dlog4j.shutdownHookEnabled=false", // log4j 2
"-Dlog4j2.disable.jmx=true", "-Dlog4j.shutdownHookEnabled=false",
"-Dlog4j2.disable.jmx=true",
javaLocaleProviders())); javaLocaleProviders()
)
);
} }
private static String javaLocaleProviders() { private static String javaLocaleProviders() {
@ -77,7 +80,7 @@ final class SystemJvmOptions {
* //TODO COMPAT will be deprecated in jdk14 https://bugs.openjdk.java.net/browse/JDK-8232906 * //TODO COMPAT will be deprecated in jdk14 https://bugs.openjdk.java.net/browse/JDK-8232906
* See also: documentation in <code>server/org.elasticsearch.common.time.IsoCalendarDataProvider</code> * See also: documentation in <code>server/org.elasticsearch.common.time.IsoCalendarDataProvider</code>
*/ */
if(JavaVersion.majorVersion(JavaVersion.CURRENT) == 8){ if (JavaVersion.majorVersion(JavaVersion.CURRENT) == 8) {
return "-Djava.locale.providers=SPI,JRE"; return "-Djava.locale.providers=SPI,JRE";
} else { } else {
return "-Djava.locale.providers=SPI,COMPAT"; return "-Djava.locale.providers=SPI,COMPAT";

View File

@ -45,23 +45,20 @@ import static org.junit.Assert.fail;
public class JvmErgonomicsTests extends LaunchersTestCase { public class JvmErgonomicsTests extends LaunchersTestCase {
public void testExtractValidHeapSizeUsingXmx() throws InterruptedException, IOException { public void testExtractValidHeapSizeUsingXmx() throws InterruptedException, IOException {
assertThat( assertThat(JvmErgonomics.extractHeapSize(JvmErgonomics.finalJvmOptions(Collections.singletonList("-Xmx2g"))), equalTo(2L << 30));
JvmErgonomics.extractHeapSize(JvmErgonomics.finalJvmOptions(Collections.singletonList("-Xmx2g"))),
equalTo(2L << 30));
} }
public void testExtractValidHeapSizeUsingMaxHeapSize() throws InterruptedException, IOException { public void testExtractValidHeapSizeUsingMaxHeapSize() throws InterruptedException, IOException {
assertThat( assertThat(
JvmErgonomics.extractHeapSize(JvmErgonomics.finalJvmOptions(Collections.singletonList("-XX:MaxHeapSize=2g"))), JvmErgonomics.extractHeapSize(JvmErgonomics.finalJvmOptions(Collections.singletonList("-XX:MaxHeapSize=2g"))),
equalTo(2L << 30)); equalTo(2L << 30)
);
} }
public void testExtractValidHeapSizeNoOptionPresent() throws InterruptedException, IOException { public void testExtractValidHeapSizeNoOptionPresent() throws InterruptedException, IOException {
// Muted for jdk8/Windows, see: https://github.com/elastic/elasticsearch/issues/47384 // Muted for jdk8/Windows, see: https://github.com/elastic/elasticsearch/issues/47384
assumeFalse(System.getProperty("os.name").startsWith("Windows") && JavaVersion.majorVersion(JavaVersion.CURRENT) == 8); assumeFalse(System.getProperty("os.name").startsWith("Windows") && JavaVersion.majorVersion(JavaVersion.CURRENT) == 8);
assertThat( assertThat(JvmErgonomics.extractHeapSize(JvmErgonomics.finalJvmOptions(Collections.emptyList())), greaterThan(0L));
JvmErgonomics.extractHeapSize(JvmErgonomics.finalJvmOptions(Collections.emptyList())),
greaterThan(0L));
} }
public void testHeapSizeInvalid() throws InterruptedException, IOException { public void testHeapSizeInvalid() throws InterruptedException, IOException {
@ -81,8 +78,9 @@ public class JvmErgonomicsTests extends LaunchersTestCase {
} catch (final RuntimeException e) { } catch (final RuntimeException e) {
assertThat(e, hasToString(containsString(("starting java failed")))); assertThat(e, hasToString(containsString(("starting java failed"))));
assertThat( assertThat(
e, e,
anyOf(hasToString(containsString("Too small initial heap")), hasToString(containsString("Too small maximum heap")))); anyOf(hasToString(containsString("Too small initial heap")), hasToString(containsString("Too small maximum heap")))
);
} }
} }
@ -98,15 +96,18 @@ public class JvmErgonomicsTests extends LaunchersTestCase {
public void testMaxDirectMemorySizeUnset() throws InterruptedException, IOException { public void testMaxDirectMemorySizeUnset() throws InterruptedException, IOException {
assertThat( assertThat(
JvmErgonomics.extractMaxDirectMemorySize(JvmErgonomics.finalJvmOptions(Collections.singletonList("-Xmx1g"))), JvmErgonomics.extractMaxDirectMemorySize(JvmErgonomics.finalJvmOptions(Collections.singletonList("-Xmx1g"))),
equalTo(0L)); equalTo(0L)
);
} }
public void testMaxDirectMemorySizeSet() throws InterruptedException, IOException { public void testMaxDirectMemorySizeSet() throws InterruptedException, IOException {
assertThat( assertThat(
JvmErgonomics.extractMaxDirectMemorySize(JvmErgonomics.finalJvmOptions( JvmErgonomics.extractMaxDirectMemorySize(
Arrays.asList("-Xmx1g", "-XX:MaxDirectMemorySize=512m"))), JvmErgonomics.finalJvmOptions(Arrays.asList("-Xmx1g", "-XX:MaxDirectMemorySize=512m"))
equalTo(512L << 20)); ),
equalTo(512L << 20)
);
} }
public void testExtractSystemProperties() { public void testExtractSystemProperties() {
@ -115,7 +116,8 @@ public class JvmErgonomicsTests extends LaunchersTestCase {
expectedSystemProperties.put("kv.setting", "ABC=DEF"); expectedSystemProperties.put("kv.setting", "ABC=DEF");
Map<String, String> parsedSystemProperties = JvmErgonomics.extractSystemProperties( Map<String, String> parsedSystemProperties = JvmErgonomics.extractSystemProperties(
Arrays.asList("-Dfile.encoding=UTF-8", "-Dkv.setting=ABC=DEF")); Arrays.asList("-Dfile.encoding=UTF-8", "-Dkv.setting=ABC=DEF")
);
assertEquals(expectedSystemProperties, parsedSystemProperties); assertEquals(expectedSystemProperties, parsedSystemProperties);
} }
@ -132,22 +134,24 @@ public class JvmErgonomicsTests extends LaunchersTestCase {
heapMaxDirectMemorySize.put("64M", Long.toString((64L << 20) / 2)); heapMaxDirectMemorySize.put("64M", Long.toString((64L << 20) / 2));
heapMaxDirectMemorySize.put("512M", Long.toString((512L << 20) / 2)); heapMaxDirectMemorySize.put("512M", Long.toString((512L << 20) / 2));
heapMaxDirectMemorySize.put("1024M", Long.toString((1024L << 20) / 2)); heapMaxDirectMemorySize.put("1024M", Long.toString((1024L << 20) / 2));
heapMaxDirectMemorySize.put("1G", Long.toString((1L << 30) / 2)); heapMaxDirectMemorySize.put("1G", Long.toString((1L << 30) / 2));
heapMaxDirectMemorySize.put("2048M", Long.toString((2048L << 20) / 2)); heapMaxDirectMemorySize.put("2048M", Long.toString((2048L << 20) / 2));
heapMaxDirectMemorySize.put("2G", Long.toString((2L << 30) / 2)); heapMaxDirectMemorySize.put("2G", Long.toString((2L << 30) / 2));
heapMaxDirectMemorySize.put("8G", Long.toString((8L << 30) / 2)); heapMaxDirectMemorySize.put("8G", Long.toString((8L << 30) / 2));
final String heapSize = randomFrom(heapMaxDirectMemorySize.keySet().toArray(new String[0])); final String heapSize = randomFrom(heapMaxDirectMemorySize.keySet().toArray(new String[0]));
assertThat( assertThat(
JvmErgonomics.choose(Arrays.asList("-Xms" + heapSize, "-Xmx" + heapSize)), JvmErgonomics.choose(Arrays.asList("-Xms" + heapSize, "-Xmx" + heapSize)),
hasItem("-XX:MaxDirectMemorySize=" + heapMaxDirectMemorySize.get(heapSize))); hasItem("-XX:MaxDirectMemorySize=" + heapMaxDirectMemorySize.get(heapSize))
);
} }
public void testMaxDirectMemorySizeChoiceWhenSet() throws InterruptedException, IOException { public void testMaxDirectMemorySizeChoiceWhenSet() throws InterruptedException, IOException {
List<String> derivedSettingList = JvmErgonomics.choose(Arrays.asList("-Xms5g", "-Xmx5g", "-XX:MaxDirectMemorySize=4g")); List<String> derivedSettingList = JvmErgonomics.choose(Arrays.asList("-Xms5g", "-Xmx5g", "-XX:MaxDirectMemorySize=4g"));
assertThat( assertThat(
derivedSettingList, derivedSettingList,
// if MaxDirectMemorySize is set, we shouldn't derive our own value for it // if MaxDirectMemorySize is set, we shouldn't derive our own value for it
everyItem(not(startsWith("-XX:MaxDirectMemorySize=")))); everyItem(not(startsWith("-XX:MaxDirectMemorySize=")))
);
} }
} }

View File

@ -43,13 +43,13 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
public void testSubstitution() { public void testSubstitution() {
final List<String> jvmOptions = JvmOptionsParser.substitutePlaceholders( final List<String> jvmOptions = JvmOptionsParser.substitutePlaceholders(
Collections.singletonList("-Djava.io.tmpdir=${ES_TMPDIR}"), Collections.singletonList("-Djava.io.tmpdir=${ES_TMPDIR}"),
Collections.singletonMap("ES_TMPDIR", "/tmp/elasticsearch")); Collections.singletonMap("ES_TMPDIR", "/tmp/elasticsearch")
);
assertThat(jvmOptions, contains("-Djava.io.tmpdir=/tmp/elasticsearch")); assertThat(jvmOptions, contains("-Djava.io.tmpdir=/tmp/elasticsearch"));
} }
public void testUnversionedOptions() throws IOException { public void testUnversionedOptions() throws IOException {
try (StringReader sr = new StringReader("-Xms1g\n-Xmx1g"); try (StringReader sr = new StringReader("-Xms1g\n-Xmx1g"); BufferedReader br = new BufferedReader(sr)) {
BufferedReader br = new BufferedReader(sr)) {
assertExpectedJvmOptions(randomIntBetween(8, Integer.MAX_VALUE), br, Arrays.asList("-Xms1g", "-Xmx1g")); assertExpectedJvmOptions(randomIntBetween(8, Integer.MAX_VALUE), br, Arrays.asList("-Xms1g", "-Xmx1g"));
} }
@ -59,14 +59,18 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE - 1); final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE - 1);
final int smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion); final int smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion);
final int largerJavaMajorVersion = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE); final int largerJavaMajorVersion = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
try (StringReader sr = new StringReader( try (
StringReader sr = new StringReader(
String.format( String.format(
Locale.ROOT, Locale.ROOT,
"-Xms1g\n%d:-Xmx1g\n%d:-XX:+UseG1GC\n%d:-Xlog:gc", "-Xms1g\n%d:-Xmx1g\n%d:-XX:+UseG1GC\n%d:-Xlog:gc",
javaMajorVersion, javaMajorVersion,
smallerJavaMajorVersion, smallerJavaMajorVersion,
largerJavaMajorVersion)); largerJavaMajorVersion
BufferedReader br = new BufferedReader(sr)) { )
);
BufferedReader br = new BufferedReader(sr)
) {
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g")); assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g"));
} }
} }
@ -75,14 +79,18 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE - 1); final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE - 1);
final int smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion); final int smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion);
final int largerJavaMajorVersion = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE); final int largerJavaMajorVersion = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
try (StringReader sr = new StringReader( try (
StringReader sr = new StringReader(
String.format( String.format(
Locale.ROOT, Locale.ROOT,
"-Xms1g\n%d-:-Xmx1g\n%d-:-XX:+UseG1GC\n%d-:-Xlog:gc", "-Xms1g\n%d-:-Xmx1g\n%d-:-XX:+UseG1GC\n%d-:-Xlog:gc",
javaMajorVersion, javaMajorVersion,
smallerJavaMajorVersion, smallerJavaMajorVersion,
largerJavaMajorVersion)); largerJavaMajorVersion
BufferedReader br = new BufferedReader(sr)) { )
);
BufferedReader br = new BufferedReader(sr)
) {
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC")); assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC"));
} }
} }
@ -94,17 +102,21 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
final int smallerJavaMajorVersionUpperBound = randomIntBetween(smallerJavaMajorVersionLowerBound, javaMajorVersion); final int smallerJavaMajorVersionUpperBound = randomIntBetween(smallerJavaMajorVersionLowerBound, javaMajorVersion);
final int largerJavaMajorVersionLowerBound = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE); final int largerJavaMajorVersionLowerBound = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
final int largerJavaMajorVersionUpperBound = randomIntBetween(largerJavaMajorVersionLowerBound, Integer.MAX_VALUE); final int largerJavaMajorVersionUpperBound = randomIntBetween(largerJavaMajorVersionLowerBound, Integer.MAX_VALUE);
try (StringReader sr = new StringReader( try (
StringReader sr = new StringReader(
String.format( String.format(
Locale.ROOT, Locale.ROOT,
"-Xms1g\n%d-%d:-Xmx1g\n%d-%d:-XX:+UseG1GC\n%d-%d:-Xlog:gc", "-Xms1g\n%d-%d:-Xmx1g\n%d-%d:-XX:+UseG1GC\n%d-%d:-Xlog:gc",
javaMajorVersion, javaMajorVersion,
javaMajorVersionUpperBound, javaMajorVersionUpperBound,
smallerJavaMajorVersionLowerBound, smallerJavaMajorVersionLowerBound,
smallerJavaMajorVersionUpperBound, smallerJavaMajorVersionUpperBound,
largerJavaMajorVersionLowerBound, largerJavaMajorVersionLowerBound,
largerJavaMajorVersionUpperBound)); largerJavaMajorVersionUpperBound
BufferedReader br = new BufferedReader(sr)) { )
);
BufferedReader br = new BufferedReader(sr)
) {
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g")); assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g"));
} }
} }
@ -116,91 +128,86 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
final int smallerJavaMajorVersionUpperBound = randomIntBetween(smallerJavaMajorVersionLowerBound, javaMajorVersion); final int smallerJavaMajorVersionUpperBound = randomIntBetween(smallerJavaMajorVersionLowerBound, javaMajorVersion);
final int largerJavaMajorVersionLowerBound = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE); final int largerJavaMajorVersionLowerBound = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
final int largerJavaMajorVersionUpperBound = randomIntBetween(largerJavaMajorVersionLowerBound, Integer.MAX_VALUE); final int largerJavaMajorVersionUpperBound = randomIntBetween(largerJavaMajorVersionLowerBound, Integer.MAX_VALUE);
try (StringReader sr = new StringReader( try (
StringReader sr = new StringReader(
String.format( String.format(
Locale.ROOT, Locale.ROOT,
"-Xms1g\n%d:-Xmx1g\n%d-:-XX:+UseG1GC\n%d-%d:-Xlog:gc\n%d-%d:-XX:+PrintFlagsFinal\n%d-%d:-XX+AggressiveOpts", "-Xms1g\n%d:-Xmx1g\n%d-:-XX:+UseG1GC\n%d-%d:-Xlog:gc\n%d-%d:-XX:+PrintFlagsFinal\n%d-%d:-XX+AggressiveOpts",
javaMajorVersion, javaMajorVersion,
javaMajorVersion, javaMajorVersion,
javaMajorVersion, javaMajorVersion,
javaMajorVersionUpperBound, javaMajorVersionUpperBound,
smallerJavaMajorVersionLowerBound, smallerJavaMajorVersionLowerBound,
smallerJavaMajorVersionUpperBound, smallerJavaMajorVersionUpperBound,
largerJavaMajorVersionLowerBound, largerJavaMajorVersionLowerBound,
largerJavaMajorVersionUpperBound)); largerJavaMajorVersionUpperBound
BufferedReader br = new BufferedReader(sr)) { )
);
BufferedReader br = new BufferedReader(sr)
) {
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC", "-Xlog:gc")); assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC", "-Xlog:gc"));
} }
} }
private void assertExpectedJvmOptions( private void assertExpectedJvmOptions(final int javaMajorVersion, final BufferedReader br, final List<String> expectedJvmOptions)
final int javaMajorVersion, final BufferedReader br, final List<String> expectedJvmOptions) throws IOException { throws IOException {
final Map<String, AtomicBoolean> seenJvmOptions = new HashMap<>(); final Map<String, AtomicBoolean> seenJvmOptions = new HashMap<>();
for (final String expectedJvmOption : expectedJvmOptions) { for (final String expectedJvmOption : expectedJvmOptions) {
assertNull(seenJvmOptions.put(expectedJvmOption, new AtomicBoolean())); assertNull(seenJvmOptions.put(expectedJvmOption, new AtomicBoolean()));
} }
JvmOptionsParser.parse( JvmOptionsParser.parse(javaMajorVersion, br, new JvmOptionsParser.JvmOptionConsumer() {
javaMajorVersion, @Override
br, public void accept(final String jvmOption) {
new JvmOptionsParser.JvmOptionConsumer() { final AtomicBoolean seen = seenJvmOptions.get(jvmOption);
@Override if (seen == null) {
public void accept(final String jvmOption) { fail("unexpected JVM option [" + jvmOption + "]");
final AtomicBoolean seen = seenJvmOptions.get(jvmOption); }
if (seen == null) { assertFalse("saw JVM option [" + jvmOption + "] more than once", seen.get());
fail("unexpected JVM option [" + jvmOption + "]"); seen.set(true);
} }
assertFalse("saw JVM option [" + jvmOption + "] more than once", seen.get()); }, new JvmOptionsParser.InvalidLineConsumer() {
seen.set(true); @Override
} public void accept(final int lineNumber, final String line) {
}, fail("unexpected invalid line [" + line + "] on line number [" + lineNumber + "]");
new JvmOptionsParser.InvalidLineConsumer() { }
@Override });
public void accept(final int lineNumber, final String line) {
fail("unexpected invalid line [" + line + "] on line number [" + lineNumber + "]");
}
});
for (final Map.Entry<String, AtomicBoolean> seenJvmOption : seenJvmOptions.entrySet()) { for (final Map.Entry<String, AtomicBoolean> seenJvmOption : seenJvmOptions.entrySet()) {
assertTrue("expected JVM option [" + seenJvmOption.getKey() + "]", seenJvmOption.getValue().get()); assertTrue("expected JVM option [" + seenJvmOption.getKey() + "]", seenJvmOption.getValue().get());
} }
} }
public void testInvalidLines() throws IOException { public void testInvalidLines() throws IOException {
try (StringReader sr = new StringReader("XX:+UseG1GC"); try (StringReader sr = new StringReader("XX:+UseG1GC"); BufferedReader br = new BufferedReader(sr)) {
BufferedReader br = new BufferedReader(sr)) { JvmOptionsParser.parse(randomIntBetween(8, Integer.MAX_VALUE), br, new JvmOptionsParser.JvmOptionConsumer() {
JvmOptionsParser.parse( @Override
randomIntBetween(8, Integer.MAX_VALUE), public void accept(final String jvmOption) {
br, fail("unexpected valid JVM option [" + jvmOption + "]");
new JvmOptionsParser.JvmOptionConsumer() { }
@Override }, new JvmOptionsParser.InvalidLineConsumer() {
public void accept(final String jvmOption) { @Override
fail("unexpected valid JVM option [" + jvmOption + "]"); public void accept(final int lineNumber, final String line) {
} assertThat(lineNumber, equalTo(1));
}, new JvmOptionsParser.InvalidLineConsumer() { assertThat(line, equalTo("XX:+UseG1GC"));
@Override }
public void accept(final int lineNumber, final String line) { });
assertThat(lineNumber, equalTo(1));
assertThat(line, equalTo("XX:+UseG1GC"));
}
});
} }
final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE); final int javaMajorVersion = randomIntBetween(8, Integer.MAX_VALUE);
final int smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion - 1); final int smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion - 1);
final String invalidRangeLine = String.format(Locale.ROOT, "%d:%d-XX:+UseG1GC", javaMajorVersion, smallerJavaMajorVersion); final String invalidRangeLine = String.format(Locale.ROOT, "%d:%d-XX:+UseG1GC", javaMajorVersion, smallerJavaMajorVersion);
try (StringReader sr = new StringReader(invalidRangeLine); try (StringReader sr = new StringReader(invalidRangeLine); BufferedReader br = new BufferedReader(sr)) {
BufferedReader br = new BufferedReader(sr)) {
assertInvalidLines(br, Collections.singletonMap(1, invalidRangeLine)); assertInvalidLines(br, Collections.singletonMap(1, invalidRangeLine));
} }
final long invalidLowerJavaMajorVersion = (long) randomIntBetween(1, 16) + Integer.MAX_VALUE; final long invalidLowerJavaMajorVersion = (long) randomIntBetween(1, 16) + Integer.MAX_VALUE;
final long invalidUpperJavaMajorVersion = (long) randomIntBetween(1, 16) + Integer.MAX_VALUE; final long invalidUpperJavaMajorVersion = (long) randomIntBetween(1, 16) + Integer.MAX_VALUE;
final String numberFormatExceptionsLine = String.format( final String numberFormatExceptionsLine = String.format(
Locale.ROOT, Locale.ROOT,
"%d:-XX:+UseG1GC\n8-%d:-XX:+AggressiveOpts", "%d:-XX:+UseG1GC\n8-%d:-XX:+AggressiveOpts",
invalidLowerJavaMajorVersion, invalidLowerJavaMajorVersion,
invalidUpperJavaMajorVersion); invalidUpperJavaMajorVersion
try (StringReader sr = new StringReader(numberFormatExceptionsLine); );
BufferedReader br = new BufferedReader(sr)) { try (StringReader sr = new StringReader(numberFormatExceptionsLine); BufferedReader br = new BufferedReader(sr)) {
final Map<Integer, String> invalidLines = new HashMap<>(2); final Map<Integer, String> invalidLines = new HashMap<>(2);
invalidLines.put(1, String.format(Locale.ROOT, "%d:-XX:+UseG1GC", invalidLowerJavaMajorVersion)); invalidLines.put(1, String.format(Locale.ROOT, "%d:-XX:+UseG1GC", invalidLowerJavaMajorVersion));
invalidLines.put(2, String.format(Locale.ROOT, "8-%d:-XX:+AggressiveOpts", invalidUpperJavaMajorVersion)); invalidLines.put(2, String.format(Locale.ROOT, "8-%d:-XX:+AggressiveOpts", invalidUpperJavaMajorVersion));
@ -208,8 +215,7 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
} }
final String multipleInvalidLines = "XX:+UseG1GC\nXX:+AggressiveOpts"; final String multipleInvalidLines = "XX:+UseG1GC\nXX:+AggressiveOpts";
try (StringReader sr = new StringReader(multipleInvalidLines); try (StringReader sr = new StringReader(multipleInvalidLines); BufferedReader br = new BufferedReader(sr)) {
BufferedReader br = new BufferedReader(sr)) {
final Map<Integer, String> invalidLines = new HashMap<>(2); final Map<Integer, String> invalidLines = new HashMap<>(2);
invalidLines.put(1, "XX:+UseG1GC"); invalidLines.put(1, "XX:+UseG1GC");
invalidLines.put(2, "XX:+AggressiveOpts"); invalidLines.put(2, "XX:+AggressiveOpts");
@ -219,29 +225,24 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
final int lowerBound = randomIntBetween(9, 16); final int lowerBound = randomIntBetween(9, 16);
final int upperBound = randomIntBetween(8, lowerBound - 1); final int upperBound = randomIntBetween(8, lowerBound - 1);
final String upperBoundGreaterThanLowerBound = String.format(Locale.ROOT, "%d-%d-XX:+UseG1GC", lowerBound, upperBound); final String upperBoundGreaterThanLowerBound = String.format(Locale.ROOT, "%d-%d-XX:+UseG1GC", lowerBound, upperBound);
try (StringReader sr = new StringReader(upperBoundGreaterThanLowerBound); try (StringReader sr = new StringReader(upperBoundGreaterThanLowerBound); BufferedReader br = new BufferedReader(sr)) {
BufferedReader br = new BufferedReader(sr)) {
assertInvalidLines(br, Collections.singletonMap(1, upperBoundGreaterThanLowerBound)); assertInvalidLines(br, Collections.singletonMap(1, upperBoundGreaterThanLowerBound));
} }
} }
private void assertInvalidLines(final BufferedReader br, final Map<Integer, String> invalidLines) throws IOException { private void assertInvalidLines(final BufferedReader br, final Map<Integer, String> invalidLines) throws IOException {
final Map<Integer, String> seenInvalidLines = new HashMap<>(invalidLines.size()); final Map<Integer, String> seenInvalidLines = new HashMap<>(invalidLines.size());
JvmOptionsParser.parse( JvmOptionsParser.parse(randomIntBetween(8, Integer.MAX_VALUE), br, new JvmOptionsParser.JvmOptionConsumer() {
randomIntBetween(8, Integer.MAX_VALUE), @Override
br, public void accept(final String jvmOption) {
new JvmOptionsParser.JvmOptionConsumer() { fail("unexpected valid JVM options [" + jvmOption + "]");
@Override }
public void accept(final String jvmOption) { }, new JvmOptionsParser.InvalidLineConsumer() {
fail("unexpected valid JVM options [" + jvmOption + "]"); @Override
} public void accept(final int lineNumber, final String line) {
}, seenInvalidLines.put(lineNumber, line);
new JvmOptionsParser.InvalidLineConsumer() { }
@Override });
public void accept(final int lineNumber, final String line) {
seenInvalidLines.put(lineNumber, line);
}
});
assertThat(seenInvalidLines, equalTo(invalidLines)); assertThat(seenInvalidLines, equalTo(invalidLines));
} }
@ -249,8 +250,9 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
assertThat(JvmOptionsParser.spaceDelimitJvmOptions(Collections.singletonList("-Xms1g")), equalTo("-Xms1g")); assertThat(JvmOptionsParser.spaceDelimitJvmOptions(Collections.singletonList("-Xms1g")), equalTo("-Xms1g"));
assertThat(JvmOptionsParser.spaceDelimitJvmOptions(Arrays.asList("-Xms1g", "-Xmx1g")), equalTo("-Xms1g -Xmx1g")); assertThat(JvmOptionsParser.spaceDelimitJvmOptions(Arrays.asList("-Xms1g", "-Xmx1g")), equalTo("-Xms1g -Xmx1g"));
assertThat( assertThat(
JvmOptionsParser.spaceDelimitJvmOptions(Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC")), JvmOptionsParser.spaceDelimitJvmOptions(Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC")),
equalTo("-Xms1g -Xmx1g -XX:+UseG1GC")); equalTo("-Xms1g -Xmx1g -XX:+UseG1GC")
);
} }
} }

View File

@ -31,15 +31,12 @@ import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies; import com.carrotsearch.randomizedtesting.annotations.ThreadLeakZombies;
import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite;
@TestMethodProviders({ @TestMethodProviders({ JUnit3MethodProvider.class })
JUnit3MethodProvider.class @SeedDecorators({ MixWithSuiteName.class })
})
@SeedDecorators({MixWithSuiteName.class})
@ThreadLeakScope(ThreadLeakScope.Scope.SUITE) @ThreadLeakScope(ThreadLeakScope.Scope.SUITE)
@ThreadLeakGroup(ThreadLeakGroup.Group.MAIN) @ThreadLeakGroup(ThreadLeakGroup.Group.MAIN)
@ThreadLeakAction({ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT}) @ThreadLeakAction({ ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT })
@ThreadLeakZombies(ThreadLeakZombies.Consequence.IGNORE_REMAINING_TESTS) @ThreadLeakZombies(ThreadLeakZombies.Consequence.IGNORE_REMAINING_TESTS)
@ThreadLeakLingering(linger = 5000) @ThreadLeakLingering(linger = 5000)
@TimeoutSuite(millis = 2 * 60 * 60 * 1000) @TimeoutSuite(millis = 2 * 60 * 60 * 1000)
abstract class LaunchersTestCase extends RandomizedTest { abstract class LaunchersTestCase extends RandomizedTest {}
}

View File

@ -134,8 +134,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
/** The builtin modules, which are plugins, but cannot be installed or removed. */ /** The builtin modules, which are plugins, but cannot be installed or removed. */
static final Set<String> MODULES; static final Set<String> MODULES;
static { static {
try (InputStream stream = InstallPluginCommand.class.getResourceAsStream("/modules.txt"); try (
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { InputStream stream = InstallPluginCommand.class.getResourceAsStream("/modules.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))
) {
Set<String> modules = new HashSet<>(); Set<String> modules = new HashSet<>();
String line = reader.readLine(); String line = reader.readLine();
while (line != null) { while (line != null) {
@ -151,8 +153,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
/** The official plugins that can be installed simply by name. */ /** The official plugins that can be installed simply by name. */
static final Set<String> OFFICIAL_PLUGINS; static final Set<String> OFFICIAL_PLUGINS;
static { static {
try (InputStream stream = InstallPluginCommand.class.getResourceAsStream("/plugins.txt"); try (
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { InputStream stream = InstallPluginCommand.class.getResourceAsStream("/plugins.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))
) {
Set<String> plugins = new TreeSet<>(); // use tree set to get sorting for help command Set<String> plugins = new TreeSet<>(); // use tree set to get sorting for help command
String line = reader.readLine(); String line = reader.readLine();
while (line != null) { while (line != null) {
@ -197,8 +201,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
InstallPluginCommand() { InstallPluginCommand() {
super("Install a plugin"); super("Install a plugin");
this.batchOption = parser.acceptsAll(Arrays.asList("b", "batch"), this.batchOption = parser.acceptsAll(
"Enable batch mode explicitly, automatic confirmation of security permission"); Arrays.asList("b", "batch"),
"Enable batch mode explicitly, automatic confirmation of security permission"
);
this.arguments = parser.nonOptions("plugin id"); this.arguments = parser.nonOptions("plugin id");
} }
@ -261,7 +267,8 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
} catch (final IOException exceptionWhileRemovingFiles) { } catch (final IOException exceptionWhileRemovingFiles) {
final Exception exception = new Exception( final Exception exception = new Exception(
"failed rolling back installation of [" + deleteOnFailureEntry.getKey() + "]", "failed rolling back installation of [" + deleteOnFailureEntry.getKey() + "]",
exceptionWhileRemovingFiles); exceptionWhileRemovingFiles
);
installProblem.addSuppressed(exception); installProblem.addSuppressed(exception);
terminal.println("-> Failed rolling back " + deleteOnFailureEntry.getKey()); terminal.println("-> Failed rolling back " + deleteOnFailureEntry.getKey());
} }
@ -284,8 +291,9 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
throw new UserException(ExitCodes.CONFIG, "this distribution of Elasticsearch contains X-Pack by default"); throw new UserException(ExitCodes.CONFIG, "this distribution of Elasticsearch contains X-Pack by default");
case OSS: case OSS:
throw new UserException( throw new UserException(
ExitCodes.CONFIG, ExitCodes.CONFIG,
"X-Pack is not available with the oss distribution; to use X-Pack features use the default distribution"); "X-Pack is not available with the oss distribution; to use X-Pack features use the default distribution"
);
case UNKNOWN: case UNKNOWN:
throw new IllegalStateException("your distribution is broken"); throw new IllegalStateException("your distribution is broken");
} }
@ -313,7 +321,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
List<String> plugins = checkMisspelledPlugin(pluginId); List<String> plugins = checkMisspelledPlugin(pluginId);
String msg = "Unknown plugin " + pluginId; String msg = "Unknown plugin " + pluginId;
if (plugins.isEmpty() == false) { if (plugins.isEmpty() == false) {
msg += ", did you mean " + (plugins.size() == 1 ? "[" + plugins.get(0) + "]": "any of " + plugins.toString()) + "?"; msg += ", did you mean " + (plugins.size() == 1 ? "[" + plugins.get(0) + "]" : "any of " + plugins.toString()) + "?";
} }
throw new UserException(ExitCodes.USAGE, msg); throw new UserException(ExitCodes.USAGE, msg);
} }
@ -332,16 +340,20 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
/** Returns the url for an official elasticsearch plugin. */ /** Returns the url for an official elasticsearch plugin. */
private String getElasticUrl( private String getElasticUrl(
final Terminal terminal, final Terminal terminal,
final String stagingHash, final String stagingHash,
final Version version, final Version version,
final boolean isSnapshot, final boolean isSnapshot,
final String pluginId, final String pluginId,
final String platform) throws IOException, UserException { final String platform
) throws IOException,
UserException {
final String baseUrl; final String baseUrl;
if (isSnapshot && stagingHash == null) { if (isSnapshot && stagingHash == null) {
throw new UserException( throw new UserException(
ExitCodes.CONFIG, "attempted to install release build of official plugin on snapshot build of Elasticsearch"); ExitCodes.CONFIG,
"attempted to install release build of official plugin on snapshot build of Elasticsearch"
);
} }
if (stagingHash != null) { if (stagingHash != null) {
if (isSnapshot) { if (isSnapshot) {
@ -352,8 +364,14 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
} else { } else {
baseUrl = String.format(Locale.ROOT, "https://artifacts.elastic.co/downloads/elasticsearch-plugins/%s", pluginId); baseUrl = String.format(Locale.ROOT, "https://artifacts.elastic.co/downloads/elasticsearch-plugins/%s", pluginId);
} }
final String platformUrl = final String platformUrl = String.format(
String.format(Locale.ROOT, "%s/%s-%s-%s.zip", baseUrl, pluginId, platform, Build.CURRENT.getQualifiedVersion()); Locale.ROOT,
"%s/%s-%s-%s.zip",
baseUrl,
pluginId,
platform,
Build.CURRENT.getQualifiedVersion()
);
if (urlExists(terminal, platformUrl)) { if (urlExists(terminal, platformUrl)) {
return platformUrl; return platformUrl;
} }
@ -362,7 +380,13 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
private String nonReleaseUrl(final String hostname, final Version version, final String stagingHash, final String pluginId) { private String nonReleaseUrl(final String hostname, final Version version, final String stagingHash, final String pluginId) {
return String.format( return String.format(
Locale.ROOT, "https://%s.elastic.co/%s-%s/downloads/elasticsearch-plugins/%s", hostname, version, stagingHash, pluginId); Locale.ROOT,
"https://%s.elastic.co/%s-%s/downloads/elasticsearch-plugins/%s",
hostname,
version,
stagingHash,
pluginId
);
} }
/** Returns the url for an elasticsearch plugin in maven. */ /** Returns the url for an elasticsearch plugin in maven. */
@ -419,8 +443,11 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
Path zip = Files.createTempFile(tmpDir, null, ".zip"); Path zip = Files.createTempFile(tmpDir, null, ".zip");
URLConnection urlConnection = url.openConnection(); URLConnection urlConnection = url.openConnection();
urlConnection.addRequestProperty("User-Agent", "elasticsearch-plugin-installer"); urlConnection.addRequestProperty("User-Agent", "elasticsearch-plugin-installer");
try (InputStream in = isBatch ? urlConnection.getInputStream() : try (
new TerminalProgressInputStream(urlConnection.getInputStream(),urlConnection.getContentLength(),terminal)) { InputStream in = isBatch
? urlConnection.getInputStream()
: new TerminalProgressInputStream(urlConnection.getInputStream(), urlConnection.getContentLength(), terminal)
) {
// must overwrite since creating the temp file above actually created the file // must overwrite since creating the temp file above actually created the file
Files.copy(in, zip, StandardCopyOption.REPLACE_EXISTING); Files.copy(in, zip, StandardCopyOption.REPLACE_EXISTING);
} }
@ -493,7 +520,11 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
final Terminal terminal, final Terminal terminal,
final String urlString, final String urlString,
final Path tmpDir, final Path tmpDir,
final boolean officialPlugin, boolean isBatch) throws IOException, PGPException, UserException { final boolean officialPlugin,
boolean isBatch
) throws IOException,
PGPException,
UserException {
Path zip = downloadZip(terminal, urlString, tmpDir, isBatch); Path zip = downloadZip(terminal, urlString, tmpDir, isBatch);
pathsToDeleteOnShutdown.add(zip); pathsToDeleteOnShutdown.add(zip);
String checksumUrlString = urlString + ".sha512"; String checksumUrlString = urlString + ".sha512";
@ -501,8 +532,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
String digestAlgo = "SHA-512"; String digestAlgo = "SHA-512";
if (checksumUrl == null && officialPlugin == false) { if (checksumUrl == null && officialPlugin == false) {
// fallback to sha1, until 7.0, but with warning // fallback to sha1, until 7.0, but with warning
terminal.println("Warning: sha512 not found, falling back to sha1. This behavior is deprecated and will be removed in a " + terminal.println(
"future release. Please update the plugin to use a sha512 checksum."); "Warning: sha512 not found, falling back to sha1. This behavior is deprecated and will be removed in a "
+ "future release. Please update the plugin to use a sha512 checksum."
);
checksumUrlString = urlString + ".sha1"; checksumUrlString = urlString + ".sha1";
checksumUrl = openUrl(checksumUrlString); checksumUrl = openUrl(checksumUrlString);
digestAlgo = "SHA-1"; digestAlgo = "SHA-1";
@ -536,11 +569,12 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
final String expectedFile = segments[segments.length - 1]; final String expectedFile = segments[segments.length - 1];
if (fields[1].equals(expectedFile) == false) { if (fields[1].equals(expectedFile) == false) {
final String message = String.format( final String message = String.format(
Locale.ROOT, Locale.ROOT,
"checksum file at [%s] is not for this plugin, expected [%s] but was [%s]", "checksum file at [%s] is not for this plugin, expected [%s] but was [%s]",
checksumUrl, checksumUrl,
expectedFile, expectedFile,
fields[1]); fields[1]
);
throw new UserException(ExitCodes.IO_ERROR, message); throw new UserException(ExitCodes.IO_ERROR, message);
} }
if (checksumReader.readLine() != null) { if (checksumReader.readLine() != null) {
@ -563,7 +597,8 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
if (expectedChecksum.equals(actualChecksum) == false) { if (expectedChecksum.equals(actualChecksum) == false) {
throw new UserException( throw new UserException(
ExitCodes.IO_ERROR, ExitCodes.IO_ERROR,
digestAlgo + " mismatch, expected " + expectedChecksum + " but got " + actualChecksum); digestAlgo + " mismatch, expected " + expectedChecksum + " but got " + actualChecksum
);
} }
} catch (final NoSuchAlgorithmException e) { } catch (final NoSuchAlgorithmException e) {
// this should never happen as we are using SHA-1 and SHA-512 here // this should never happen as we are using SHA-1 and SHA-512 here
@ -591,12 +626,13 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
final String ascUrlString = urlString + ".asc"; final String ascUrlString = urlString + ".asc";
final URL ascUrl = openUrl(ascUrlString); final URL ascUrl = openUrl(ascUrlString);
try ( try (
// fin is a file stream over the downloaded plugin zip whose signature to verify // fin is a file stream over the downloaded plugin zip whose signature to verify
InputStream fin = pluginZipInputStream(zip); InputStream fin = pluginZipInputStream(zip);
// sin is a URL stream to the signature corresponding to the downloaded plugin zip // sin is a URL stream to the signature corresponding to the downloaded plugin zip
InputStream sin = urlOpenStream(ascUrl); InputStream sin = urlOpenStream(ascUrl);
// ain is a input stream to the public key in ASCII-Armor format (RFC4880) // ain is a input stream to the public key in ASCII-Armor format (RFC4880)
InputStream ain = new ArmoredInputStream(getPublicKey())) { InputStream ain = new ArmoredInputStream(getPublicKey())
) {
final JcaPGPObjectFactory factory = new JcaPGPObjectFactory(PGPUtil.getDecoderStream(sin)); final JcaPGPObjectFactory factory = new JcaPGPObjectFactory(PGPUtil.getDecoderStream(sin));
final PGPSignature signature = ((PGPSignatureList) factory.nextObject()).get(0); final PGPSignature signature = ((PGPSignatureList) factory.nextObject()).get(0);
@ -660,7 +696,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
// pkg private for tests // pkg private for tests
URL openUrl(String urlString) throws IOException { URL openUrl(String urlString) throws IOException {
URL checksumUrl = new URL(urlString); URL checksumUrl = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection)checksumUrl.openConnection(); HttpURLConnection connection = (HttpURLConnection) checksumUrl.openConnection();
if (connection.getResponseCode() == 404) { if (connection.getResponseCode() == 404) {
return null; return null;
} }
@ -678,8 +714,11 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
byte[] buffer = new byte[8192]; byte[] buffer = new byte[8192];
while ((entry = zipInput.getNextEntry()) != null) { while ((entry = zipInput.getNextEntry()) != null) {
if (entry.getName().startsWith("elasticsearch/")) { if (entry.getName().startsWith("elasticsearch/")) {
throw new UserException(PLUGIN_MALFORMED, "This plugin was built with an older plugin structure." + throw new UserException(
" Contact the plugin author to remove the intermediate \"elasticsearch\" directory within the plugin zip."); 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."
);
} }
Path targetFile = target.resolve(entry.getName()); Path targetFile = target.resolve(entry.getName());
@ -689,8 +728,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
// normalizing the path (which removes foo/..) and ensuring the normalized entry // normalizing the path (which removes foo/..) and ensuring the normalized entry
// is still rooted with the target plugin directory. // is still rooted with the target plugin directory.
if (targetFile.normalize().startsWith(target) == false) { if (targetFile.normalize().startsWith(target) == false) {
throw new UserException(PLUGIN_MALFORMED, "Zip contains entry name '" + throw new UserException(
entry.getName() + "' resolving outside of plugin directory"); PLUGIN_MALFORMED,
"Zip contains entry name '" + entry.getName() + "' resolving outside of plugin directory"
);
} }
// be on the safe side: do not rely on that directories are always extracted // be on the safe side: do not rely on that directories are always extracted
@ -725,9 +766,9 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
// and the Jimfs test dependency is upgraded to include // and the Jimfs test dependency is upgraded to include
// this pull request // this pull request
final StackTraceElement[] elements = e.getStackTrace(); final StackTraceElement[] elements = e.getStackTrace();
if (elements.length >= 1 && if (elements.length >= 1
elements[0].getClassName().equals("com.google.common.jimfs.AttributeService") && && elements[0].getClassName().equals("com.google.common.jimfs.AttributeService")
elements[0].getMethodName().equals("setAttributeInternal")) { && elements[0].getMethodName().equals("setAttributeInternal")) {
return stagingDirectoryWithoutPosixPermissions(pluginsDir); return stagingDirectoryWithoutPosixPermissions(pluginsDir);
} else { } else {
throw e; throw e;
@ -753,10 +794,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
if (Files.exists(destination)) { if (Files.exists(destination)) {
final String message = String.format( final String message = String.format(
Locale.ROOT, Locale.ROOT,
"plugin directory [%s] already exists; if you need to update the plugin, " + "plugin directory [%s] already exists; if you need to update the plugin, " + "uninstall it first using command 'remove %s'",
"uninstall it first using command 'remove %s'",
destination, destination,
pluginName); pluginName
);
throw new UserException(PLUGIN_EXISTS, message); throw new UserException(PLUGIN_EXISTS, message);
} }
} }
@ -785,24 +826,19 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
private static final String LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR; private static final String LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR;
static { static {
LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR = LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR = String.format(Locale.ROOT, ".+%1$slib%1$stools%1$splugin-cli%1$s[^%1$s]+\\.jar", "(/|\\\\)");
String.format(Locale.ROOT, ".+%1$slib%1$stools%1$splugin-cli%1$s[^%1$s]+\\.jar", "(/|\\\\)");
} }
/** check a candidate plugin for jar hell before installing it */ /** check a candidate plugin for jar hell before installing it */
void jarHellCheck(PluginInfo candidateInfo, Path candidateDir, Path pluginsDir, Path modulesDir) throws Exception { void jarHellCheck(PluginInfo candidateInfo, Path candidateDir, Path pluginsDir, Path modulesDir) throws Exception {
// create list of current jars in classpath // create list of current jars in classpath
final Set<URL> classpath = final Set<URL> classpath = JarHell.parseClassPath().stream().filter(url -> {
JarHell.parseClassPath() try {
.stream() return url.toURI().getPath().matches(LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR) == false;
.filter(url -> { } catch (final URISyntaxException e) {
try { throw new AssertionError(e);
return url.toURI().getPath().matches(LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR) == false; }
} catch (final URISyntaxException e) { }).collect(Collectors.toSet());
throw new AssertionError(e);
}
})
.collect(Collectors.toSet());
// read existing bundles. this does some checks on the installation too. // read existing bundles. this does some checks on the installation too.
Set<PluginsService.Bundle> bundles = new HashSet<>(PluginsService.getPluginBundles(pluginsDir)); Set<PluginsService.Bundle> bundles = new HashSet<>(PluginsService.getPluginBundles(pluginsDir));
@ -825,8 +861,8 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
* Installs the plugin from {@code tmpRoot} into the plugins dir. * Installs the plugin from {@code tmpRoot} into the plugins dir.
* If the plugin has a bin dir and/or a config dir, those are moved. * If the plugin has a bin dir and/or a config dir, those are moved.
*/ */
private PluginInfo installPlugin(Terminal terminal, boolean isBatch, Path tmpRoot, private PluginInfo installPlugin(Terminal terminal, boolean isBatch, Path tmpRoot, Environment env, List<Path> deleteOnFailure)
Environment env, List<Path> deleteOnFailure) throws Exception { throws Exception {
final PluginInfo info = loadPluginInfo(terminal, tmpRoot, env); final PluginInfo info = loadPluginInfo(terminal, tmpRoot, env);
// read optional security policy (extra permissions), if it exists, confirm or warn the user // read optional security policy (extra permissions), if it exists, confirm or warn the user
Path policy = tmpRoot.resolve(PluginInfo.ES_PLUGIN_POLICY); Path policy = tmpRoot.resolve(PluginInfo.ES_PLUGIN_POLICY);
@ -841,15 +877,20 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
final Path destination = env.pluginsFile().resolve(info.getName()); final Path destination = env.pluginsFile().resolve(info.getName());
deleteOnFailure.add(destination); deleteOnFailure.add(destination);
installPluginSupportFiles(info, tmpRoot, env.binFile().resolve(info.getName()), installPluginSupportFiles(
env.configFile().resolve(info.getName()), deleteOnFailure); info,
tmpRoot,
env.binFile().resolve(info.getName()),
env.configFile().resolve(info.getName()),
deleteOnFailure
);
movePlugin(tmpRoot, destination); movePlugin(tmpRoot, destination);
return info; return info;
} }
/** Moves bin and config directories from the plugin if they exist */ /** Moves bin and config directories from the plugin if they exist */
private void installPluginSupportFiles(PluginInfo info, Path tmpRoot, private void installPluginSupportFiles(PluginInfo info, Path tmpRoot, Path destBinDir, Path destConfigDir, List<Path> deleteOnFailure)
Path destBinDir, Path destConfigDir, List<Path> deleteOnFailure) throws Exception { throws Exception {
Path tmpBinDir = tmpRoot.resolve("bin"); Path tmpBinDir = tmpRoot.resolve("bin");
if (Files.exists(tmpBinDir)) { if (Files.exists(tmpBinDir)) {
deleteOnFailure.add(destBinDir); deleteOnFailure.add(destBinDir);
@ -900,8 +941,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(tmpBinDir)) { try (DirectoryStream<Path> stream = Files.newDirectoryStream(tmpBinDir)) {
for (Path srcFile : stream) { for (Path srcFile : stream) {
if (Files.isDirectory(srcFile)) { if (Files.isDirectory(srcFile)) {
throw new UserException(PLUGIN_MALFORMED, "Directories not allowed in bin dir " + throw new UserException(
"for plugin " + info.getName() + ", found " + srcFile.getFileName()); PLUGIN_MALFORMED,
"Directories not allowed in bin dir " + "for plugin " + info.getName() + ", found " + srcFile.getFileName()
);
} }
Path destFile = destBinDir.resolve(tmpBinDir.relativize(srcFile)); Path destFile = destBinDir.resolve(tmpBinDir.relativize(srcFile));
@ -918,16 +961,18 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
*/ */
private void installConfig(PluginInfo info, Path tmpConfigDir, Path destConfigDir) throws Exception { private void installConfig(PluginInfo info, Path tmpConfigDir, Path destConfigDir) throws Exception {
if (Files.isDirectory(tmpConfigDir) == false) { if (Files.isDirectory(tmpConfigDir) == false) {
throw new UserException(PLUGIN_MALFORMED, throw new UserException(PLUGIN_MALFORMED, "config in plugin " + info.getName() + " is not a directory");
"config in plugin " + info.getName() + " is not a directory");
} }
Files.createDirectories(destConfigDir); Files.createDirectories(destConfigDir);
setFileAttributes(destConfigDir, CONFIG_DIR_PERMS); setFileAttributes(destConfigDir, CONFIG_DIR_PERMS);
final PosixFileAttributeView destConfigDirAttributesView = final PosixFileAttributeView destConfigDirAttributesView = Files.getFileAttributeView(
Files.getFileAttributeView(destConfigDir.getParent(), PosixFileAttributeView.class); destConfigDir.getParent(),
final PosixFileAttributes destConfigDirAttributes = PosixFileAttributeView.class
destConfigDirAttributesView != null ? destConfigDirAttributesView.readAttributes() : null; );
final PosixFileAttributes destConfigDirAttributes = destConfigDirAttributesView != null
? destConfigDirAttributesView.readAttributes()
: null;
if (destConfigDirAttributes != null) { if (destConfigDirAttributes != null) {
setOwnerGroup(destConfigDir, destConfigDirAttributes); setOwnerGroup(destConfigDir, destConfigDirAttributes);
} }
@ -935,8 +980,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(tmpConfigDir)) { try (DirectoryStream<Path> stream = Files.newDirectoryStream(tmpConfigDir)) {
for (Path srcFile : stream) { for (Path srcFile : stream) {
if (Files.isDirectory(srcFile)) { if (Files.isDirectory(srcFile)) {
throw new UserException(PLUGIN_MALFORMED, throw new UserException(PLUGIN_MALFORMED, "Directories not allowed in config dir for plugin " + info.getName());
"Directories not allowed in config dir for plugin " + info.getName());
} }
Path destFile = destConfigDir.resolve(tmpConfigDir.relativize(srcFile)); Path destFile = destConfigDir.resolve(tmpConfigDir.relativize(srcFile));

View File

@ -66,8 +66,15 @@ class ListPluginsCommand extends EnvironmentAwareCommand {
PluginInfo info = PluginInfo.readFromProperties(env.pluginsFile().resolve(plugin)); PluginInfo info = PluginInfo.readFromProperties(env.pluginsFile().resolve(plugin));
terminal.println(Terminal.Verbosity.VERBOSE, info.toString(prefix)); terminal.println(Terminal.Verbosity.VERBOSE, info.toString(prefix));
if (info.getElasticsearchVersion().equals(Version.CURRENT) == false) { if (info.getElasticsearchVersion().equals(Version.CURRENT) == false) {
terminal.errorPrintln("WARNING: plugin [" + info.getName() + "] was built for Elasticsearch version " + info.getVersion() + terminal.errorPrintln(
" but version " + Version.CURRENT + " is required"); "WARNING: plugin ["
+ info.getName()
+ "] was built for Elasticsearch version "
+ info.getVersion()
+ " but version "
+ Version.CURRENT
+ " is required"
);
} }
} }
} }

View File

@ -71,7 +71,7 @@ abstract class ProgressInputStream extends FilterInputStream {
count += byteCount; count += byteCount;
// rounding up to 100% would mean we say we are done, before we are... // rounding up to 100% would mean we say we are done, before we are...
// this also catches issues, when expectedTotalSize was guessed wrong // this also catches issues, when expectedTotalSize was guessed wrong
int percent = Math.min(99, (int) Math.floor(100.0*count/expectedTotalSize)); int percent = Math.min(99, (int) Math.floor(100.0 * count / expectedTotalSize));
if (percent > currentPercent) { if (percent > currentPercent) {
currentPercent = percent; currentPercent = percent;
onProgress(percent); onProgress(percent);

View File

@ -95,8 +95,10 @@ class RemovePluginCommand extends EnvironmentAwareCommand {
} }
} }
if (usedBy.isEmpty() == false) { if (usedBy.isEmpty() == false) {
throw new UserException(PLUGIN_STILL_USED, "plugin [" + pluginName + "] cannot be removed" + throw new UserException(
" because it is extended by other plugins: " + usedBy); PLUGIN_STILL_USED,
"plugin [" + pluginName + "] cannot be removed" + " because it is extended by other plugins: " + usedBy
);
} }
final Path pluginDir = env.pluginsFile().resolve(pluginName); final Path pluginDir = env.pluginsFile().resolve(pluginName);
@ -110,9 +112,12 @@ class RemovePluginCommand extends EnvironmentAwareCommand {
* not exist, the plugin config does, and we are not purging, again fail to the user that the plugin is not found. * not exist, the plugin config does, and we are not purging, again fail to the user that the plugin is not found.
*/ */
if ((!Files.exists(pluginDir) && !Files.exists(pluginConfigDir) && !Files.exists(removing)) if ((!Files.exists(pluginDir) && !Files.exists(pluginConfigDir) && !Files.exists(removing))
|| (!Files.exists(pluginDir) && Files.exists(pluginConfigDir) && !purge)) { || (!Files.exists(pluginDir) && Files.exists(pluginConfigDir) && !purge)) {
final String message = String.format( final String message = String.format(
Locale.ROOT, "plugin [%s] not found; run 'elasticsearch-plugin list' to get list of installed plugins", pluginName); Locale.ROOT,
"plugin [%s] not found; run 'elasticsearch-plugin list' to get list of installed plugins",
pluginName
);
throw new UserException(ExitCodes.CONFIG, message); throw new UserException(ExitCodes.CONFIG, message);
} }
@ -154,9 +159,10 @@ class RemovePluginCommand extends EnvironmentAwareCommand {
* knows in case they want to remove manually. * knows in case they want to remove manually.
*/ */
final String message = String.format( final String message = String.format(
Locale.ROOT, Locale.ROOT,
"-> preserving plugin config files [%s] in case of upgrade; use --purge if not needed", "-> preserving plugin config files [%s] in case of upgrade; use --purge if not needed",
pluginConfigDir); pluginConfigDir
);
terminal.println(message); terminal.println(message);
} }
} }

View File

@ -191,7 +191,7 @@ public class InstallPluginCommandTests extends ESTestCase {
parameters.add(new Parameter(Jimfs.newFileSystem(Configuration.windows()), "c:\\")); 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.osX())), "/"));
parameters.add(new Parameter(Jimfs.newFileSystem(toPosix(Configuration.unix())), "/")); parameters.add(new Parameter(Jimfs.newFileSystem(toPosix(Configuration.unix())), "/"));
parameters.add(new Parameter(PathUtils.getDefaultFileSystem(), LuceneTestCase::createTempDir )); parameters.add(new Parameter(PathUtils.getDefaultFileSystem(), LuceneTestCase::createTempDir));
return parameters.stream().map(p -> new Object[] { p.fileSystem, p.temp }).collect(Collectors.toList()); return parameters.stream().map(p -> new Object[] { p.fileSystem, p.temp }).collect(Collectors.toList());
} }
@ -208,9 +208,7 @@ public class InstallPluginCommandTests extends ESTestCase {
Files.createFile(home.resolve("config").resolve("elasticsearch.yml")); Files.createFile(home.resolve("config").resolve("elasticsearch.yml"));
Path plugins = Files.createDirectories(home.resolve("plugins")); Path plugins = Files.createDirectories(home.resolve("plugins"));
assertTrue(Files.exists(plugins)); assertTrue(Files.exists(plugins));
Settings settings = Settings.builder() Settings settings = Settings.builder().put("path.home", home).build();
.put("path.home", home)
.build();
return Tuple.tuple(home, TestEnvironment.newEnvironment(settings)); return Tuple.tuple(home, TestEnvironment.newEnvironment(settings));
} }
@ -249,14 +247,23 @@ public class InstallPluginCommandTests extends ESTestCase {
} }
static void writePlugin(String name, Path structure, String... additionalProps) throws IOException { static void writePlugin(String name, Path structure, String... additionalProps) throws IOException {
String[] properties = Stream.concat(Stream.of( String[] properties = Stream.concat(
"description", "fake desc", Stream.of(
"name", name, "description",
"version", "1.0", "fake desc",
"elasticsearch.version", Version.CURRENT.toString(), "name",
"java.version", System.getProperty("java.specification.version"), name,
"classname", "FakePlugin" "version",
), Arrays.stream(additionalProps)).toArray(String[]::new); "1.0",
"elasticsearch.version",
Version.CURRENT.toString(),
"java.version",
System.getProperty("java.specification.version"),
"classname",
"FakePlugin"
),
Arrays.stream(additionalProps)
).toArray(String[]::new);
PluginTestUtil.writePluginProperties(structure, properties); PluginTestUtil.writePluginProperties(structure, properties);
String className = name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1) + "Plugin"; String className = name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1) + "Plugin";
writeJar(structure.resolve("plugin.jar"), className); writeJar(structure.resolve("plugin.jar"), className);
@ -316,7 +323,9 @@ public class InstallPluginCommandTests extends ESTestCase {
PosixFilePermission.GROUP_READ, PosixFilePermission.GROUP_READ,
PosixFilePermission.GROUP_EXECUTE, PosixFilePermission.GROUP_EXECUTE,
PosixFilePermission.OTHERS_READ, PosixFilePermission.OTHERS_READ,
PosixFilePermission.OTHERS_EXECUTE)); PosixFilePermission.OTHERS_EXECUTE
)
);
} }
assertTrue("jar was copied", Files.exists(got.resolve("plugin.jar"))); assertTrue("jar was copied", Files.exists(got.resolve("plugin.jar")));
assertFalse("bin was not copied", Files.exists(got.resolve("bin"))); assertFalse("bin was not copied", Files.exists(got.resolve("bin")));
@ -351,8 +360,8 @@ public class InstallPluginCommandTests extends ESTestCase {
GroupPrincipal group = null; GroupPrincipal group = null;
if (isPosix) { if (isPosix) {
PosixFileAttributes configAttributes = PosixFileAttributes configAttributes = Files.getFileAttributeView(env.configFile(), PosixFileAttributeView.class)
Files.getFileAttributeView(env.configFile(), PosixFileAttributeView.class).readAttributes(); .readAttributes();
user = configAttributes.owner(); user = configAttributes.owner();
group = configAttributes.group(); group = configAttributes.group();
@ -427,7 +436,8 @@ public class InstallPluginCommandTests extends ESTestCase {
String pluginZip = createPluginUrl("fake", pluginDir); String pluginZip = createPluginUrl("fake", pluginDir);
final FileNotFoundException e = expectThrows( final FileNotFoundException e = expectThrows(
FileNotFoundException.class, FileNotFoundException.class,
() -> installPlugins(Arrays.asList(pluginZip, pluginZip + "does-not-exist"), env.v1())); () -> installPlugins(Arrays.asList(pluginZip, pluginZip + "does-not-exist"), env.v1())
);
assertThat(e, hasToString(containsString("does-not-exist"))); assertThat(e, hasToString(containsString("does-not-exist")));
final Path fakeInstallPath = env.v2().pluginsFile().resolve("fake"); final Path fakeInstallPath = env.v2().pluginsFile().resolve("fake");
// fake should have been removed when the file not found exception occurred // fake should have been removed when the file not found exception occurred
@ -443,9 +453,10 @@ public class InstallPluginCommandTests extends ESTestCase {
Files.createDirectory(removing); Files.createDirectory(removing);
final IllegalStateException e = expectThrows(IllegalStateException.class, () -> installPlugin(pluginZip, env.v1())); final IllegalStateException e = expectThrows(IllegalStateException.class, () -> installPlugin(pluginZip, env.v1()));
final String expected = String.format( final String expected = String.format(
Locale.ROOT, Locale.ROOT,
"found file [%s] from a failed attempt to remove the plugin [failed]; execute [elasticsearch-plugin remove failed]", "found file [%s] from a failed attempt to remove the plugin [failed]; execute [elasticsearch-plugin remove failed]",
removing); removing
);
assertThat(e, hasToString(containsString(expected))); assertThat(e, hasToString(containsString(expected)));
} }
@ -471,9 +482,11 @@ public class InstallPluginCommandTests extends ESTestCase {
public void testFileNotMaven() throws Exception { public void testFileNotMaven() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp); Tuple<Path, Environment> env = createEnv(fs, temp);
String dir = randomAlphaOfLength(10) + ":" + randomAlphaOfLength(5) + "\\" + randomAlphaOfLength(5); String dir = randomAlphaOfLength(10) + ":" + randomAlphaOfLength(5) + "\\" + randomAlphaOfLength(5);
Exception e = expectThrows(Exception.class, Exception e = expectThrows(
Exception.class,
// has two colons, so it appears similar to maven coordinates // has two colons, so it appears similar to maven coordinates
() -> installPlugin("file:" + dir, env.v1())); () -> installPlugin("file:" + dir, env.v1())
);
assertFalse(e.getMessage(), e.getMessage().contains("maven.org")); assertFalse(e.getMessage(), e.getMessage().contains("maven.org"));
assertTrue(e.getMessage(), e.getMessage().contains(dir)); assertTrue(e.getMessage(), e.getMessage().contains(dir));
} }
@ -522,8 +535,10 @@ public class InstallPluginCommandTests extends ESTestCase {
Path pluginDirectory = createPluginDir(temp); Path pluginDirectory = createPluginDir(temp);
writeJar(pluginDirectory.resolve("other.jar"), "FakePlugin"); writeJar(pluginDirectory.resolve("other.jar"), "FakePlugin");
String pluginZip = createPluginUrl("fake", pluginDirectory); // adds plugin.jar with FakePlugin String pluginZip = createPluginUrl("fake", pluginDirectory); // adds plugin.jar with FakePlugin
IllegalStateException e = expectThrows(IllegalStateException.class, IllegalStateException e = expectThrows(
() -> installPlugin(pluginZip, environment.v1(), defaultCommand)); IllegalStateException.class,
() -> installPlugin(pluginZip, environment.v1(), defaultCommand)
);
assertTrue(e.getMessage(), e.getMessage().contains("jar hell")); assertTrue(e.getMessage(), e.getMessage().contains("jar hell"));
assertInstallCleaned(environment.v2()); assertInstallCleaned(environment.v2());
} }
@ -587,7 +602,7 @@ public class InstallPluginCommandTests extends ESTestCase {
public void testBinConflict() throws Exception { public void testBinConflict() throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp); Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp); Path pluginDir = createPluginDir(temp);
Path binDir = pluginDir.resolve("bin"); Path binDir = pluginDir.resolve("bin");
Files.createDirectory(binDir); Files.createDirectory(binDir);
Files.createFile(binDir.resolve("somescript")); Files.createFile(binDir.resolve("somescript"));
@ -795,14 +810,15 @@ public class InstallPluginCommandTests extends ESTestCase {
public void testInstallXPack() throws IOException { public void testInstallXPack() throws IOException {
runInstallXPackTest(Build.Flavor.DEFAULT, UserException.class, "this distribution of Elasticsearch contains X-Pack by default"); runInstallXPackTest(Build.Flavor.DEFAULT, UserException.class, "this distribution of Elasticsearch contains X-Pack by default");
runInstallXPackTest( runInstallXPackTest(
Build.Flavor.OSS, Build.Flavor.OSS,
UserException.class, UserException.class,
"X-Pack is not available with the oss distribution; to use X-Pack features use the default distribution"); "X-Pack is not available with the oss distribution; to use X-Pack features use the default distribution"
);
runInstallXPackTest(Build.Flavor.UNKNOWN, IllegalStateException.class, "your distribution is broken"); runInstallXPackTest(Build.Flavor.UNKNOWN, IllegalStateException.class, "your distribution is broken");
} }
private <T extends Exception> void runInstallXPackTest( private <T extends Exception> void runInstallXPackTest(final Build.Flavor flavor, final Class<T> clazz, final String expectedMessage)
final Build.Flavor flavor, final Class<T> clazz, final String expectedMessage) throws IOException { throws IOException {
final InstallPluginCommand flavorCommand = new InstallPluginCommand() { final InstallPluginCommand flavorCommand = new InstallPluginCommand() {
@Override @Override
Build.Flavor buildFlavor() { Build.Flavor buildFlavor() {
@ -811,8 +827,10 @@ public class InstallPluginCommandTests extends ESTestCase {
}; };
final Environment environment = createEnv(fs, temp).v2(); final Environment environment = createEnv(fs, temp).v2();
final T exception = final T exception = expectThrows(
expectThrows(clazz, () -> flavorCommand.execute(terminal, Collections.singletonList("x-pack"), false, environment)); clazz,
() -> flavorCommand.execute(terminal, Collections.singletonList("x-pack"), false, environment)
);
assertThat(exception, hasToString(containsString(expectedMessage))); assertThat(exception, hasToString(containsString(expectedMessage)));
} }
@ -857,12 +875,19 @@ public class InstallPluginCommandTests extends ESTestCase {
Path pluginDir = createPluginDir(temp); Path pluginDir = createPluginDir(temp);
String pluginZip = createPluginUrl("fake", pluginDir); String pluginZip = createPluginUrl("fake", pluginDir);
installPlugin(pluginZip, env.v1()); installPlugin(pluginZip, env.v1());
final UserException e = expectThrows(UserException.class, final UserException e = expectThrows(
() -> installPlugin(pluginZip, env.v1(), randomFrom(skipJarHellCommand, defaultCommand))); UserException.class,
() -> installPlugin(pluginZip, env.v1(), randomFrom(skipJarHellCommand, defaultCommand))
);
assertThat( assertThat(
e.getMessage(), e.getMessage(),
equalTo("plugin directory [" + env.v2().pluginsFile().resolve("fake") + "] already exists; " + equalTo(
"if you need to update the plugin, uninstall it first using command 'remove fake'")); "plugin directory ["
+ env.v2().pluginsFile().resolve("fake")
+ "] already exists; "
+ "if you need to update the plugin, uninstall it first using command 'remove fake'"
)
);
} }
private void installPlugin(MockTerminal terminal, boolean isBatch) throws Exception { private void installPlugin(MockTerminal terminal, boolean isBatch) throws Exception {
@ -877,15 +902,16 @@ public class InstallPluginCommandTests extends ESTestCase {
} }
void assertInstallPluginFromUrl( void assertInstallPluginFromUrl(
final String pluginId, final String pluginId,
final String name, final String name,
final String url, final String url,
final String stagingHash, final String stagingHash,
final boolean isSnapshot, final boolean isSnapshot,
final String shaExtension, final String shaExtension,
final Function<byte[], String> shaCalculator, final Function<byte[], String> shaCalculator,
final PGPSecretKey secretKey, final PGPSecretKey secretKey,
final BiFunction<byte[], PGPSecretKey, String> signature) throws Exception { final BiFunction<byte[], PGPSecretKey, String> signature
) throws Exception {
Tuple<Path, Environment> env = createEnv(fs, temp); Tuple<Path, Environment> env = createEnv(fs, temp);
Path pluginDir = createPluginDir(temp); Path pluginDir = createPluginDir(temp);
Path pluginZip = createPlugin(name, pluginDir); Path pluginZip = createPlugin(name, pluginDir);
@ -897,6 +923,7 @@ public class InstallPluginCommandTests extends ESTestCase {
Files.copy(pluginZip, downloadedPath); Files.copy(pluginZip, downloadedPath);
return downloadedPath; return downloadedPath;
} }
@Override @Override
URL openUrl(String urlString) throws IOException { URL openUrl(String urlString) throws IOException {
if ((url + shaExtension).equals(urlString)) { if ((url + shaExtension).equals(urlString)) {
@ -952,6 +979,7 @@ public class InstallPluginCommandTests extends ESTestCase {
boolean urlExists(Terminal terminal, String urlString) throws IOException { boolean urlExists(Terminal terminal, String urlString) throws IOException {
return urlString.equals(url); return urlString.equals(url);
} }
@Override @Override
String getStagingHash() { String getStagingHash() {
return stagingHash; return stagingHash;
@ -972,66 +1000,99 @@ public class InstallPluginCommandTests extends ESTestCase {
} }
public void assertInstallPluginFromUrl( public void assertInstallPluginFromUrl(
final String pluginId, final String name, final String url, final String stagingHash, boolean isSnapshot) throws Exception { final String pluginId,
final String name,
final String url,
final String stagingHash,
boolean isSnapshot
) throws Exception {
final MessageDigest digest = MessageDigest.getInstance("SHA-512"); final MessageDigest digest = MessageDigest.getInstance("SHA-512");
assertInstallPluginFromUrl( assertInstallPluginFromUrl(
pluginId, name, url, stagingHash, isSnapshot, ".sha512", checksumAndFilename(digest, url), newSecretKey(), this::signature); pluginId,
name,
url,
stagingHash,
isSnapshot,
".sha512",
checksumAndFilename(digest, url),
newSecretKey(),
this::signature
);
} }
public void testOfficialPlugin() throws Exception { public void testOfficialPlugin() throws Exception {
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
Build.CURRENT.getQualifiedVersion() + ".zip"; + Build.CURRENT.getQualifiedVersion()
+ ".zip";
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, false); assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, false);
} }
public void testOfficialPluginSnapshot() throws Exception { public void testOfficialPluginSnapshot() throws Exception {
String url = String.format( String url = String.format(
Locale.ROOT, Locale.ROOT,
"https://snapshots.elastic.co/%s-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-%s.zip", "https://snapshots.elastic.co/%s-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-%s.zip",
Version.CURRENT, Version.CURRENT,
Build.CURRENT.getQualifiedVersion()); Build.CURRENT.getQualifiedVersion()
);
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", true); assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", true);
} }
public void testInstallReleaseBuildOfPluginOnSnapshotBuild() { public void testInstallReleaseBuildOfPluginOnSnapshotBuild() {
String url = String.format( String url = String.format(
Locale.ROOT, Locale.ROOT,
"https://snapshots.elastic.co/%s-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-%s.zip", "https://snapshots.elastic.co/%s-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-%s.zip",
Version.CURRENT, Version.CURRENT,
Build.CURRENT.getQualifiedVersion()); Build.CURRENT.getQualifiedVersion()
);
// attemping to install a release build of a plugin (no staging ID) on a snapshot build should throw a user exception // attemping to install a release build of a plugin (no staging ID) on a snapshot build should throw a user exception
final UserException e = final UserException e = expectThrows(
expectThrows(UserException.class, () -> assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, true)); UserException.class,
() -> assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, true)
);
assertThat(e.exitCode, equalTo(ExitCodes.CONFIG)); assertThat(e.exitCode, equalTo(ExitCodes.CONFIG));
assertThat( assertThat(
e, hasToString(containsString("attempted to install release build of official plugin on snapshot build of Elasticsearch"))); e,
hasToString(containsString("attempted to install release build of official plugin on snapshot build of Elasticsearch"))
);
} }
public void testOfficialPluginStaging() throws Exception { public void testOfficialPluginStaging() throws Exception {
String url = "https://staging.elastic.co/" + Version.CURRENT + "-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" String url = "https://staging.elastic.co/"
+ Build.CURRENT.getQualifiedVersion() + ".zip"; + Version.CURRENT
+ "-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
+ Build.CURRENT.getQualifiedVersion()
+ ".zip";
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", false); assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", false);
} }
public void testOfficialPlatformPlugin() throws Exception { public void testOfficialPlatformPlugin() throws Exception {
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + Platforms.PLATFORM_NAME + String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
"-" + Build.CURRENT.getQualifiedVersion() + ".zip"; + Platforms.PLATFORM_NAME
+ "-"
+ Build.CURRENT.getQualifiedVersion()
+ ".zip";
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, false); assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, false);
} }
public void testOfficialPlatformPluginSnapshot() throws Exception { public void testOfficialPlatformPluginSnapshot() throws Exception {
String url = String.format( String url = String.format(
Locale.ROOT, Locale.ROOT,
"https://snapshots.elastic.co/%s-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-%s-%s.zip", "https://snapshots.elastic.co/%s-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-%s-%s.zip",
Version.CURRENT, Version.CURRENT,
Platforms.PLATFORM_NAME, Platforms.PLATFORM_NAME,
Build.CURRENT.getQualifiedVersion()); Build.CURRENT.getQualifiedVersion()
);
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", true); assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", true);
} }
public void testOfficialPlatformPluginStaging() throws Exception { public void testOfficialPlatformPluginStaging() throws Exception {
String url = "https://staging.elastic.co/" + Version.CURRENT + "-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" String url = "https://staging.elastic.co/"
+ Platforms.PLATFORM_NAME + "-"+ Build.CURRENT.getQualifiedVersion() + ".zip"; + Version.CURRENT
+ "-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
+ Platforms.PLATFORM_NAME
+ "-"
+ Build.CURRENT.getQualifiedVersion()
+ ".zip";
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", false); assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", false);
} }
@ -1053,12 +1114,23 @@ public class InstallPluginCommandTests extends ESTestCase {
} }
public void testOfficialShaMissing() throws Exception { public void testOfficialShaMissing() throws Exception {
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
Build.CURRENT.getQualifiedVersion() + ".zip"; + Build.CURRENT.getQualifiedVersion()
+ ".zip";
MessageDigest digest = MessageDigest.getInstance("SHA-1"); MessageDigest digest = MessageDigest.getInstance("SHA-1");
UserException e = expectThrows(UserException.class, () -> UserException e = expectThrows(
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, false, UserException.class,
".sha1", checksum(digest), null, (b, p) -> null) () -> assertInstallPluginFromUrl(
"analysis-icu",
"analysis-icu",
url,
null,
false,
".sha1",
checksum(digest),
null,
(b, p) -> null
)
); );
assertEquals(ExitCodes.IO_ERROR, e.exitCode); assertEquals(ExitCodes.IO_ERROR, e.exitCode);
assertEquals("Plugin checksum missing: " + url + ".sha512", e.getMessage()); assertEquals("Plugin checksum missing: " + url + ".sha512", e.getMessage());
@ -1066,94 +1138,142 @@ public class InstallPluginCommandTests extends ESTestCase {
public void testMavenShaMissing() throws Exception { public void testMavenShaMissing() throws Exception {
String url = "https://repo1.maven.org/maven2/mygroup/myplugin/1.0.0/myplugin-1.0.0.zip"; String url = "https://repo1.maven.org/maven2/mygroup/myplugin/1.0.0/myplugin-1.0.0.zip";
UserException e = expectThrows(UserException.class, () -> UserException e = expectThrows(
assertInstallPluginFromUrl( UserException.class,
"mygroup:myplugin:1.0.0", "myplugin", url, null, false, ".dne", bytes -> null, null, (b, p) -> null)); () -> assertInstallPluginFromUrl(
"mygroup:myplugin:1.0.0",
"myplugin",
url,
null,
false,
".dne",
bytes -> null,
null,
(b, p) -> null
)
);
assertEquals(ExitCodes.IO_ERROR, e.exitCode); assertEquals(ExitCodes.IO_ERROR, e.exitCode);
assertEquals("Plugin checksum missing: " + url + ".sha1", e.getMessage()); assertEquals("Plugin checksum missing: " + url + ".sha1", e.getMessage());
} }
public void testInvalidShaFileMissingFilename() throws Exception { public void testInvalidShaFileMissingFilename() throws Exception {
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
Build.CURRENT.getQualifiedVersion() + ".zip"; + Build.CURRENT.getQualifiedVersion()
+ ".zip";
MessageDigest digest = MessageDigest.getInstance("SHA-512"); MessageDigest digest = MessageDigest.getInstance("SHA-512");
UserException e = expectThrows(UserException.class, UserException e = expectThrows(
() -> assertInstallPluginFromUrl( UserException.class,
"analysis-icu", "analysis-icu", url, null, false, ".sha512", checksum(digest), null, (b, p) -> null)); () -> assertInstallPluginFromUrl(
"analysis-icu",
"analysis-icu",
url,
null,
false,
".sha512",
checksum(digest),
null,
(b, p) -> null
)
);
assertEquals(ExitCodes.IO_ERROR, e.exitCode); assertEquals(ExitCodes.IO_ERROR, e.exitCode);
assertTrue(e.getMessage(), e.getMessage().startsWith("Invalid checksum file")); assertTrue(e.getMessage(), e.getMessage().startsWith("Invalid checksum file"));
} }
public void testInvalidShaFileMismatchFilename() throws Exception { public void testInvalidShaFileMismatchFilename() throws Exception {
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
Build.CURRENT.getQualifiedVersion()+ ".zip"; + Build.CURRENT.getQualifiedVersion()
+ ".zip";
MessageDigest digest = MessageDigest.getInstance("SHA-512"); MessageDigest digest = MessageDigest.getInstance("SHA-512");
UserException e = expectThrows(UserException.class, () -> UserException e = expectThrows(
assertInstallPluginFromUrl( UserException.class,
"analysis-icu", () -> assertInstallPluginFromUrl(
"analysis-icu", "analysis-icu",
url, "analysis-icu",
null, url,
false, null,
".sha512", false,
checksumAndString(digest, " repository-s3-" + Build.CURRENT.getQualifiedVersion() + ".zip"), ".sha512",
null, checksumAndString(digest, " repository-s3-" + Build.CURRENT.getQualifiedVersion() + ".zip"),
(b, p) -> null)); null,
(b, p) -> null
)
);
assertEquals(ExitCodes.IO_ERROR, e.exitCode); assertEquals(ExitCodes.IO_ERROR, e.exitCode);
assertThat(e, hasToString(matches("checksum file at \\[.*\\] is not for this plugin"))); assertThat(e, hasToString(matches("checksum file at \\[.*\\] is not for this plugin")));
} }
public void testInvalidShaFileContainingExtraLine() throws Exception { public void testInvalidShaFileContainingExtraLine() throws Exception {
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
Build.CURRENT.getQualifiedVersion() + ".zip"; + Build.CURRENT.getQualifiedVersion()
+ ".zip";
MessageDigest digest = MessageDigest.getInstance("SHA-512"); MessageDigest digest = MessageDigest.getInstance("SHA-512");
UserException e = expectThrows(UserException.class, () -> UserException e = expectThrows(
assertInstallPluginFromUrl( UserException.class,
"analysis-icu", () -> assertInstallPluginFromUrl(
"analysis-icu", "analysis-icu",
url, "analysis-icu",
null, url,
false, null,
".sha512", false,
checksumAndString(digest, " analysis-icu-" + Build.CURRENT.getQualifiedVersion() + ".zip\nfoobar"), ".sha512",
null, checksumAndString(digest, " analysis-icu-" + Build.CURRENT.getQualifiedVersion() + ".zip\nfoobar"),
(b, p) -> null)); null,
(b, p) -> null
)
);
assertEquals(ExitCodes.IO_ERROR, e.exitCode); assertEquals(ExitCodes.IO_ERROR, e.exitCode);
assertTrue(e.getMessage(), e.getMessage().startsWith("Invalid checksum file")); assertTrue(e.getMessage(), e.getMessage().startsWith("Invalid checksum file"));
} }
public void testSha512Mismatch() throws Exception { public void testSha512Mismatch() throws Exception {
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
Build.CURRENT.getQualifiedVersion() + ".zip"; + Build.CURRENT.getQualifiedVersion()
UserException e = expectThrows(UserException.class, () -> + ".zip";
assertInstallPluginFromUrl( UserException e = expectThrows(
"analysis-icu", UserException.class,
"analysis-icu", () -> assertInstallPluginFromUrl(
url, "analysis-icu",
null, "analysis-icu",
false, url,
".sha512", null,
bytes -> "foobar analysis-icu-" + Build.CURRENT.getQualifiedVersion() + ".zip", false,
null, ".sha512",
(b, p) -> null)); bytes -> "foobar analysis-icu-" + Build.CURRENT.getQualifiedVersion() + ".zip",
null,
(b, p) -> null
)
);
assertEquals(ExitCodes.IO_ERROR, e.exitCode); assertEquals(ExitCodes.IO_ERROR, e.exitCode);
assertTrue(e.getMessage(), e.getMessage().contains("SHA-512 mismatch, expected foobar")); assertTrue(e.getMessage(), e.getMessage().contains("SHA-512 mismatch, expected foobar"));
} }
public void testSha1Mismatch() throws Exception { public void testSha1Mismatch() throws Exception {
String url = "https://repo1.maven.org/maven2/mygroup/myplugin/1.0.0/myplugin-1.0.0.zip"; String url = "https://repo1.maven.org/maven2/mygroup/myplugin/1.0.0/myplugin-1.0.0.zip";
UserException e = expectThrows(UserException.class, () -> UserException e = expectThrows(
assertInstallPluginFromUrl( UserException.class,
"mygroup:myplugin:1.0.0", "myplugin", url, null, false, ".sha1", bytes -> "foobar", null, (b, p) -> null)); () -> assertInstallPluginFromUrl(
"mygroup:myplugin:1.0.0",
"myplugin",
url,
null,
false,
".sha1",
bytes -> "foobar",
null,
(b, p) -> null
)
);
assertEquals(ExitCodes.IO_ERROR, e.exitCode); assertEquals(ExitCodes.IO_ERROR, e.exitCode);
assertTrue(e.getMessage(), e.getMessage().contains("SHA-1 mismatch, expected foobar")); assertTrue(e.getMessage(), e.getMessage().contains("SHA-1 mismatch, expected foobar"));
} }
public void testPublicKeyIdMismatchToExpectedPublicKeyId() throws Exception { public void testPublicKeyIdMismatchToExpectedPublicKeyId() throws Exception {
final String icu = "analysis-icu"; final String icu = "analysis-icu";
final String url = final String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/"
"https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/" + icu + "-" + + icu
Build.CURRENT.getQualifiedVersion() + ".zip"; + "-"
+ Build.CURRENT.getQualifiedVersion()
+ ".zip";
final MessageDigest digest = MessageDigest.getInstance("SHA-512"); final MessageDigest digest = MessageDigest.getInstance("SHA-512");
/* /*
* To setup a situation where the expected public key ID does not match the public key ID used for signing, we generate a new public * To setup a situation where the expected public key ID does not match the public key ID used for signing, we generate a new public
@ -1166,18 +1286,29 @@ public class InstallPluginCommandTests extends ESTestCase {
final PGPSecretKey verifyingKey = newSecretKey(); // the expected key used for signing final PGPSecretKey verifyingKey = newSecretKey(); // the expected key used for signing
final String expectedID = Long.toHexString(verifyingKey.getKeyID()).toUpperCase(Locale.ROOT); final String expectedID = Long.toHexString(verifyingKey.getKeyID()).toUpperCase(Locale.ROOT);
final IllegalStateException e = expectThrows( final IllegalStateException e = expectThrows(
IllegalStateException.class, IllegalStateException.class,
() -> () -> assertInstallPluginFromUrl(
assertInstallPluginFromUrl( icu,
icu, icu, url, null, false, ".sha512", checksumAndFilename(digest, url), verifyingKey, signature)); icu,
url,
null,
false,
".sha512",
checksumAndFilename(digest, url),
verifyingKey,
signature
)
);
assertThat(e, hasToString(containsString("key id [" + actualID + "] does not match expected key id [" + expectedID + "]"))); assertThat(e, hasToString(containsString("key id [" + actualID + "] does not match expected key id [" + expectedID + "]")));
} }
public void testFailedSignatureVerification() throws Exception { public void testFailedSignatureVerification() throws Exception {
final String icu = "analysis-icu"; final String icu = "analysis-icu";
final String url = final String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/"
"https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/" + icu + "-" + + icu
Build.CURRENT.getQualifiedVersion() + ".zip"; + "-"
+ Build.CURRENT.getQualifiedVersion()
+ ".zip";
final MessageDigest digest = MessageDigest.getInstance("SHA-512"); final MessageDigest digest = MessageDigest.getInstance("SHA-512");
/* /*
* To setup a situation where signature verification fails, we will mutate the input byte array by modifying a single byte to some * To setup a situation where signature verification fails, we will mutate the input byte array by modifying a single byte to some
@ -1190,10 +1321,19 @@ public class InstallPluginCommandTests extends ESTestCase {
return signature(bytes, p); return signature(bytes, p);
}; };
final IllegalStateException e = expectThrows( final IllegalStateException e = expectThrows(
IllegalStateException.class, IllegalStateException.class,
() -> () -> assertInstallPluginFromUrl(
assertInstallPluginFromUrl( icu,
icu, icu, url, null, false, ".sha512", checksumAndFilename(digest, url), newSecretKey(), signature)); icu,
url,
null,
false,
".sha512",
checksumAndFilename(digest, url),
newSecretKey(),
signature
)
);
assertThat(e, hasToString(equalTo("java.lang.IllegalStateException: signature verification for [" + url + "] failed"))); assertThat(e, hasToString(equalTo("java.lang.IllegalStateException: signature verification for [" + url + "] failed")));
} }
@ -1204,16 +1344,16 @@ public class InstallPluginCommandTests extends ESTestCase {
final PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(HashAlgorithmTags.SHA1); final PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(HashAlgorithmTags.SHA1);
final PGPKeyPair pkp = new JcaPGPKeyPair(PGPPublicKey.RSA_GENERAL, pair, new Date()); final PGPKeyPair pkp = new JcaPGPKeyPair(PGPPublicKey.RSA_GENERAL, pair, new Date());
return new PGPSecretKey( return new PGPSecretKey(
PGPSignature.DEFAULT_CERTIFICATION, PGPSignature.DEFAULT_CERTIFICATION,
pkp, pkp,
"example@example.com", "example@example.com",
sha1Calc, sha1Calc,
null, null,
null, null,
new JcaPGPContentSignerBuilder(pkp.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA256), new JcaPGPContentSignerBuilder(pkp.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA256),
new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_192, sha1Calc) new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_192, sha1Calc).setProvider(new BouncyCastleFipsProvider())
.setProvider(new BouncyCastleFipsProvider()) .build("passphrase".toCharArray())
.build("passphrase".toCharArray())); );
} }
private Function<byte[], String> checksum(final MessageDigest digest) { private Function<byte[], String> checksum(final MessageDigest digest) {
@ -1231,17 +1371,18 @@ public class InstallPluginCommandTests extends ESTestCase {
private String signature(final byte[] bytes, final PGPSecretKey secretKey) { private String signature(final byte[] bytes, final PGPSecretKey secretKey) {
try { try {
final PGPPrivateKey privateKey final PGPPrivateKey privateKey = secretKey.extractPrivateKey(
= secretKey.extractPrivateKey( new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder().build()).build("passphrase".toCharArray())
new JcePBESecretKeyDecryptorBuilder( );
new JcaPGPDigestCalculatorProviderBuilder().build()).build("passphrase".toCharArray())); final PGPSignatureGenerator generator = new PGPSignatureGenerator(
final PGPSignatureGenerator generator = new JcaPGPContentSignerBuilder(privateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512)
new PGPSignatureGenerator( );
new JcaPGPContentSignerBuilder(privateKey.getPublicKeyPacket().getAlgorithm(), HashAlgorithmTags.SHA512));
generator.init(PGPSignature.BINARY_DOCUMENT, privateKey); generator.init(PGPSignature.BINARY_DOCUMENT, privateKey);
final ByteArrayOutputStream output = new ByteArrayOutputStream(); final ByteArrayOutputStream output = new ByteArrayOutputStream();
try (BCPGOutputStream pout = new BCPGOutputStream(new ArmoredOutputStream(output)); try (
InputStream is = new ByteArrayInputStream(bytes)) { BCPGOutputStream pout = new BCPGOutputStream(new ArmoredOutputStream(output));
InputStream is = new ByteArrayInputStream(bytes)
) {
final byte[] buffer = new byte[1024]; final byte[] buffer = new byte[1024];
int read; int read;
while ((read = is.read(buffer)) != -1) { while ((read = is.read(buffer)) != -1) {

View File

@ -19,7 +19,6 @@
package org.elasticsearch.plugins; package org.elasticsearch.plugins;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
@ -50,9 +49,7 @@ public class ListPluginsCommandTests extends ESTestCase {
super.setUp(); super.setUp();
home = createTempDir(); home = createTempDir();
Files.createDirectories(home.resolve("plugins")); Files.createDirectories(home.resolve("plugins"));
Settings settings = Settings.builder() Settings settings = Settings.builder().put("path.home", home).build();
.put("path.home", home)
.build();
env = TestEnvironment.newEnvironment(settings); env = TestEnvironment.newEnvironment(settings);
} }
@ -69,7 +66,7 @@ public class ListPluginsCommandTests extends ESTestCase {
@Override @Override
protected Environment createEnv(Map<String, String> settings) throws UserException { protected Environment createEnv(Map<String, String> settings) throws UserException {
Settings.Builder builder = Settings.builder().put("path.home", home); Settings.Builder builder = Settings.builder().put("path.home", home);
settings.forEach((k,v) -> builder.put(k, v)); settings.forEach((k, v) -> builder.put(k, v));
final Settings realSettings = builder.build(); final Settings realSettings = builder.build();
return new Environment(realSettings, home.resolve("config")); return new Environment(realSettings, home.resolve("config"));
} }
@ -83,33 +80,39 @@ public class ListPluginsCommandTests extends ESTestCase {
return terminal; return terminal;
} }
private static String buildMultiline(String... args){ private static String buildMultiline(String... args) {
return Arrays.stream(args).collect(Collectors.joining("\n", "", "\n")); return Arrays.stream(args).collect(Collectors.joining("\n", "", "\n"));
} }
private static void buildFakePlugin( private static void buildFakePlugin(final Environment env, final String description, final String name, final String classname)
final Environment env, throws IOException {
final String description,
final String name,
final String classname) throws IOException {
buildFakePlugin(env, description, name, classname, false); buildFakePlugin(env, description, name, classname, false);
} }
private static void buildFakePlugin( private static void buildFakePlugin(
final Environment env, final Environment env,
final String description, final String description,
final String name, final String name,
final String classname, final String classname,
final boolean hasNativeController) throws IOException { final boolean hasNativeController
) throws IOException {
PluginTestUtil.writePluginProperties( PluginTestUtil.writePluginProperties(
env.pluginsFile().resolve(name), env.pluginsFile().resolve(name),
"description", description, "description",
"name", name, description,
"version", "1.0", "name",
"elasticsearch.version", Version.CURRENT.toString(), name,
"java.version", "1.8", "version",
"classname", classname, "1.0",
"has.native.controller", Boolean.toString(hasNativeController)); "elasticsearch.version",
Version.CURRENT.toString(),
"java.version",
"1.8",
"classname",
classname,
"has.native.controller",
Boolean.toString(hasNativeController)
);
} }
public void testPluginsDirMissing() throws Exception { public void testPluginsDirMissing() throws Exception {
@ -141,19 +144,21 @@ public class ListPluginsCommandTests extends ESTestCase {
String[] params = { "-v" }; String[] params = { "-v" };
MockTerminal terminal = listPlugins(home, params); MockTerminal terminal = listPlugins(home, params);
assertEquals( assertEquals(
buildMultiline( buildMultiline(
"Plugins directory: " + env.pluginsFile(), "Plugins directory: " + env.pluginsFile(),
"fake_plugin", "fake_plugin",
"- Plugin information:", "- Plugin information:",
"Name: fake_plugin", "Name: fake_plugin",
"Description: fake desc", "Description: fake desc",
"Version: 1.0", "Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(), "Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8", "Java Version: 1.8",
"Native Controller: false", "Native Controller: false",
"Extended Plugins: []", "Extended Plugins: []",
" * Classname: org.fake"), " * Classname: org.fake"
terminal.getOutput()); ),
terminal.getOutput()
);
} }
public void testPluginWithNativeController() throws Exception { public void testPluginWithNativeController() throws Exception {
@ -172,8 +177,10 @@ public class ListPluginsCommandTests extends ESTestCase {
"Java Version: 1.8", "Java Version: 1.8",
"Native Controller: true", "Native Controller: true",
"Extended Plugins: []", "Extended Plugins: []",
" * Classname: org.fake"), " * Classname: org.fake"
terminal.getOutput()); ),
terminal.getOutput()
);
} }
public void testPluginWithVerboseMultiplePlugins() throws Exception { public void testPluginWithVerboseMultiplePlugins() throws Exception {
@ -182,29 +189,31 @@ public class ListPluginsCommandTests extends ESTestCase {
String[] params = { "-v" }; String[] params = { "-v" };
MockTerminal terminal = listPlugins(home, params); MockTerminal terminal = listPlugins(home, params);
assertEquals( assertEquals(
buildMultiline( buildMultiline(
"Plugins directory: " + env.pluginsFile(), "Plugins directory: " + env.pluginsFile(),
"fake_plugin1", "fake_plugin1",
"- Plugin information:", "- Plugin information:",
"Name: fake_plugin1", "Name: fake_plugin1",
"Description: fake desc 1", "Description: fake desc 1",
"Version: 1.0", "Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(), "Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8", "Java Version: 1.8",
"Native Controller: false", "Native Controller: false",
"Extended Plugins: []", "Extended Plugins: []",
" * Classname: org.fake", " * Classname: org.fake",
"fake_plugin2", "fake_plugin2",
"- Plugin information:", "- Plugin information:",
"Name: fake_plugin2", "Name: fake_plugin2",
"Description: fake desc 2", "Description: fake desc 2",
"Version: 1.0", "Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(), "Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8", "Java Version: 1.8",
"Native Controller: false", "Native Controller: false",
"Extended Plugins: []", "Extended Plugins: []",
" * Classname: org.fake2"), " * Classname: org.fake2"
terminal.getOutput()); ),
terminal.getOutput()
);
} }
public void testPluginWithoutVerboseMultiplePlugins() throws Exception { public void testPluginWithoutVerboseMultiplePlugins() throws Exception {
@ -215,45 +224,45 @@ public class ListPluginsCommandTests extends ESTestCase {
assertEquals(buildMultiline("fake_plugin1", "fake_plugin2"), output); assertEquals(buildMultiline("fake_plugin1", "fake_plugin2"), output);
} }
public void testPluginWithoutDescriptorFile() throws Exception{ public void testPluginWithoutDescriptorFile() throws Exception {
final Path pluginDir = env.pluginsFile().resolve("fake1"); final Path pluginDir = env.pluginsFile().resolve("fake1");
Files.createDirectories(pluginDir); Files.createDirectories(pluginDir);
NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> listPlugins(home)); NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> listPlugins(home));
assertEquals(pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES).toString(), e.getFile()); assertEquals(pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES).toString(), e.getFile());
} }
public void testPluginWithWrongDescriptorFile() throws Exception{ public void testPluginWithWrongDescriptorFile() throws Exception {
final Path pluginDir = env.pluginsFile().resolve("fake1"); final Path pluginDir = env.pluginsFile().resolve("fake1");
PluginTestUtil.writePluginProperties(pluginDir, "description", "fake desc"); PluginTestUtil.writePluginProperties(pluginDir, "description", "fake desc");
IllegalArgumentException e = expectThrows( IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> listPlugins(home));
IllegalArgumentException.class,
() -> listPlugins(home));
final Path descriptorPath = pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES); final Path descriptorPath = pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES);
assertEquals( assertEquals("property [name] is missing in [" + descriptorPath.toString() + "]", e.getMessage());
"property [name] is missing in [" + descriptorPath.toString() + "]",
e.getMessage());
} }
public void testExistingIncompatiblePlugin() throws Exception { public void testExistingIncompatiblePlugin() throws Exception {
PluginTestUtil.writePluginProperties(env.pluginsFile().resolve("fake_plugin1"), PluginTestUtil.writePluginProperties(
"description", "fake desc 1", env.pluginsFile().resolve("fake_plugin1"),
"name", "fake_plugin1", "description",
"version", "1.0", "fake desc 1",
"elasticsearch.version", Version.fromString("1.0.0").toString(), "name",
"java.version", System.getProperty("java.specification.version"), "fake_plugin1",
"classname", "org.fake1"); "version",
"1.0",
"elasticsearch.version",
Version.fromString("1.0.0").toString(),
"java.version",
System.getProperty("java.specification.version"),
"classname",
"org.fake1"
);
buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2"); buildFakePlugin(env, "fake desc 2", "fake_plugin2", "org.fake2");
MockTerminal terminal = listPlugins(home); MockTerminal terminal = listPlugins(home);
String message = "plugin [fake_plugin1] was built for Elasticsearch version 1.0 but version " + Version.CURRENT + " is required"; String message = "plugin [fake_plugin1] was built for Elasticsearch version 1.0 but version " + Version.CURRENT + " is required";
assertEquals( assertEquals("fake_plugin1\nfake_plugin2\n", terminal.getOutput());
"fake_plugin1\nfake_plugin2\n", assertEquals("WARNING: " + message + "\n", terminal.getErrorOutput());
terminal.getOutput());
assertEquals(
"WARNING: " + message + "\n",
terminal.getErrorOutput());
String[] params = {"-s"}; String[] params = { "-s" };
terminal = listPlugins(home, params); terminal = listPlugins(home, params);
assertEquals("fake_plugin1\nfake_plugin2\n", terminal.getOutput()); assertEquals("fake_plugin1\nfake_plugin2\n", terminal.getOutput());
} }

View File

@ -113,4 +113,4 @@ public class ProgressInputStreamTests extends ESTestCase {
} }
}; };
} }
} }

View File

@ -73,9 +73,7 @@ public class RemovePluginCommandTests extends ESTestCase {
Files.createDirectories(home.resolve("bin")); Files.createDirectories(home.resolve("bin"));
Files.createFile(home.resolve("bin").resolve("elasticsearch")); Files.createFile(home.resolve("bin").resolve("elasticsearch"));
Files.createDirectories(home.resolve("plugins")); Files.createDirectories(home.resolve("plugins"));
Settings settings = Settings.builder() Settings settings = Settings.builder().put("path.home", home).build();
.put("path.home", home)
.build();
env = TestEnvironment.newEnvironment(settings); env = TestEnvironment.newEnvironment(settings);
} }
@ -93,13 +91,20 @@ public class RemovePluginCommandTests extends ESTestCase {
void createPlugin(Path path, String name, Version version) throws IOException { void createPlugin(Path path, String name, Version version) throws IOException {
PluginTestUtil.writePluginProperties( PluginTestUtil.writePluginProperties(
path.resolve(name), path.resolve(name),
"description", "dummy", "description",
"name", name, "dummy",
"version", "1.0", "name",
"elasticsearch.version", version.toString(), name,
"java.version", System.getProperty("java.specification.version"), "version",
"classname", "SomeClass"); "1.0",
"elasticsearch.version",
version.toString(),
"java.version",
System.getProperty("java.specification.version"),
"classname",
"SomeClass"
);
} }
static MockTerminal removePlugin(String name, Path home, boolean purge) throws Exception { static MockTerminal removePlugin(String name, Path home, boolean purge) throws Exception {
@ -138,11 +143,13 @@ public class RemovePluginCommandTests extends ESTestCase {
public void testRemoveOldVersion() throws Exception { public void testRemoveOldVersion() throws Exception {
createPlugin( createPlugin(
"fake", "fake",
VersionUtils.randomVersionBetween( VersionUtils.randomVersionBetween(
random(), random(),
Version.CURRENT.minimumIndexCompatibilityVersion(), Version.CURRENT.minimumIndexCompatibilityVersion(),
VersionUtils.getPreviousVersion())); VersionUtils.getPreviousVersion()
)
);
removePlugin("fake", home, randomBoolean()); removePlugin("fake", home, randomBoolean());
assertThat(Files.exists(env.pluginsFile().resolve("fake")), equalTo(false)); assertThat(Files.exists(env.pluginsFile().resolve("fake")), equalTo(false));
assertRemoveCleaned(env); assertRemoveCleaned(env);
@ -237,12 +244,15 @@ public class RemovePluginCommandTests extends ESTestCase {
return false; return false;
} }
}.main(new String[] { "-Epath.home=" + home, "fake" }, terminal); }.main(new String[] { "-Epath.home=" + home, "fake" }, terminal);
try (BufferedReader reader = new BufferedReader(new StringReader(terminal.getOutput())); try (
BufferedReader errorReader = new BufferedReader(new StringReader(terminal.getErrorOutput())) BufferedReader reader = new BufferedReader(new StringReader(terminal.getOutput()));
BufferedReader errorReader = new BufferedReader(new StringReader(terminal.getErrorOutput()))
) { ) {
assertEquals("-> removing [fake]...", reader.readLine()); assertEquals("-> removing [fake]...", reader.readLine());
assertEquals("ERROR: plugin [fake] not found; run 'elasticsearch-plugin list' to get list of installed plugins", assertEquals(
errorReader.readLine()); "ERROR: plugin [fake] not found; run 'elasticsearch-plugin list' to get list of installed plugins",
errorReader.readLine()
);
assertNull(reader.readLine()); assertNull(reader.readLine());
assertNull(errorReader.readLine()); assertNull(errorReader.readLine());
} }
@ -266,4 +276,3 @@ public class RemovePluginCommandTests extends ESTestCase {
} }
} }