From 0f85182abe8ca542289b05f4467b5e9364a92194 Mon Sep 17 00:00:00 2001 From: Alpar Torok Date: Mon, 4 Mar 2019 09:12:12 +0200 Subject: [PATCH] Testclusters: implement support to install plugins (#39116) * methods to run bin script * Add support for specifying and installing plugins * Add OS specific distirbution support * Add test to verify plugin installed * Remove use of Gradle internal OperatingSystem --- .../elasticsearch/GradleServicesAdapter.java | 6 + .../elasticsearch/gradle/Distribution.java | 29 +++- .../java/org/elasticsearch/gradle/OS.java | 90 +++++++++++ .../testclusters/ElasticsearchNode.java | 145 +++++++++++++----- .../testclusters/TestClustersPlugin.java | 35 ++--- .../testfixtures/TestFixturesPlugin.java | 4 +- .../testclusters/TestClustersPluginIT.java | 12 +- .../src/testKit/testclusters/build.gradle | 22 ++- .../testclusters/dummyPlugin/build.gradle | 11 ++ .../src/main/java/DummyPlugin.java | 30 ++++ buildSrc/src/testKit/testclusters/empty.txt | 0 .../src/testKit/testclusters/settings.gradle | 3 +- 12 files changed, 316 insertions(+), 71 deletions(-) create mode 100644 buildSrc/src/main/java/org/elasticsearch/gradle/OS.java create mode 100644 buildSrc/src/testKit/testclusters/dummyPlugin/build.gradle create mode 100644 buildSrc/src/testKit/testclusters/dummyPlugin/src/main/java/DummyPlugin.java create mode 100644 buildSrc/src/testKit/testclusters/empty.txt diff --git a/buildSrc/src/main/java/org/elasticsearch/GradleServicesAdapter.java b/buildSrc/src/main/java/org/elasticsearch/GradleServicesAdapter.java index 0174f576e2b..b5327ed6322 100644 --- a/buildSrc/src/main/java/org/elasticsearch/GradleServicesAdapter.java +++ b/buildSrc/src/main/java/org/elasticsearch/GradleServicesAdapter.java @@ -18,6 +18,7 @@ */ package org.elasticsearch; +import org.elasticsearch.gradle.LoggedExec; import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.file.CopySpec; @@ -25,6 +26,7 @@ import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileTree; import org.gradle.api.tasks.WorkResult; import org.gradle.process.ExecResult; +import org.gradle.process.ExecSpec; import org.gradle.process.JavaExecSpec; import java.io.File; @@ -70,4 +72,8 @@ public class GradleServicesAdapter { public FileCollection fileTree(File dir) { return project.fileTree(dir); } + + public void loggedExec(Action action) { + LoggedExec.exec(project, action); + } } diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/Distribution.java b/buildSrc/src/main/java/org/elasticsearch/gradle/Distribution.java index 721eddb5291..f0e406e00ed 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/Distribution.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/Distribution.java @@ -20,23 +20,36 @@ package org.elasticsearch.gradle; public enum Distribution { - INTEG_TEST("integ-test", "zip"), - ZIP("elasticsearch", "zip"), - ZIP_OSS("elasticsearch-oss", "zip"); + INTEG_TEST("integ-test"), + DEFAULT("elasticsearch"), + OSS("elasticsearch-oss"); private final String fileName; - private final String fileExtension; - Distribution(String name, String fileExtension) { + Distribution(String name) { this.fileName = name; - this.fileExtension = fileExtension; } - public String getFileName() { + public String getArtifactName() { return fileName; } public String getFileExtension() { - return fileExtension; + if (this.equals(INTEG_TEST)) { + return "zip"; + } else { + return OS.conditionalString() + .onUnix(() -> "tar.gz") + .onWindows(() -> "zip") + .supply(); + } + } + + public String getClassifier() { + return OS.conditional() + .onLinux(() -> "linux-x86_64") + .onWindows(() -> "windows-x86_64") + .onMac(() -> "darwin-x86_64") + .supply(); } } diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/OS.java b/buildSrc/src/main/java/org/elasticsearch/gradle/OS.java new file mode 100644 index 00000000000..a8f158270cb --- /dev/null +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/OS.java @@ -0,0 +1,90 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.elasticsearch.gradle; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.function.Supplier; + +public enum OS { + WINDOWS, + MAC, + LINUX; + + public static OS current() { + String os = System.getProperty("os.name", ""); + if (os.startsWith("Windows")) { + return OS.WINDOWS; + } + if (os.startsWith("Linux") || os.startsWith("LINUX")) { + return OS.LINUX; + } + if (os.startsWith("Mac")) { + return OS.MAC; + } + throw new IllegalStateException("Can't determine OS from: " + os); + } + + public static class Conditional { + + private final Map> conditions = new HashMap<>(); + + public Conditional onWindows(Supplier supplier) { + conditions.put(WINDOWS, supplier); + return this; + } + + public Conditional onLinux(Supplier supplier) { + conditions.put(LINUX, supplier); + return this; + } + + public Conditional onMac(Supplier supplier) { + conditions.put(MAC, supplier); + return this; + } + + public Conditional onUnix(Supplier supplier) { + conditions.put(MAC, supplier); + conditions.put(LINUX, supplier); + return this; + } + + public T supply() { + HashSet missingOS = new HashSet<>(Arrays.asList(OS.values())); + missingOS.removeAll(conditions.keySet()); + if (missingOS.isEmpty() == false) { + throw new IllegalArgumentException("No condition specified for " + missingOS); + } + return conditions.get(OS.current()).get(); + } + + } + + public static Conditional conditional() { + return new Conditional<>(); + } + + public static Conditional conditionalString() { + return conditional(); + } + +} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java index b494c3be364..1010bc54f86 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java @@ -20,10 +20,10 @@ package org.elasticsearch.gradle.testclusters; import org.elasticsearch.GradleServicesAdapter; import org.elasticsearch.gradle.Distribution; +import org.elasticsearch.gradle.OS; import org.elasticsearch.gradle.Version; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; -import org.gradle.internal.os.OperatingSystem; import java.io.BufferedReader; import java.io.File; @@ -31,11 +31,14 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.UncheckedIOException; import java.net.HttpURLConnection; +import java.net.URI; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -65,7 +68,9 @@ public class ElasticsearchNode { private static final TimeUnit ES_DESTROY_TIMEOUT_UNIT = TimeUnit.SECONDS; private static final int NODE_UP_TIMEOUT = 30; private static final TimeUnit NODE_UP_TIMEOUT_UNIT = TimeUnit.SECONDS; + private final LinkedHashMap> waitConditions; + private final List plugins = new ArrayList<>(); private final Path confPathRepo; private final Path configFile; @@ -75,6 +80,7 @@ public class ElasticsearchNode { private final Path httpPortsFile; private final Path esStdoutFile; private final Path esStderrFile; + private final Path tmpDir; private Distribution distribution; private String version; @@ -96,6 +102,7 @@ public class ElasticsearchNode { httpPortsFile = confPathLogs.resolve("http.ports"); esStdoutFile = confPathLogs.resolve("es.stdout.log"); esStderrFile = confPathLogs.resolve("es.stderr.log"); + tmpDir = workingDir.resolve("tmp"); this.waitConditions = new LinkedHashMap<>(); waitConditions.put("http ports file", node -> Files.exists(node.httpPortsFile)); waitConditions.put("transport ports file", node -> Files.exists(node.transportPortFile)); @@ -126,6 +133,16 @@ public class ElasticsearchNode { this.distribution = distribution; } + public void plugin(URI plugin) { + requireNonNull(plugin, "Plugin name can't be null"); + checkFrozen(); + this.plugins.add(plugin); + } + + public void plugin(File plugin) { + plugin(plugin.toURI()); + } + public void freeze() { requireNonNull(distribution, "null distribution passed when configuring test cluster `" + this + "`"); requireNonNull(version, "null version passed when configuring test cluster `" + this + "`"); @@ -166,12 +183,20 @@ public class ElasticsearchNode { }); } + /** + * Returns a stream of lines in the generated logs similar to Files.lines + * + * @return stream of log lines + */ + public Stream logLines() throws IOException { + return Files.lines(esStdoutFile, StandardCharsets.UTF_8); + } + synchronized void start() { logger.info("Starting `{}`", this); Path distroArtifact = artifactsExtractDir - .resolve(distribution.getFileExtension()) - .resolve(distribution.getFileName() + "-" + getVersion()); + .resolve(distribution.getArtifactName() + "-" + getVersion()); if (Files.exists(distroArtifact) == false) { throw new TestClustersException("Can not start " + this + ", missing: " + distroArtifact); @@ -183,34 +208,79 @@ public class ElasticsearchNode { spec.from(distroArtifact.resolve("config").toFile()); spec.into(configFile.getParent()); }); - configure(); - startElasticsearchProcess(distroArtifact); + + try { + createWorkingDir(distroArtifact); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + createConfiguration(); + + plugins.forEach(plugin -> runElaticsearchBinScript( + "elasticsearch-plugin", + "install", "--batch", plugin.toString()) + ); + + startElasticsearchProcess(); } - private void startElasticsearchProcess(Path distroArtifact) { - logger.info("Running `bin/elasticsearch` in `{}` for {}", workingDir, this); + private void runElaticsearchBinScript(String tool, String... args) { + services.loggedExec(spec -> { + spec.setEnvironment(getESEnvironment()); + spec.workingDir(workingDir); + spec.executable( + OS.conditionalString() + .onUnix(() -> "./bin/" + tool) + .onWindows(() -> "cmd") + .supply() + ); + spec.args( + OS.>conditional() + .onWindows(() -> { + ArrayList result = new ArrayList<>(); + result.add("/c"); + result.add("bin\\" + tool + ".bat"); + for (String arg : args) { + result.add(arg); + } + return result; + }) + .onUnix(() -> Arrays.asList(args)) + .supply() + ); + }); + } + + private Map getESEnvironment() { + Map environment= new HashMap<>(); + environment.put("JAVA_HOME", getJavaHome().getAbsolutePath()); + environment.put("ES_PATH_CONF", configFile.getParent().toString()); + environment.put("ES_JAVA_OPTS", "-Xms512m -Xmx512m"); + environment.put("ES_TMPDIR", tmpDir.toString()); + // Windows requires this as it defaults to `c:\windows` despite ES_TMPDIR + + environment.put("TMP", tmpDir.toString()); + return environment; + } + + private void startElasticsearchProcess() { final ProcessBuilder processBuilder = new ProcessBuilder(); - if (OperatingSystem.current().isWindows()) { - processBuilder.command( - "cmd", "/c", - distroArtifact.resolve("\\bin\\elasticsearch.bat").toAbsolutePath().toString() - ); - } else { - processBuilder.command( - distroArtifact.resolve("bin/elasticsearch").toAbsolutePath().toString() - ); - } + + List command = OS.>conditional() + .onUnix(() -> Arrays.asList("./bin/elasticsearch")) + .onWindows(() -> Arrays.asList("cmd", "/c", "bin\\elasticsearch.bat")) + .supply(); + processBuilder.command(command); + processBuilder.directory(workingDir.toFile()); + Map environment = processBuilder.environment(); + // Don't inherit anything from the environment for as that would lack reproducibility + environment.clear(); + environment.putAll(getESEnvironment()); + // don't buffer all in memory, make sure we don't block on the default pipes + processBuilder.redirectError(ProcessBuilder.Redirect.appendTo(esStderrFile.toFile())); + processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(esStdoutFile.toFile())); + logger.info("Running `{}` in `{}` for {} env: {}", command, workingDir, this, environment); try { - processBuilder.directory(workingDir.toFile()); - Map environment = processBuilder.environment(); - // Don't inherit anything from the environment for as that would lack reproductability - environment.clear(); - environment.put("JAVA_HOME", getJavaHome().getAbsolutePath()); - environment.put("ES_PATH_CONF", configFile.getParent().toAbsolutePath().toString()); - environment.put("ES_JAVA_OPTIONS", "-Xms512m -Xmx512m"); - // don't buffer all in memory, make sure we don't block on the default pipes - processBuilder.redirectError(ProcessBuilder.Redirect.appendTo(esStderrFile.toFile())); - processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(esStdoutFile.toFile())); esProcess = processBuilder.start(); } catch (IOException e) { throw new TestClustersException("Failed to start ES process for " + this, e); @@ -311,16 +381,19 @@ public class ElasticsearchNode { } } - private void configure() { - try { - Files.createDirectories(configFile.getParent()); - Files.createDirectories(confPathRepo); - Files.createDirectories(confPathData); - Files.createDirectories(confPathLogs); - } catch (IOException e) { - throw new UncheckedIOException(e); - } + private void createWorkingDir(Path distroExtractDir) throws IOException { + services.sync(spec -> { + spec.from(distroExtractDir.toFile()); + spec.into(workingDir.toFile()); + }); + Files.createDirectories(configFile.getParent()); + Files.createDirectories(confPathRepo); + Files.createDirectories(confPathData); + Files.createDirectories(confPathLogs); + Files.createDirectories(tmpDir); + } + private void createConfiguration() { LinkedHashMap config = new LinkedHashMap<>(); String nodeName = safeName(name); diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/TestClustersPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/TestClustersPlugin.java index 56ff501a388..ee9e1dc133a 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/TestClustersPlugin.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/testclusters/TestClustersPlugin.java @@ -25,7 +25,6 @@ import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; -import org.gradle.api.artifacts.component.ComponentArtifactIdentifier; import org.gradle.api.execution.TaskActionListener; import org.gradle.api.execution.TaskExecutionListener; import org.gradle.api.file.FileTree; @@ -91,20 +90,6 @@ public class TestClustersPlugin implements Plugin { "Internal helper configuration used by cluster configuration to download " + "ES distributions and plugins." ); - helperConfiguration.getIncoming().afterResolve(resolvableDependencies -> { - Set nonZipComponents = resolvableDependencies.getArtifacts() - .getArtifacts() - .stream() - .filter(artifact -> artifact.getFile().getName().endsWith(".zip") == false) - .map(artifact -> artifact.getId()) - .collect(Collectors.toSet()); - - if(nonZipComponents.isEmpty() == false) { - throw new IllegalStateException("Dependencies with non-zip artifacts found in configuration '" + - TestClustersPlugin.HELPER_CONFIGURATION_NAME + "': " + nonZipComponents - ); - } - }); // When running in the Daemon it's possible for this to hold references to past usedClusters.clear(); @@ -120,10 +105,18 @@ public class TestClustersPlugin implements Plugin { sync.from((Callable>) () -> helperConfiguration.getFiles() .stream() - .map(project::zipTree) + .map(file -> { + if (file.getName().endsWith(".zip")) { + return project.zipTree(file); + } else if (file.getName().endsWith("tar.gz")) { + return project.tarTree(file); + } else { + throw new IllegalArgumentException("Can't extract " + file + " unknown file extension"); + } + }) .collect(Collectors.toList()) ); - sync.into(new File(getTestClustersConfigurationExtractDir(project), "zip")); + sync.into(getTestClustersConfigurationExtractDir(project)); }); // When we know what tasks will run, we claim the clusters of those task to differentiate between clusters @@ -302,9 +295,11 @@ public class TestClustersPlugin implements Plugin { project.afterEvaluate(ip -> container.forEach(esNode -> { // declare dependencies against artifacts needed by cluster formation. String dependency = String.format( - "org.elasticsearch.distribution.zip:%s:%s@zip", - esNode.getDistribution().getFileName(), - esNode.getVersion() + "unused:%s:%s:%s@%s", + esNode.getDistribution().getArtifactName(), + esNode.getVersion(), + esNode.getDistribution().getClassifier(), + esNode.getDistribution().getFileExtension() ); logger.info("Cluster {} depends on {}", esNode.getName(), dependency); rootProject.getDependencies().add(HELPER_CONFIGURATION_NAME, dependency); diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/testfixtures/TestFixturesPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/testfixtures/TestFixturesPlugin.java index 3dfccaf4350..59cb851974c 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/testfixtures/TestFixturesPlugin.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/testfixtures/TestFixturesPlugin.java @@ -21,6 +21,7 @@ package org.elasticsearch.gradle.testfixtures; import com.avast.gradle.dockercompose.ComposeExtension; import com.avast.gradle.dockercompose.DockerComposePlugin; import com.avast.gradle.dockercompose.tasks.ComposeUp; +import org.elasticsearch.gradle.OS; import org.elasticsearch.gradle.precommit.JarHellTask; import org.elasticsearch.gradle.precommit.TestingConventionsTasks; import org.elasticsearch.gradle.precommit.ThirdPartyAuditTask; @@ -32,7 +33,6 @@ import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.ExtraPropertiesExtension; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.TaskContainer; -import org.gradle.internal.os.OperatingSystem; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -157,7 +157,7 @@ public class TestFixturesPlugin implements Plugin { @Input public boolean dockerComposeSupported(Project project) { - if (OperatingSystem.current().isWindows()) { + if (OS.current().equals(OS.WINDOWS)) { return false; } final boolean hasDockerCompose = project.file("/usr/local/bin/docker-compose").exists() || diff --git a/buildSrc/src/test/java/org/elasticsearch/gradle/testclusters/TestClustersPluginIT.java b/buildSrc/src/test/java/org/elasticsearch/gradle/testclusters/TestClustersPluginIT.java index bb69665026b..ffd21b18f67 100644 --- a/buildSrc/src/test/java/org/elasticsearch/gradle/testclusters/TestClustersPluginIT.java +++ b/buildSrc/src/test/java/org/elasticsearch/gradle/testclusters/TestClustersPluginIT.java @@ -21,11 +21,9 @@ package org.elasticsearch.gradle.testclusters; import org.elasticsearch.gradle.test.GradleIntegrationTestCase; import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.GradleRunner; -import org.junit.Ignore; import java.util.Arrays; -@Ignore // Awaiting a fix in https://github.com/elastic/elasticsearch/issues/37889. public class TestClustersPluginIT extends GradleIntegrationTestCase { public void testListClusters() { @@ -152,6 +150,14 @@ public class TestClustersPluginIT extends GradleIntegrationTestCase { ); } + public void testPluginInstalled() { + BuildResult result = getTestClustersRunner(":printLog").build(); + assertTaskSuccessful(result, ":printLog"); + assertStartedAndStoppedOnce(result); + assertOutputContains(result.getOutput(), "-> Installed dummy"); + assertOutputContains(result.getOutput(), "loaded plugin [dummy]"); + } + private void assertNotStarted(BuildResult result) { assertOutputDoesNotContain( result.getOutput(), @@ -178,4 +184,6 @@ public class TestClustersPluginIT extends GradleIntegrationTestCase { "Stopping `node{::myTestCluster}`" ); } + + } diff --git a/buildSrc/src/testKit/testclusters/build.gradle b/buildSrc/src/testKit/testclusters/build.gradle index d02240c0ad2..b1d82fff0b1 100644 --- a/buildSrc/src/testKit/testclusters/build.gradle +++ b/buildSrc/src/testKit/testclusters/build.gradle @@ -5,6 +5,9 @@ plugins { allprojects { all -> repositories { + flatDir { + dir System.getProperty("test.local-test-downloads-path") + } maven { url System.getProperty("local.repo.path") } @@ -14,6 +17,7 @@ allprojects { all -> url "http://s3.amazonaws.com/download.elasticsearch.org/lucenesnapshots/" + luceneSnapshotRevision } } + jcenter() } @@ -22,9 +26,10 @@ allprojects { all -> all.testClusters { myTestCluster { - distribution = 'ZIP' + distribution = 'DEFAULT' version = System.getProperty("test.version_under_test") javaHome = file(System.getProperty('java.home')) + plugin file("${project(":dummyPlugin").buildDir}/distributions/dummy-${version}.zip") } } @@ -40,6 +45,19 @@ allprojects { all -> println "$path: Cluster running @ ${testClusters.myTestCluster.httpSocketURI}" } } + syncTestClustersArtifacts { + dependsOn ":dummyPlugin:bundlePlugin" + } + } +} + +task printLog { + useCluster testClusters.myTestCluster + doFirst { + println "$path: Cluster running @ ${testClusters.myTestCluster.httpSocketURI}" + testClusters.myTestCluster.logLines().each { + println it + } } } @@ -77,6 +95,6 @@ task illegalConfigAlter { useCluster testClusters.myTestCluster doFirst { println "Going to alter configuration after use" - testClusters.myTestCluster.distribution = 'ZIP_OSS' + testClusters.myTestCluster.distribution = 'OSS' } } diff --git a/buildSrc/src/testKit/testclusters/dummyPlugin/build.gradle b/buildSrc/src/testKit/testclusters/dummyPlugin/build.gradle new file mode 100644 index 00000000000..73833fc80cc --- /dev/null +++ b/buildSrc/src/testKit/testclusters/dummyPlugin/build.gradle @@ -0,0 +1,11 @@ +apply plugin: 'elasticsearch.esplugin' + +version = System.getProperty("test.version_under_test") + +esplugin { + name 'dummy' + description 'A dummy plugin used for testing' + classname 'DummyPlugin' + licenseFile rootProject.file('empty.txt') + noticeFile rootProject.file('empty.txt') +} \ No newline at end of file diff --git a/buildSrc/src/testKit/testclusters/dummyPlugin/src/main/java/DummyPlugin.java b/buildSrc/src/testKit/testclusters/dummyPlugin/src/main/java/DummyPlugin.java new file mode 100644 index 00000000000..fff45b7365e --- /dev/null +++ b/buildSrc/src/testKit/testclusters/dummyPlugin/src/main/java/DummyPlugin.java @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.common.settings.Settings; + +import java.nio.file.Path; + +public class DummyPlugin extends Plugin { + + public DummyPlugin(final Settings settings, final Path configPath) { + } + +} diff --git a/buildSrc/src/testKit/testclusters/empty.txt b/buildSrc/src/testKit/testclusters/empty.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/buildSrc/src/testKit/testclusters/settings.gradle b/buildSrc/src/testKit/testclusters/settings.gradle index 6549a93801b..0b90220482d 100644 --- a/buildSrc/src/testKit/testclusters/settings.gradle +++ b/buildSrc/src/testKit/testclusters/settings.gradle @@ -1,4 +1,5 @@ include 'dummyPlugin' include ':alpha' include ':bravo' -include ':charlie' \ No newline at end of file +include ':charlie' +include 'dummyPlugin' \ No newline at end of file