diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 94f7da08e60..5775b2b6323 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -23,15 +23,6 @@ plugins { id 'groovy' } -gradlePlugin { - plugins { - simplePlugin { - id = 'elasticsearch.clusterformation' - implementationClass = 'org.elasticsearch.gradle.clusterformation.ClusterformationPlugin' - } - } -} - group = 'org.elasticsearch.gradle' String minimumGradleVersion = file('src/main/resources/minimumGradleVersion').text.trim() diff --git a/buildSrc/src/main/java/org/elasticsearch/GradleServicesAdapter.java b/buildSrc/src/main/java/org/elasticsearch/GradleServicesAdapter.java deleted file mode 100644 index 6d256ba0449..00000000000 --- a/buildSrc/src/main/java/org/elasticsearch/GradleServicesAdapter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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; - -import org.gradle.api.Action; -import org.gradle.api.Project; -import org.gradle.api.file.CopySpec; -import org.gradle.api.file.FileTree; -import org.gradle.api.tasks.WorkResult; -import org.gradle.process.ExecResult; -import org.gradle.process.JavaExecSpec; - -import java.io.File; - -/** - * Facilitate access to Gradle services without a direct dependency on Project. - * - * In a future release Gradle will offer service injection, this adapter plays that role until that time. - * It exposes the service methods that are part of the public API as the classes implementing them are not. - * Today service injection is not available for - * extensions. - * - * Everything exposed here must be thread safe. That is the very reason why project is not passed in directly. - */ -public class GradleServicesAdapter { - - public final Project project; - - public GradleServicesAdapter(Project project) { - this.project = project; - } - - public static GradleServicesAdapter getInstance(Project project) { - return new GradleServicesAdapter(project); - } - - public WorkResult copy(Action action) { - return project.copy(action); - } - - public WorkResult sync(Action action) { - return project.sync(action); - } - - public ExecResult javaexec(Action action) { - return project.javaexec(action); - } - - public FileTree zipTree(File zipPath) { - return project.zipTree(zipPath); - } -} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/Distribution.java b/buildSrc/src/main/java/org/elasticsearch/gradle/Distribution.java deleted file mode 100644 index c926e70b3f7..00000000000 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/Distribution.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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; - -public enum Distribution { - - INTEG_TEST("integ-test-zip"), - ZIP("zip"), - ZIP_OSS("zip-oss"); - - private final String name; - - Distribution(String name) { - this.name = name; - } - - public String getName() { - return name; - } -} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ClusterFormationTaskExecutionListener.java b/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ClusterFormationTaskExecutionListener.java deleted file mode 100644 index e4a50d77599..00000000000 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ClusterFormationTaskExecutionListener.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.clusterformation; - -import org.gradle.api.Task; -import org.gradle.api.execution.TaskActionListener; -import org.gradle.api.execution.TaskExecutionListener; -import org.gradle.api.tasks.TaskState; - -public class ClusterFormationTaskExecutionListener implements TaskExecutionListener, TaskActionListener { - @Override - public void afterExecute(Task task, TaskState state) { - // always unclaim the cluster, even if _this_ task is up-to-date, as others might not have been and caused the - // cluster to start. - ClusterFormationTaskExtension.getForTask(task).getClaimedClusters().forEach(ElasticsearchConfiguration::unClaimAndStop); - } - - @Override - public void beforeActions(Task task) { - // we only start the cluster before the actions, so we'll not start it if the task is up-to-date - ClusterFormationTaskExtension.getForTask(task).getClaimedClusters().forEach(ElasticsearchConfiguration::start); - } - - @Override - public void beforeExecute(Task task) { - } - - @Override - public void afterActions(Task task) { - } -} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ClusterFormationTaskExtension.java b/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ClusterFormationTaskExtension.java deleted file mode 100644 index 0cafd2d4beb..00000000000 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ClusterFormationTaskExtension.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.clusterformation; - -import org.gradle.api.Task; -import org.gradle.api.logging.Logger; -import org.gradle.api.logging.Logging; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class ClusterFormationTaskExtension { - - private final Task task; - - private final List claimedClusters = new ArrayList<>(); - - private final Logger logger = Logging.getLogger(ClusterFormationTaskExtension.class); - - public ClusterFormationTaskExtension(Task task) { - this.task = task; - } - - public void call(ElasticsearchConfiguration cluster) { - // not likely to configure the same task from multiple threads as of Gradle 4.7, but it's the right thing to do - synchronized (claimedClusters) { - if (claimedClusters.contains(cluster)) { - logger.warn("{} already claimed cluster {} will not claim it again", - task.getPath(), cluster.getName() - ); - return; - } - claimedClusters.add(cluster); - } - logger.info("CF: the {} task will use cluster: {}", task.getName(), cluster.getName()); - } - - public List getClaimedClusters() { - synchronized (claimedClusters) { - return Collections.unmodifiableList(claimedClusters); - } - } - - static ClusterFormationTaskExtension getForTask(Task task) { - return task.getExtensions().getByType(ClusterFormationTaskExtension.class); - } -} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ClusterformationPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ClusterformationPlugin.java deleted file mode 100644 index e79f67c0fd5..00000000000 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ClusterformationPlugin.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.clusterformation; - -import groovy.lang.Closure; -import org.elasticsearch.GradleServicesAdapter; -import org.gradle.api.NamedDomainObjectContainer; -import org.gradle.api.Plugin; -import org.gradle.api.Project; -import org.gradle.api.Task; -import org.gradle.api.logging.Logger; -import org.gradle.api.logging.Logging; -import org.gradle.api.plugins.ExtraPropertiesExtension; - -public class ClusterformationPlugin implements Plugin { - - public static final String LIST_TASK_NAME = "listElasticSearchClusters"; - public static final String EXTENSION_NAME = "elasticSearchClusters"; - public static final String TASK_EXTENSION_NAME = "useClusterExt"; - - private final Logger logger = Logging.getLogger(ClusterformationPlugin.class); - - @Override - public void apply(Project project) { - NamedDomainObjectContainer container = project.container( - ElasticsearchNode.class, - (name) -> new ElasticsearchNode(name, GradleServicesAdapter.getInstance(project)) - ); - project.getExtensions().add(EXTENSION_NAME, container); - - Task listTask = project.getTasks().create(LIST_TASK_NAME); - listTask.setGroup("ES cluster formation"); - listTask.setDescription("Lists all ES clusters configured for this project"); - listTask.doLast((Task task) -> - container.forEach((ElasticsearchConfiguration cluster) -> - logger.lifecycle(" * {}: {}", cluster.getName(), cluster.getDistribution()) - ) - ); - - // register an extension for all current and future tasks, so that any task can declare that it wants to use a - // specific cluster. - project.getTasks().all((Task task) -> { - ClusterFormationTaskExtension taskExtension = task.getExtensions().create( - TASK_EXTENSION_NAME, ClusterFormationTaskExtension.class, task - ); - // Gradle doesn't look for extensions that might implement `call` and instead only looks for task methods - // work around by creating a closure in the extra properties extensions which does work - task.getExtensions().findByType(ExtraPropertiesExtension.class) - .set( - "useCluster", - new Closure(this, this) { - public void doCall(ElasticsearchConfiguration conf) { - taskExtension.call(conf); - } - } - ); - }); - - // Make sure we only claim the clusters for the tasks that will actually execute - project.getGradle().getTaskGraph().whenReady(taskExecutionGraph -> - taskExecutionGraph.getAllTasks().forEach( - task -> ClusterFormationTaskExtension.getForTask(task).getClaimedClusters().forEach( - ElasticsearchConfiguration::claim - ) - ) - ); - - // create the listener to start the clusters on-demand and terminate when no longer claimed. - // we need to use a task execution listener, as tasl - project.getGradle().addListener(new ClusterFormationTaskExecutionListener()); - } - -} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ElasticsearchConfiguration.java b/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ElasticsearchConfiguration.java deleted file mode 100644 index 913d88e9fa1..00000000000 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ElasticsearchConfiguration.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.clusterformation; - -import org.elasticsearch.gradle.Distribution; -import org.elasticsearch.gradle.Version; - -import java.util.concurrent.Future; - -public interface ElasticsearchConfiguration { - String getName(); - - Version getVersion(); - - void setVersion(Version version); - - default void setVersion(String version) { - setVersion(Version.fromString(version)); - } - - Distribution getDistribution(); - - void setDistribution(Distribution distribution); - - void claim(); - - Future start(); - - void unClaimAndStop(); -} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ElasticsearchNode.java b/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ElasticsearchNode.java deleted file mode 100644 index 8b78fc2b627..00000000000 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/clusterformation/ElasticsearchNode.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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.clusterformation; - -import org.elasticsearch.GradleServicesAdapter; -import org.elasticsearch.gradle.Distribution; -import org.elasticsearch.gradle.Version; -import org.gradle.api.logging.Logger; -import org.gradle.api.logging.Logging; - -import java.util.Objects; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -public class ElasticsearchNode implements ElasticsearchConfiguration { - - private final String name; - private final GradleServicesAdapter services; - private final AtomicInteger noOfClaims = new AtomicInteger(); - private final AtomicBoolean started = new AtomicBoolean(false); - private final Logger logger = Logging.getLogger(ElasticsearchNode.class); - - private Distribution distribution; - private Version version; - - public ElasticsearchNode(String name, GradleServicesAdapter services) { - this.name = name; - this.services = services; - } - - @Override - public String getName() { - return name; - } - - @Override - public Version getVersion() { - return version; - } - - @Override - public void setVersion(Version version) { - checkNotRunning(); - this.version = version; - } - - @Override - public Distribution getDistribution() { - return distribution; - } - - @Override - public void setDistribution(Distribution distribution) { - checkNotRunning(); - this.distribution = distribution; - } - - @Override - public void claim() { - noOfClaims.incrementAndGet(); - } - - /** - * Start the cluster if not running. Does nothing if the cluster is already running. - * - * @return future of thread running in the background - */ - @Override - public Future start() { - if (started.getAndSet(true)) { - logger.lifecycle("Already started cluster: {}", name); - } else { - logger.lifecycle("Starting cluster: {}", name); - } - return null; - } - - /** - * Stops a running cluster if it's not claimed. Does nothing otherwise. - */ - @Override - public void unClaimAndStop() { - int decrementedClaims = noOfClaims.decrementAndGet(); - if (decrementedClaims > 0) { - logger.lifecycle("Not stopping {}, since cluster still has {} claim(s)", name, decrementedClaims); - return; - } - if (started.get() == false) { - logger.lifecycle("Asked to unClaimAndStop, but cluster was not running: {}", name); - return; - } - logger.lifecycle("Stopping {}, number of claims is {}", name, decrementedClaims); - } - - private void checkNotRunning() { - if (started.get()) { - throw new IllegalStateException("Configuration can not be altered while running "); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ElasticsearchNode that = (ElasticsearchNode) o; - return Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(name); - } -} diff --git a/buildSrc/src/test/java/org/elasticsearch/gradle/clusterformation/ClusterformationPluginIT.java b/buildSrc/src/test/java/org/elasticsearch/gradle/clusterformation/ClusterformationPluginIT.java deleted file mode 100644 index c690557537d..00000000000 --- a/buildSrc/src/test/java/org/elasticsearch/gradle/clusterformation/ClusterformationPluginIT.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.clusterformation; - -import org.elasticsearch.gradle.test.GradleIntegrationTestCase; -import org.gradle.testkit.runner.BuildResult; -import org.gradle.testkit.runner.GradleRunner; -import org.gradle.testkit.runner.TaskOutcome; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -public class ClusterformationPluginIT extends GradleIntegrationTestCase { - - public void testListClusters() { - BuildResult result = GradleRunner.create() - .withProjectDir(getProjectDir("clusterformation")) - .withArguments("listElasticSearchClusters", "-s") - .withPluginClasspath() - .build(); - - assertEquals(TaskOutcome.SUCCESS, result.task(":listElasticSearchClusters").getOutcome()); - assertOutputContains( - result.getOutput(), - " * myTestCluster:" - ); - - } - - public void testUseClusterByOne() { - BuildResult result = GradleRunner.create() - .withProjectDir(getProjectDir("clusterformation")) - .withArguments("user1", "-s") - .withPluginClasspath() - .build(); - - assertEquals(TaskOutcome.SUCCESS, result.task(":user1").getOutcome()); - assertOutputContains( - result.getOutput(), - "Starting cluster: myTestCluster", - "Stopping myTestCluster, number of claims is 0" - ); - } - - public void testUseClusterByOneWithDryRun() { - BuildResult result = GradleRunner.create() - .withProjectDir(getProjectDir("clusterformation")) - .withArguments("user1", "-s", "--dry-run") - .withPluginClasspath() - .build(); - - assertNull(result.task(":user1")); - assertOutputDoesNotContain( - result.getOutput(), - "Starting cluster: myTestCluster", - "Stopping myTestCluster, number of claims is 0" - ); - } - - public void testUseClusterByTwo() { - BuildResult result = GradleRunner.create() - .withProjectDir(getProjectDir("clusterformation")) - .withArguments("user1", "user2", "-s") - .withPluginClasspath() - .build(); - - assertEquals(TaskOutcome.SUCCESS, result.task(":user1").getOutcome()); - assertEquals(TaskOutcome.SUCCESS, result.task(":user2").getOutcome()); - assertOutputContains( - result.getOutput(), - "Starting cluster: myTestCluster", - "Not stopping myTestCluster, since cluster still has 1 claim(s)", - "Stopping myTestCluster, number of claims is 0" - ); - } - - public void testUseClusterByUpToDateTask() { - BuildResult result = GradleRunner.create() - .withProjectDir(getProjectDir("clusterformation")) - .withArguments("upToDate1", "upToDate2", "-s") - .withPluginClasspath() - .build(); - - assertEquals(TaskOutcome.UP_TO_DATE, result.task(":upToDate1").getOutcome()); - assertEquals(TaskOutcome.UP_TO_DATE, result.task(":upToDate2").getOutcome()); - assertOutputContains( - result.getOutput(), - "Not stopping myTestCluster, since cluster still has 1 claim(s)", - "cluster was not running: myTestCluster" - ); - assertOutputDoesNotContain(result.getOutput(), "Starting cluster: myTestCluster"); - } - - public void testUseClusterBySkippedTask() { - BuildResult result = GradleRunner.create() - .withProjectDir(getProjectDir("clusterformation")) - .withArguments("skipped1", "skipped2", "-s") - .withPluginClasspath() - .build(); - - assertEquals(TaskOutcome.SKIPPED, result.task(":skipped1").getOutcome()); - assertEquals(TaskOutcome.SKIPPED, result.task(":skipped2").getOutcome()); - assertOutputContains( - result.getOutput(), - "Not stopping myTestCluster, since cluster still has 1 claim(s)", - "cluster was not running: myTestCluster" - ); - assertOutputDoesNotContain(result.getOutput(), "Starting cluster: myTestCluster"); - } - - public void tetUseClusterBySkippedAndWorkingTask() { - BuildResult result = GradleRunner.create() - .withProjectDir(getProjectDir("clusterformation")) - .withArguments("skipped1", "user1", "-s") - .withPluginClasspath() - .build(); - - assertEquals(TaskOutcome.SKIPPED, result.task(":skipped1").getOutcome()); - assertEquals(TaskOutcome.SUCCESS, result.task(":user1").getOutcome()); - assertOutputContains( - result.getOutput(), - "> Task :user1", - "Starting cluster: myTestCluster", - "Stopping myTestCluster, number of claims is 0" - ); - } - -} diff --git a/buildSrc/src/testKit/clusterformation/build.gradle b/buildSrc/src/testKit/clusterformation/build.gradle deleted file mode 100644 index ae9dd8a2c33..00000000000 --- a/buildSrc/src/testKit/clusterformation/build.gradle +++ /dev/null @@ -1,41 +0,0 @@ -plugins { - id 'elasticsearch.clusterformation' -} - -elasticSearchClusters { - myTestCluster { - distribution = 'ZIP' - } -} - -task user1 { - useCluster elasticSearchClusters.myTestCluster - doLast { - println "user1 executing" - } -} - -task user2 { - useCluster elasticSearchClusters.myTestCluster - doLast { - println "user2 executing" - } -} - -task upToDate1 { - useCluster elasticSearchClusters.myTestCluster -} - -task upToDate2 { - useCluster elasticSearchClusters.myTestCluster -} - -task skipped1 { - enabled = false - useCluster elasticSearchClusters.myTestCluster -} - -task skipped2 { - enabled = false - useCluster elasticSearchClusters.myTestCluster -}