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.
def projectPathsToFormat = [
':build-tools',
':distribution:tools:java-version-checker',
':distribution:tools:launchers',
':distribution:tools:plugin-cli',
':x-pack:plugin:autoscaling',
':x-pack:plugin:enrich'
]

View File

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

View File

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

View File

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

View File

@ -28,42 +28,45 @@ import java.util.List;
final class SystemJvmOptions {
static List<String> systemJvmOptions() {
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.
*/
"-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.
*/
"-Des.networkaddress.cache.negative.ttl=10",
// pre-touch JVM emory pages during initialization
"-XX:+AlwaysPreTouch",
// explicitly set the stack size
"-Xss1m",
// set to headless, just in case,
"-Djava.awt.headless=true",
// ensure UTF-8 encoding by default (e.g., filenames)
"-Dfile.encoding=UTF-8",
// 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.
*/
"-XX:-OmitStackTraceInFastThrow",
// flags to configure Netty
"-Dio.netty.noUnsafe=true",
"-Dio.netty.noKeySetOptimization=true",
"-Dio.netty.recycler.maxCapacityPerThread=0",
"-Dio.netty.allocator.numDirectArenas=0",
// log4j 2
"-Dlog4j.shutdownHookEnabled=false",
"-Dlog4j2.disable.jmx=true",
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.
*/
"-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.
*/
"-Des.networkaddress.cache.negative.ttl=10",
// pre-touch JVM emory pages during initialization
"-XX:+AlwaysPreTouch",
// explicitly set the stack size
"-Xss1m",
// set to headless, just in case,
"-Djava.awt.headless=true",
// ensure UTF-8 encoding by default (e.g., filenames)
"-Dfile.encoding=UTF-8",
// 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.
*/
"-XX:-OmitStackTraceInFastThrow",
// flags to configure Netty
"-Dio.netty.noUnsafe=true",
"-Dio.netty.noKeySetOptimization=true",
"-Dio.netty.recycler.maxCapacityPerThread=0",
"-Dio.netty.allocator.numDirectArenas=0",
// log4j 2
"-Dlog4j.shutdownHookEnabled=false",
"-Dlog4j2.disable.jmx=true",
javaLocaleProviders()));
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
* 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";
} else {
return "-Djava.locale.providers=SPI,COMPAT";

View File

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

View File

@ -43,13 +43,13 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
public void testSubstitution() {
final List<String> jvmOptions = JvmOptionsParser.substitutePlaceholders(
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"));
}
public void testUnversionedOptions() throws IOException {
try (StringReader sr = new StringReader("-Xms1g\n-Xmx1g");
BufferedReader br = new BufferedReader(sr)) {
try (StringReader sr = new StringReader("-Xms1g\n-Xmx1g"); BufferedReader br = new BufferedReader(sr)) {
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 smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion);
final int largerJavaMajorVersion = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
try (StringReader sr = new StringReader(
try (
StringReader sr = new StringReader(
String.format(
Locale.ROOT,
"-Xms1g\n%d:-Xmx1g\n%d:-XX:+UseG1GC\n%d:-Xlog:gc",
javaMajorVersion,
smallerJavaMajorVersion,
largerJavaMajorVersion));
BufferedReader br = new BufferedReader(sr)) {
Locale.ROOT,
"-Xms1g\n%d:-Xmx1g\n%d:-XX:+UseG1GC\n%d:-Xlog:gc",
javaMajorVersion,
smallerJavaMajorVersion,
largerJavaMajorVersion
)
);
BufferedReader br = new BufferedReader(sr)
) {
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 smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion);
final int largerJavaMajorVersion = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
try (StringReader sr = new StringReader(
try (
StringReader sr = new StringReader(
String.format(
Locale.ROOT,
"-Xms1g\n%d-:-Xmx1g\n%d-:-XX:+UseG1GC\n%d-:-Xlog:gc",
javaMajorVersion,
smallerJavaMajorVersion,
largerJavaMajorVersion));
BufferedReader br = new BufferedReader(sr)) {
Locale.ROOT,
"-Xms1g\n%d-:-Xmx1g\n%d-:-XX:+UseG1GC\n%d-:-Xlog:gc",
javaMajorVersion,
smallerJavaMajorVersion,
largerJavaMajorVersion
)
);
BufferedReader br = new BufferedReader(sr)
) {
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 largerJavaMajorVersionLowerBound = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
final int largerJavaMajorVersionUpperBound = randomIntBetween(largerJavaMajorVersionLowerBound, Integer.MAX_VALUE);
try (StringReader sr = new StringReader(
try (
StringReader sr = new StringReader(
String.format(
Locale.ROOT,
"-Xms1g\n%d-%d:-Xmx1g\n%d-%d:-XX:+UseG1GC\n%d-%d:-Xlog:gc",
javaMajorVersion,
javaMajorVersionUpperBound,
smallerJavaMajorVersionLowerBound,
smallerJavaMajorVersionUpperBound,
largerJavaMajorVersionLowerBound,
largerJavaMajorVersionUpperBound));
BufferedReader br = new BufferedReader(sr)) {
Locale.ROOT,
"-Xms1g\n%d-%d:-Xmx1g\n%d-%d:-XX:+UseG1GC\n%d-%d:-Xlog:gc",
javaMajorVersion,
javaMajorVersionUpperBound,
smallerJavaMajorVersionLowerBound,
smallerJavaMajorVersionUpperBound,
largerJavaMajorVersionLowerBound,
largerJavaMajorVersionUpperBound
)
);
BufferedReader br = new BufferedReader(sr)
) {
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g"));
}
}
@ -116,91 +128,86 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
final int smallerJavaMajorVersionUpperBound = randomIntBetween(smallerJavaMajorVersionLowerBound, javaMajorVersion);
final int largerJavaMajorVersionLowerBound = randomIntBetween(javaMajorVersion + 1, Integer.MAX_VALUE);
final int largerJavaMajorVersionUpperBound = randomIntBetween(largerJavaMajorVersionLowerBound, Integer.MAX_VALUE);
try (StringReader sr = new StringReader(
try (
StringReader sr = new StringReader(
String.format(
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",
javaMajorVersion,
javaMajorVersion,
javaMajorVersion,
javaMajorVersionUpperBound,
smallerJavaMajorVersionLowerBound,
smallerJavaMajorVersionUpperBound,
largerJavaMajorVersionLowerBound,
largerJavaMajorVersionUpperBound));
BufferedReader br = new BufferedReader(sr)) {
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",
javaMajorVersion,
javaMajorVersion,
javaMajorVersion,
javaMajorVersionUpperBound,
smallerJavaMajorVersionLowerBound,
smallerJavaMajorVersionUpperBound,
largerJavaMajorVersionLowerBound,
largerJavaMajorVersionUpperBound
)
);
BufferedReader br = new BufferedReader(sr)
) {
assertExpectedJvmOptions(javaMajorVersion, br, Arrays.asList("-Xms1g", "-Xmx1g", "-XX:+UseG1GC", "-Xlog:gc"));
}
}
private void assertExpectedJvmOptions(
final int javaMajorVersion, final BufferedReader br, final List<String> expectedJvmOptions) throws IOException {
private void assertExpectedJvmOptions(final int javaMajorVersion, final BufferedReader br, final List<String> expectedJvmOptions)
throws IOException {
final Map<String, AtomicBoolean> seenJvmOptions = new HashMap<>();
for (final String expectedJvmOption : expectedJvmOptions) {
assertNull(seenJvmOptions.put(expectedJvmOption, new AtomicBoolean()));
}
JvmOptionsParser.parse(
javaMajorVersion,
br,
new JvmOptionsParser.JvmOptionConsumer() {
@Override
public void accept(final String jvmOption) {
final AtomicBoolean seen = seenJvmOptions.get(jvmOption);
if (seen == null) {
fail("unexpected JVM option [" + jvmOption + "]");
}
assertFalse("saw JVM option [" + jvmOption + "] more than once", seen.get());
seen.set(true);
}
},
new JvmOptionsParser.InvalidLineConsumer() {
@Override
public void accept(final int lineNumber, final String line) {
fail("unexpected invalid line [" + line + "] on line number [" + lineNumber + "]");
}
});
JvmOptionsParser.parse(javaMajorVersion, br, new JvmOptionsParser.JvmOptionConsumer() {
@Override
public void accept(final String jvmOption) {
final AtomicBoolean seen = seenJvmOptions.get(jvmOption);
if (seen == null) {
fail("unexpected JVM option [" + jvmOption + "]");
}
assertFalse("saw JVM option [" + jvmOption + "] more than once", seen.get());
seen.set(true);
}
}, 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()) {
assertTrue("expected JVM option [" + seenJvmOption.getKey() + "]", seenJvmOption.getValue().get());
}
}
public void testInvalidLines() throws IOException {
try (StringReader sr = new StringReader("XX:+UseG1GC");
BufferedReader br = new BufferedReader(sr)) {
JvmOptionsParser.parse(
randomIntBetween(8, Integer.MAX_VALUE),
br,
new JvmOptionsParser.JvmOptionConsumer() {
@Override
public void accept(final String jvmOption) {
fail("unexpected valid JVM option [" + jvmOption + "]");
}
}, new JvmOptionsParser.InvalidLineConsumer() {
@Override
public void accept(final int lineNumber, final String line) {
assertThat(lineNumber, equalTo(1));
assertThat(line, equalTo("XX:+UseG1GC"));
}
});
try (StringReader sr = new StringReader("XX:+UseG1GC"); BufferedReader br = new BufferedReader(sr)) {
JvmOptionsParser.parse(randomIntBetween(8, Integer.MAX_VALUE), br, new JvmOptionsParser.JvmOptionConsumer() {
@Override
public void accept(final String jvmOption) {
fail("unexpected valid JVM option [" + jvmOption + "]");
}
}, new JvmOptionsParser.InvalidLineConsumer() {
@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 smallerJavaMajorVersion = randomIntBetween(7, javaMajorVersion - 1);
final String invalidRangeLine = String.format(Locale.ROOT, "%d:%d-XX:+UseG1GC", javaMajorVersion, smallerJavaMajorVersion);
try (StringReader sr = new StringReader(invalidRangeLine);
BufferedReader br = new BufferedReader(sr)) {
try (StringReader sr = new StringReader(invalidRangeLine); BufferedReader br = new BufferedReader(sr)) {
assertInvalidLines(br, Collections.singletonMap(1, invalidRangeLine));
}
final long invalidLowerJavaMajorVersion = (long) randomIntBetween(1, 16) + Integer.MAX_VALUE;
final long invalidUpperJavaMajorVersion = (long) randomIntBetween(1, 16) + Integer.MAX_VALUE;
final String numberFormatExceptionsLine = String.format(
Locale.ROOT,
"%d:-XX:+UseG1GC\n8-%d:-XX:+AggressiveOpts",
invalidLowerJavaMajorVersion,
invalidUpperJavaMajorVersion);
try (StringReader sr = new StringReader(numberFormatExceptionsLine);
BufferedReader br = new BufferedReader(sr)) {
Locale.ROOT,
"%d:-XX:+UseG1GC\n8-%d:-XX:+AggressiveOpts",
invalidLowerJavaMajorVersion,
invalidUpperJavaMajorVersion
);
try (StringReader sr = new StringReader(numberFormatExceptionsLine); BufferedReader br = new BufferedReader(sr)) {
final Map<Integer, String> invalidLines = new HashMap<>(2);
invalidLines.put(1, String.format(Locale.ROOT, "%d:-XX:+UseG1GC", invalidLowerJavaMajorVersion));
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";
try (StringReader sr = new StringReader(multipleInvalidLines);
BufferedReader br = new BufferedReader(sr)) {
try (StringReader sr = new StringReader(multipleInvalidLines); BufferedReader br = new BufferedReader(sr)) {
final Map<Integer, String> invalidLines = new HashMap<>(2);
invalidLines.put(1, "XX:+UseG1GC");
invalidLines.put(2, "XX:+AggressiveOpts");
@ -219,29 +225,24 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
final int lowerBound = randomIntBetween(9, 16);
final int upperBound = randomIntBetween(8, lowerBound - 1);
final String upperBoundGreaterThanLowerBound = String.format(Locale.ROOT, "%d-%d-XX:+UseG1GC", lowerBound, upperBound);
try (StringReader sr = new StringReader(upperBoundGreaterThanLowerBound);
BufferedReader br = new BufferedReader(sr)) {
try (StringReader sr = new StringReader(upperBoundGreaterThanLowerBound); BufferedReader br = new BufferedReader(sr)) {
assertInvalidLines(br, Collections.singletonMap(1, upperBoundGreaterThanLowerBound));
}
}
private void assertInvalidLines(final BufferedReader br, final Map<Integer, String> invalidLines) throws IOException {
final Map<Integer, String> seenInvalidLines = new HashMap<>(invalidLines.size());
JvmOptionsParser.parse(
randomIntBetween(8, Integer.MAX_VALUE),
br,
new JvmOptionsParser.JvmOptionConsumer() {
@Override
public void accept(final String jvmOption) {
fail("unexpected valid JVM options [" + jvmOption + "]");
}
},
new JvmOptionsParser.InvalidLineConsumer() {
@Override
public void accept(final int lineNumber, final String line) {
seenInvalidLines.put(lineNumber, line);
}
});
JvmOptionsParser.parse(randomIntBetween(8, Integer.MAX_VALUE), br, new JvmOptionsParser.JvmOptionConsumer() {
@Override
public void accept(final String jvmOption) {
fail("unexpected valid JVM options [" + jvmOption + "]");
}
}, new JvmOptionsParser.InvalidLineConsumer() {
@Override
public void accept(final int lineNumber, final String line) {
seenInvalidLines.put(lineNumber, line);
}
});
assertThat(seenInvalidLines, equalTo(invalidLines));
}
@ -249,8 +250,9 @@ public class JvmOptionsParserTests extends LaunchersTestCase {
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", "-XX:+UseG1GC")),
equalTo("-Xms1g -Xmx1g -XX:+UseG1GC"));
JvmOptionsParser.spaceDelimitJvmOptions(Arrays.asList("-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.TimeoutSuite;
@TestMethodProviders({
JUnit3MethodProvider.class
})
@SeedDecorators({MixWithSuiteName.class})
@TestMethodProviders({ JUnit3MethodProvider.class })
@SeedDecorators({ MixWithSuiteName.class })
@ThreadLeakScope(ThreadLeakScope.Scope.SUITE)
@ThreadLeakGroup(ThreadLeakGroup.Group.MAIN)
@ThreadLeakAction({ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT})
@ThreadLeakAction({ ThreadLeakAction.Action.WARN, ThreadLeakAction.Action.INTERRUPT })
@ThreadLeakZombies(ThreadLeakZombies.Consequence.IGNORE_REMAINING_TESTS)
@ThreadLeakLingering(linger = 5000)
@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. */
static final Set<String> MODULES;
static {
try (InputStream stream = InstallPluginCommand.class.getResourceAsStream("/modules.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
try (
InputStream stream = InstallPluginCommand.class.getResourceAsStream("/modules.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))
) {
Set<String> modules = new HashSet<>();
String line = reader.readLine();
while (line != null) {
@ -151,8 +153,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
/** The official plugins that can be installed simply by name. */
static final Set<String> OFFICIAL_PLUGINS;
static {
try (InputStream stream = InstallPluginCommand.class.getResourceAsStream("/plugins.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
try (
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
String line = reader.readLine();
while (line != null) {
@ -197,8 +201,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
InstallPluginCommand() {
super("Install a plugin");
this.batchOption = parser.acceptsAll(Arrays.asList("b", "batch"),
"Enable batch mode explicitly, automatic confirmation of security permission");
this.batchOption = parser.acceptsAll(
Arrays.asList("b", "batch"),
"Enable batch mode explicitly, automatic confirmation of security permission"
);
this.arguments = parser.nonOptions("plugin id");
}
@ -261,7 +267,8 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
} catch (final IOException exceptionWhileRemovingFiles) {
final Exception exception = new Exception(
"failed rolling back installation of [" + deleteOnFailureEntry.getKey() + "]",
exceptionWhileRemovingFiles);
exceptionWhileRemovingFiles
);
installProblem.addSuppressed(exception);
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");
case OSS:
throw new UserException(
ExitCodes.CONFIG,
"X-Pack is not available with the oss distribution; to use X-Pack features use the default distribution");
ExitCodes.CONFIG,
"X-Pack is not available with the oss distribution; to use X-Pack features use the default distribution"
);
case UNKNOWN:
throw new IllegalStateException("your distribution is broken");
}
@ -313,7 +321,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
List<String> plugins = checkMisspelledPlugin(pluginId);
String msg = "Unknown plugin " + pluginId;
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);
}
@ -332,16 +340,20 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
/** Returns the url for an official elasticsearch plugin. */
private String getElasticUrl(
final Terminal terminal,
final String stagingHash,
final Version version,
final boolean isSnapshot,
final String pluginId,
final String platform) throws IOException, UserException {
final Terminal terminal,
final String stagingHash,
final Version version,
final boolean isSnapshot,
final String pluginId,
final String platform
) throws IOException,
UserException {
final String baseUrl;
if (isSnapshot && stagingHash == null) {
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 (isSnapshot) {
@ -352,8 +364,14 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
} else {
baseUrl = String.format(Locale.ROOT, "https://artifacts.elastic.co/downloads/elasticsearch-plugins/%s", pluginId);
}
final String platformUrl =
String.format(Locale.ROOT, "%s/%s-%s-%s.zip", baseUrl, pluginId, platform, Build.CURRENT.getQualifiedVersion());
final String platformUrl = String.format(
Locale.ROOT,
"%s/%s-%s-%s.zip",
baseUrl,
pluginId,
platform,
Build.CURRENT.getQualifiedVersion()
);
if (urlExists(terminal, 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) {
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. */
@ -419,8 +443,11 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
Path zip = Files.createTempFile(tmpDir, null, ".zip");
URLConnection urlConnection = url.openConnection();
urlConnection.addRequestProperty("User-Agent", "elasticsearch-plugin-installer");
try (InputStream in = isBatch ? urlConnection.getInputStream() :
new TerminalProgressInputStream(urlConnection.getInputStream(),urlConnection.getContentLength(),terminal)) {
try (
InputStream in = isBatch
? urlConnection.getInputStream()
: new TerminalProgressInputStream(urlConnection.getInputStream(), urlConnection.getContentLength(), terminal)
) {
// must overwrite since creating the temp file above actually created the file
Files.copy(in, zip, StandardCopyOption.REPLACE_EXISTING);
}
@ -493,7 +520,11 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
final Terminal terminal,
final String urlString,
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);
pathsToDeleteOnShutdown.add(zip);
String checksumUrlString = urlString + ".sha512";
@ -501,8 +532,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
String digestAlgo = "SHA-512";
if (checksumUrl == null && officialPlugin == false) {
// 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 " +
"future release. Please update the plugin to use a sha512 checksum.");
terminal.println(
"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";
checksumUrl = openUrl(checksumUrlString);
digestAlgo = "SHA-1";
@ -536,11 +569,12 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
final String expectedFile = segments[segments.length - 1];
if (fields[1].equals(expectedFile) == false) {
final String message = String.format(
Locale.ROOT,
"checksum file at [%s] is not for this plugin, expected [%s] but was [%s]",
checksumUrl,
expectedFile,
fields[1]);
Locale.ROOT,
"checksum file at [%s] is not for this plugin, expected [%s] but was [%s]",
checksumUrl,
expectedFile,
fields[1]
);
throw new UserException(ExitCodes.IO_ERROR, message);
}
if (checksumReader.readLine() != null) {
@ -563,7 +597,8 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
if (expectedChecksum.equals(actualChecksum) == false) {
throw new UserException(
ExitCodes.IO_ERROR,
digestAlgo + " mismatch, expected " + expectedChecksum + " but got " + actualChecksum);
digestAlgo + " mismatch, expected " + expectedChecksum + " but got " + actualChecksum
);
}
} catch (final NoSuchAlgorithmException e) {
// 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 URL ascUrl = openUrl(ascUrlString);
try (
// fin is a file stream over the downloaded plugin zip whose signature to verify
InputStream fin = pluginZipInputStream(zip);
// sin is a URL stream to the signature corresponding to the downloaded plugin zip
InputStream sin = urlOpenStream(ascUrl);
// ain is a input stream to the public key in ASCII-Armor format (RFC4880)
InputStream ain = new ArmoredInputStream(getPublicKey())) {
// fin is a file stream over the downloaded plugin zip whose signature to verify
InputStream fin = pluginZipInputStream(zip);
// sin is a URL stream to the signature corresponding to the downloaded plugin zip
InputStream sin = urlOpenStream(ascUrl);
// ain is a input stream to the public key in ASCII-Armor format (RFC4880)
InputStream ain = new ArmoredInputStream(getPublicKey())
) {
final JcaPGPObjectFactory factory = new JcaPGPObjectFactory(PGPUtil.getDecoderStream(sin));
final PGPSignature signature = ((PGPSignatureList) factory.nextObject()).get(0);
@ -660,7 +696,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
// pkg private for tests
URL openUrl(String urlString) throws IOException {
URL checksumUrl = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection)checksumUrl.openConnection();
HttpURLConnection connection = (HttpURLConnection) checksumUrl.openConnection();
if (connection.getResponseCode() == 404) {
return null;
}
@ -678,8 +714,11 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
byte[] buffer = new byte[8192];
while ((entry = zipInput.getNextEntry()) != null) {
if (entry.getName().startsWith("elasticsearch/")) {
throw new UserException(PLUGIN_MALFORMED, "This plugin was built with an older plugin structure." +
" Contact the plugin author to remove the intermediate \"elasticsearch\" directory within the plugin zip.");
throw new UserException(
PLUGIN_MALFORMED,
"This plugin was built with an older plugin structure."
+ " Contact the plugin author to remove the intermediate \"elasticsearch\" directory within the plugin zip."
);
}
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
// is still rooted with the target plugin directory.
if (targetFile.normalize().startsWith(target) == false) {
throw new UserException(PLUGIN_MALFORMED, "Zip contains entry name '" +
entry.getName() + "' resolving outside of plugin directory");
throw new UserException(
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
@ -725,9 +766,9 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
// and the Jimfs test dependency is upgraded to include
// this pull request
final StackTraceElement[] elements = e.getStackTrace();
if (elements.length >= 1 &&
elements[0].getClassName().equals("com.google.common.jimfs.AttributeService") &&
elements[0].getMethodName().equals("setAttributeInternal")) {
if (elements.length >= 1
&& elements[0].getClassName().equals("com.google.common.jimfs.AttributeService")
&& elements[0].getMethodName().equals("setAttributeInternal")) {
return stagingDirectoryWithoutPosixPermissions(pluginsDir);
} else {
throw e;
@ -753,10 +794,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
if (Files.exists(destination)) {
final String message = String.format(
Locale.ROOT,
"plugin directory [%s] already exists; if you need to update the plugin, " +
"uninstall it first using command 'remove %s'",
"plugin directory [%s] already exists; if you need to update the plugin, " + "uninstall it first using command 'remove %s'",
destination,
pluginName);
pluginName
);
throw new UserException(PLUGIN_EXISTS, message);
}
}
@ -785,24 +826,19 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
private static final String LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR;
static {
LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR =
String.format(Locale.ROOT, ".+%1$slib%1$stools%1$splugin-cli%1$s[^%1$s]+\\.jar", "(/|\\\\)");
LIB_TOOLS_PLUGIN_CLI_CLASSPATH_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 */
void jarHellCheck(PluginInfo candidateInfo, Path candidateDir, Path pluginsDir, Path modulesDir) throws Exception {
// create list of current jars in classpath
final Set<URL> classpath =
JarHell.parseClassPath()
.stream()
.filter(url -> {
try {
return url.toURI().getPath().matches(LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR) == false;
} catch (final URISyntaxException e) {
throw new AssertionError(e);
}
})
.collect(Collectors.toSet());
final Set<URL> classpath = JarHell.parseClassPath().stream().filter(url -> {
try {
return url.toURI().getPath().matches(LIB_TOOLS_PLUGIN_CLI_CLASSPATH_JAR) == false;
} catch (final URISyntaxException e) {
throw new AssertionError(e);
}
}).collect(Collectors.toSet());
// read existing bundles. this does some checks on the installation too.
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.
* If the plugin has a bin dir and/or a config dir, those are moved.
*/
private PluginInfo installPlugin(Terminal terminal, boolean isBatch, Path tmpRoot,
Environment env, List<Path> deleteOnFailure) throws Exception {
private PluginInfo installPlugin(Terminal terminal, boolean isBatch, Path tmpRoot, Environment env, List<Path> deleteOnFailure)
throws Exception {
final PluginInfo info = loadPluginInfo(terminal, tmpRoot, env);
// read optional security policy (extra permissions), if it exists, confirm or warn the user
Path policy = tmpRoot.resolve(PluginInfo.ES_PLUGIN_POLICY);
@ -841,15 +877,20 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
final Path destination = env.pluginsFile().resolve(info.getName());
deleteOnFailure.add(destination);
installPluginSupportFiles(info, tmpRoot, env.binFile().resolve(info.getName()),
env.configFile().resolve(info.getName()), deleteOnFailure);
installPluginSupportFiles(
info,
tmpRoot,
env.binFile().resolve(info.getName()),
env.configFile().resolve(info.getName()),
deleteOnFailure
);
movePlugin(tmpRoot, destination);
return info;
}
/** Moves bin and config directories from the plugin if they exist */
private void installPluginSupportFiles(PluginInfo info, Path tmpRoot,
Path destBinDir, Path destConfigDir, List<Path> deleteOnFailure) throws Exception {
private void installPluginSupportFiles(PluginInfo info, Path tmpRoot, Path destBinDir, Path destConfigDir, List<Path> deleteOnFailure)
throws Exception {
Path tmpBinDir = tmpRoot.resolve("bin");
if (Files.exists(tmpBinDir)) {
deleteOnFailure.add(destBinDir);
@ -900,8 +941,10 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(tmpBinDir)) {
for (Path srcFile : stream) {
if (Files.isDirectory(srcFile)) {
throw new UserException(PLUGIN_MALFORMED, "Directories not allowed in bin dir " +
"for plugin " + info.getName() + ", found " + srcFile.getFileName());
throw new UserException(
PLUGIN_MALFORMED,
"Directories not allowed in bin dir " + "for plugin " + info.getName() + ", found " + srcFile.getFileName()
);
}
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 {
if (Files.isDirectory(tmpConfigDir) == false) {
throw new UserException(PLUGIN_MALFORMED,
"config in plugin " + info.getName() + " is not a directory");
throw new UserException(PLUGIN_MALFORMED, "config in plugin " + info.getName() + " is not a directory");
}
Files.createDirectories(destConfigDir);
setFileAttributes(destConfigDir, CONFIG_DIR_PERMS);
final PosixFileAttributeView destConfigDirAttributesView =
Files.getFileAttributeView(destConfigDir.getParent(), PosixFileAttributeView.class);
final PosixFileAttributes destConfigDirAttributes =
destConfigDirAttributesView != null ? destConfigDirAttributesView.readAttributes() : null;
final PosixFileAttributeView destConfigDirAttributesView = Files.getFileAttributeView(
destConfigDir.getParent(),
PosixFileAttributeView.class
);
final PosixFileAttributes destConfigDirAttributes = destConfigDirAttributesView != null
? destConfigDirAttributesView.readAttributes()
: null;
if (destConfigDirAttributes != null) {
setOwnerGroup(destConfigDir, destConfigDirAttributes);
}
@ -935,8 +980,7 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(tmpConfigDir)) {
for (Path srcFile : stream) {
if (Files.isDirectory(srcFile)) {
throw new UserException(PLUGIN_MALFORMED,
"Directories not allowed in config dir for plugin " + info.getName());
throw new UserException(PLUGIN_MALFORMED, "Directories not allowed in config dir for plugin " + info.getName());
}
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));
terminal.println(Terminal.Verbosity.VERBOSE, info.toString(prefix));
if (info.getElasticsearchVersion().equals(Version.CURRENT) == false) {
terminal.errorPrintln("WARNING: plugin [" + info.getName() + "] was built for Elasticsearch version " + info.getVersion() +
" but version " + Version.CURRENT + " is required");
terminal.errorPrintln(
"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;
// rounding up to 100% would mean we say we are done, before we are...
// 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) {
currentPercent = percent;
onProgress(percent);

View File

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

View File

@ -19,7 +19,6 @@
package org.elasticsearch.plugins;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
@ -50,9 +49,7 @@ public class ListPluginsCommandTests extends ESTestCase {
super.setUp();
home = createTempDir();
Files.createDirectories(home.resolve("plugins"));
Settings settings = Settings.builder()
.put("path.home", home)
.build();
Settings settings = Settings.builder().put("path.home", home).build();
env = TestEnvironment.newEnvironment(settings);
}
@ -69,7 +66,7 @@ public class ListPluginsCommandTests extends ESTestCase {
@Override
protected Environment createEnv(Map<String, String> settings) throws UserException {
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();
return new Environment(realSettings, home.resolve("config"));
}
@ -83,33 +80,39 @@ public class ListPluginsCommandTests extends ESTestCase {
return terminal;
}
private static String buildMultiline(String... args){
private static String buildMultiline(String... args) {
return Arrays.stream(args).collect(Collectors.joining("\n", "", "\n"));
}
private static void buildFakePlugin(
final Environment env,
final String description,
final String name,
final String classname) throws IOException {
private static void buildFakePlugin(final Environment env, final String description, final String name, final String classname)
throws IOException {
buildFakePlugin(env, description, name, classname, false);
}
private static void buildFakePlugin(
final Environment env,
final String description,
final String name,
final String classname,
final boolean hasNativeController) throws IOException {
final Environment env,
final String description,
final String name,
final String classname,
final boolean hasNativeController
) throws IOException {
PluginTestUtil.writePluginProperties(
env.pluginsFile().resolve(name),
"description", description,
"name", name,
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", "1.8",
"classname", classname,
"has.native.controller", Boolean.toString(hasNativeController));
"description",
description,
"name",
name,
"version",
"1.0",
"elasticsearch.version",
Version.CURRENT.toString(),
"java.version",
"1.8",
"classname",
classname,
"has.native.controller",
Boolean.toString(hasNativeController)
);
}
public void testPluginsDirMissing() throws Exception {
@ -141,19 +144,21 @@ public class ListPluginsCommandTests extends ESTestCase {
String[] params = { "-v" };
MockTerminal terminal = listPlugins(home, params);
assertEquals(
buildMultiline(
"Plugins directory: " + env.pluginsFile(),
"fake_plugin",
"- Plugin information:",
"Name: fake_plugin",
"Description: fake desc",
"Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Extended Plugins: []",
" * Classname: org.fake"),
terminal.getOutput());
buildMultiline(
"Plugins directory: " + env.pluginsFile(),
"fake_plugin",
"- Plugin information:",
"Name: fake_plugin",
"Description: fake desc",
"Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Extended Plugins: []",
" * Classname: org.fake"
),
terminal.getOutput()
);
}
public void testPluginWithNativeController() throws Exception {
@ -172,8 +177,10 @@ public class ListPluginsCommandTests extends ESTestCase {
"Java Version: 1.8",
"Native Controller: true",
"Extended Plugins: []",
" * Classname: org.fake"),
terminal.getOutput());
" * Classname: org.fake"
),
terminal.getOutput()
);
}
public void testPluginWithVerboseMultiplePlugins() throws Exception {
@ -182,29 +189,31 @@ public class ListPluginsCommandTests extends ESTestCase {
String[] params = { "-v" };
MockTerminal terminal = listPlugins(home, params);
assertEquals(
buildMultiline(
"Plugins directory: " + env.pluginsFile(),
"fake_plugin1",
"- Plugin information:",
"Name: fake_plugin1",
"Description: fake desc 1",
"Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Extended Plugins: []",
" * Classname: org.fake",
"fake_plugin2",
"- Plugin information:",
"Name: fake_plugin2",
"Description: fake desc 2",
"Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Extended Plugins: []",
" * Classname: org.fake2"),
terminal.getOutput());
buildMultiline(
"Plugins directory: " + env.pluginsFile(),
"fake_plugin1",
"- Plugin information:",
"Name: fake_plugin1",
"Description: fake desc 1",
"Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Extended Plugins: []",
" * Classname: org.fake",
"fake_plugin2",
"- Plugin information:",
"Name: fake_plugin2",
"Description: fake desc 2",
"Version: 1.0",
"Elasticsearch Version: " + Version.CURRENT.toString(),
"Java Version: 1.8",
"Native Controller: false",
"Extended Plugins: []",
" * Classname: org.fake2"
),
terminal.getOutput()
);
}
public void testPluginWithoutVerboseMultiplePlugins() throws Exception {
@ -215,45 +224,45 @@ public class ListPluginsCommandTests extends ESTestCase {
assertEquals(buildMultiline("fake_plugin1", "fake_plugin2"), output);
}
public void testPluginWithoutDescriptorFile() throws Exception{
public void testPluginWithoutDescriptorFile() throws Exception {
final Path pluginDir = env.pluginsFile().resolve("fake1");
Files.createDirectories(pluginDir);
NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> listPlugins(home));
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");
PluginTestUtil.writePluginProperties(pluginDir, "description", "fake desc");
IllegalArgumentException e = expectThrows(
IllegalArgumentException.class,
() -> listPlugins(home));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> listPlugins(home));
final Path descriptorPath = pluginDir.resolve(PluginInfo.ES_PLUGIN_PROPERTIES);
assertEquals(
"property [name] is missing in [" + descriptorPath.toString() + "]",
e.getMessage());
assertEquals("property [name] is missing in [" + descriptorPath.toString() + "]", e.getMessage());
}
public void testExistingIncompatiblePlugin() throws Exception {
PluginTestUtil.writePluginProperties(env.pluginsFile().resolve("fake_plugin1"),
"description", "fake desc 1",
"name", "fake_plugin1",
"version", "1.0",
"elasticsearch.version", Version.fromString("1.0.0").toString(),
"java.version", System.getProperty("java.specification.version"),
"classname", "org.fake1");
PluginTestUtil.writePluginProperties(
env.pluginsFile().resolve("fake_plugin1"),
"description",
"fake desc 1",
"name",
"fake_plugin1",
"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");
MockTerminal terminal = listPlugins(home);
String message = "plugin [fake_plugin1] was built for Elasticsearch version 1.0 but version " + Version.CURRENT + " is required";
assertEquals(
"fake_plugin1\nfake_plugin2\n",
terminal.getOutput());
assertEquals(
"WARNING: " + message + "\n",
terminal.getErrorOutput());
assertEquals("fake_plugin1\nfake_plugin2\n", terminal.getOutput());
assertEquals("WARNING: " + message + "\n", terminal.getErrorOutput());
String[] params = {"-s"};
String[] params = { "-s" };
terminal = listPlugins(home, params);
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.createFile(home.resolve("bin").resolve("elasticsearch"));
Files.createDirectories(home.resolve("plugins"));
Settings settings = Settings.builder()
.put("path.home", home)
.build();
Settings settings = Settings.builder().put("path.home", home).build();
env = TestEnvironment.newEnvironment(settings);
}
@ -93,13 +91,20 @@ public class RemovePluginCommandTests extends ESTestCase {
void createPlugin(Path path, String name, Version version) throws IOException {
PluginTestUtil.writePluginProperties(
path.resolve(name),
"description", "dummy",
"name", name,
"version", "1.0",
"elasticsearch.version", version.toString(),
"java.version", System.getProperty("java.specification.version"),
"classname", "SomeClass");
path.resolve(name),
"description",
"dummy",
"name",
name,
"version",
"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 {
@ -138,11 +143,13 @@ public class RemovePluginCommandTests extends ESTestCase {
public void testRemoveOldVersion() throws Exception {
createPlugin(
"fake",
VersionUtils.randomVersionBetween(
random(),
Version.CURRENT.minimumIndexCompatibilityVersion(),
VersionUtils.getPreviousVersion()));
"fake",
VersionUtils.randomVersionBetween(
random(),
Version.CURRENT.minimumIndexCompatibilityVersion(),
VersionUtils.getPreviousVersion()
)
);
removePlugin("fake", home, randomBoolean());
assertThat(Files.exists(env.pluginsFile().resolve("fake")), equalTo(false));
assertRemoveCleaned(env);
@ -237,12 +244,15 @@ public class RemovePluginCommandTests extends ESTestCase {
return false;
}
}.main(new String[] { "-Epath.home=" + home, "fake" }, terminal);
try (BufferedReader reader = new BufferedReader(new StringReader(terminal.getOutput()));
BufferedReader errorReader = new BufferedReader(new StringReader(terminal.getErrorOutput()))
try (
BufferedReader reader = new BufferedReader(new StringReader(terminal.getOutput()));
BufferedReader errorReader = new BufferedReader(new StringReader(terminal.getErrorOutput()))
) {
assertEquals("-> removing [fake]...", reader.readLine());
assertEquals("ERROR: plugin [fake] not found; run 'elasticsearch-plugin list' to get list of installed plugins",
errorReader.readLine());
assertEquals(
"ERROR: plugin [fake] not found; run 'elasticsearch-plugin list' to get list of installed plugins",
errorReader.readLine()
);
assertNull(reader.readLine());
assertNull(errorReader.readLine());
}
@ -266,4 +276,3 @@ public class RemovePluginCommandTests extends ESTestCase {
}
}