20
20
21
21
import groovy .lang .Closure ;
22
22
import org .elasticsearch .gradle .BwcVersions ;
23
- import org .elasticsearch .gradle .Distribution ;
24
23
import org .elasticsearch .gradle .Version ;
24
+ import org .elasticsearch .gradle .tool .Boilerplate ;
25
25
import org .gradle .api .Action ;
26
26
import org .gradle .api .NamedDomainObjectContainer ;
27
27
import org .gradle .api .Plugin ;
28
28
import org .gradle .api .Project ;
29
29
import org .gradle .api .Task ;
30
30
import org .gradle .api .artifacts .Configuration ;
31
+ import org .gradle .api .artifacts .repositories .MavenArtifactRepository ;
32
+ import org .gradle .api .credentials .HttpHeaderCredentials ;
31
33
import org .gradle .api .execution .TaskActionListener ;
32
34
import org .gradle .api .execution .TaskExecutionListener ;
33
- import org .gradle .api .file .FileCollection ;
34
35
import org .gradle .api .file .FileTree ;
35
36
import org .gradle .api .logging .Logger ;
36
37
import org .gradle .api .logging .Logging ;
46
47
import java .util .List ;
47
48
import java .util .Map ;
48
49
import java .util .Set ;
49
- import java .util .concurrent .Callable ;
50
50
import java .util .concurrent .ExecutorService ;
51
51
import java .util .concurrent .Executors ;
52
52
import java .util .concurrent .TimeUnit ;
@@ -56,7 +56,7 @@ public class TestClustersPlugin implements Plugin<Project> {
56
56
57
57
private static final String LIST_TASK_NAME = "listTestClusters" ;
58
58
private static final String NODE_EXTENSION_NAME = "testClusters" ;
59
- private static final String HELPER_CONFIGURATION_NAME = "testclusters" ;
59
+ private static final String HELPER_CONFIGURATION_PREFIX = "testclusters" ;
60
60
private static final String SYNC_ARTIFACTS_TASK_NAME = "syncTestClustersArtifacts" ;
61
61
private static final int EXECUTOR_SHUTDOWN_TIMEOUT = 1 ;
62
62
private static final TimeUnit EXECUTOR_SHUTDOWN_TIMEOUT_UNIT = TimeUnit .MINUTES ;
@@ -69,6 +69,10 @@ public class TestClustersPlugin implements Plugin<Project> {
69
69
private final Thread shutdownHook = new Thread (this ::shutDownAllClusters );
70
70
private ExecutorService executorService = Executors .newSingleThreadExecutor ();
71
71
72
+ public static String getHelperConfigurationName (String version ) {
73
+ return HELPER_CONFIGURATION_PREFIX + "-" + version ;
74
+ }
75
+
72
76
@ Override
73
77
public void apply (Project project ) {
74
78
Project rootProject = project .getRootProject ();
@@ -82,47 +86,6 @@ public void apply(Project project) {
82
86
// create DSL for tasks to mark clusters these use
83
87
createUseClusterTaskExtension (project , container );
84
88
85
- if (rootProject .getConfigurations ().findByName (HELPER_CONFIGURATION_NAME ) == null ) {
86
- // We use a single configuration on the root project to resolve all testcluster dependencies ( like distros )
87
- // at once, only once without the need to repeat it for each project. This pays off assuming that most
88
- // projects use the same dependencies.
89
- Configuration helperConfiguration = project .getRootProject ().getConfigurations ().create (HELPER_CONFIGURATION_NAME );
90
- helperConfiguration .setDescription (
91
- "Internal helper configuration used by cluster configuration to download " +
92
- "ES distributions and plugins."
93
- );
94
-
95
- // We have a single task to sync the helper configuration to "artifacts dir"
96
- // the clusters will look for artifacts there based on the naming conventions.
97
- // Tasks that use a cluster will add this as a dependency automatically so it's guaranteed to run early in
98
- // the build.
99
- rootProject .getTasks ().create (SYNC_ARTIFACTS_TASK_NAME , sync -> {
100
- sync .getInputs ().files ((Callable <FileCollection >) helperConfiguration ::getAsFileTree );
101
- sync .getOutputs ().dir (new File (project .getRootProject ().getBuildDir (), "testclusters/extract" ));
102
- // NOTE: Gradle doesn't allow a lambda here ( fails at runtime )
103
- sync .doLast (new Action <Task >() {
104
- @ Override
105
- public void execute (Task task ) {
106
- project .sync (spec ->
107
- helperConfiguration .getResolvedConfiguration ().getResolvedArtifacts ().forEach (resolvedArtifact -> {
108
- final FileTree files ;
109
- File file = resolvedArtifact .getFile ();
110
- if (file .getName ().endsWith (".zip" )) {
111
- files = project .zipTree (file );
112
- } else if (file .getName ().endsWith ("tar.gz" )) {
113
- files = project .tarTree (file );
114
- } else {
115
- throw new IllegalArgumentException ("Can't extract " + file + " unknown file extension" );
116
- }
117
- spec .from (files ).into (new File (project .getRootProject ().getBuildDir (), "testclusters/extract" ) + "/" +
118
- resolvedArtifact .getModuleVersion ().getId ().getGroup ()
119
- );
120
- }));
121
- }
122
- });
123
- });
124
- }
125
-
126
89
// When we know what tasks will run, we claim the clusters of those task to differentiate between clusters
127
90
// that are defined in the build script and the ones that will actually be used in this invocation of gradle
128
91
// we use this information to determine when the last task that required the cluster executed so that we can
@@ -143,6 +106,10 @@ public void execute(Task task) {
143
106
autoConfigureClusterDependencies (project , rootProject , container );
144
107
}
145
108
109
+ private static File getExtractDir (Project project ) {
110
+ return new File (project .getRootProject ().getBuildDir (), "testclusters/extract/" );
111
+ }
112
+
146
113
private NamedDomainObjectContainer <ElasticsearchCluster > createTestClustersContainerExtension (Project project ) {
147
114
// Create an extensions that allows describing clusters
148
115
NamedDomainObjectContainer <ElasticsearchCluster > container = project .container (
@@ -290,12 +257,59 @@ private static void autoConfigureClusterDependencies(
290
257
Project rootProject ,
291
258
NamedDomainObjectContainer <ElasticsearchCluster > container
292
259
) {
260
+ // Download integ test distribution from maven central
261
+ MavenArtifactRepository mavenCentral = project .getRepositories ().mavenCentral ();
262
+ mavenCentral .content (spec -> {
263
+ spec .includeGroupByRegex ("org\\ .elasticsearch\\ .distribution\\ ..*" );
264
+ });
265
+
266
+ // Other distributions from the download service
267
+ project .getRepositories ().add (
268
+ project .getRepositories ().ivy (spec -> {
269
+ spec .setUrl ("https://artifacts.elastic.co/downloads" );
270
+ spec .patternLayout (p -> p .artifact ("elasticsearch/[module]-[revision](-[classifier]).[ext]" ));
271
+ HttpHeaderCredentials headerConfig = spec .getCredentials (HttpHeaderCredentials .class );
272
+ headerConfig .setName ("X-Elastic-No-KPI" );
273
+ headerConfig .setValue ("1" );
274
+ spec .content (c -> c .includeGroupByRegex ("org\\ .elasticsearch\\ .distribution\\ ..*" ));
275
+ })
276
+ );
277
+
278
+ // We have a single task to sync the helper configuration to "artifacts dir"
279
+ // the clusters will look for artifacts there based on the naming conventions.
280
+ // Tasks that use a cluster will add this as a dependency automatically so it's guaranteed to run early in
281
+ // the build.
282
+ Task sync = Boilerplate .maybeCreate (rootProject .getTasks (), SYNC_ARTIFACTS_TASK_NAME , onCreate -> {
283
+ onCreate .getOutputs ().dir (getExtractDir (rootProject ));
284
+ // NOTE: Gradle doesn't allow a lambda here ( fails at runtime )
285
+ onCreate .doFirst (new Action <Task >() {
286
+ @ Override
287
+ public void execute (Task task ) {
288
+ // Clean up the extract dir first to make sure we have no stale files from older
289
+ // previous builds of the same distribution
290
+ project .delete (getExtractDir (rootProject ));
291
+ }
292
+ });
293
+ });
294
+
293
295
// When the project evaluated we know of all tasks that use clusters.
294
296
// Each of these have to depend on the artifacts being synced.
295
297
// We need afterEvaluate here despite the fact that container is a domain object, we can't implement this with
296
298
// all because fields can change after the fact.
297
299
project .afterEvaluate (ip -> container .forEach (esCluster ->
298
300
esCluster .eachVersionedDistribution ((version , distribution ) -> {
301
+ Configuration helperConfiguration = Boilerplate .maybeCreate (
302
+ rootProject .getConfigurations (),
303
+ getHelperConfigurationName (version ),
304
+ onCreate ->
305
+ // We use a single configuration on the root project to resolve all testcluster dependencies ( like distros )
306
+ // at once, only once without the need to repeat it for each project. This pays off assuming that most
307
+ // projects use the same dependencies.
308
+ onCreate .setDescription (
309
+ "Internal helper configuration used by cluster configuration to download " +
310
+ "ES distributions and plugins for " + version
311
+ )
312
+ );
299
313
BwcVersions .UnreleasedVersionInfo unreleasedInfo ;
300
314
final List <Version > unreleased ;
301
315
{
@@ -320,29 +334,42 @@ private static void autoConfigureClusterDependencies(
320
334
projectNotation .put ("path" , unreleasedInfo .gradleProjectPath );
321
335
projectNotation .put ("configuration" , distribution .getLiveConfiguration ());
322
336
rootProject .getDependencies ().add (
323
- HELPER_CONFIGURATION_NAME ,
337
+ helperConfiguration . getName () ,
324
338
project .getDependencies ().project (projectNotation )
325
339
);
326
340
} else {
327
- if (distribution .equals (Distribution .INTEG_TEST )) {
328
- rootProject .getDependencies ().add (
329
- HELPER_CONFIGURATION_NAME , "org.elasticsearch.distribution.integ-test-zip:elasticsearch:" + version
330
- );
331
- } else {
332
- // declare dependencies to be downloaded from the download service.
333
- // The BuildPlugin sets up the right repo for this to work
334
- // TODO: move the repo definition in this plugin when ClusterFormationTasks is removed
335
- String dependency = String .format (
336
- "%s:%s:%s:%s@%s" ,
337
- distribution .getGroup (),
338
- distribution .getArtifactName (),
339
- version ,
340
- distribution .getClassifier (),
341
- distribution .getFileExtension ()
342
- );
343
- rootProject .getDependencies ().add (HELPER_CONFIGURATION_NAME , dependency );
344
- }
341
+ rootProject .getDependencies ().add (
342
+ helperConfiguration .getName (),
343
+ distribution .getGroup () + ":" +
344
+ distribution .getArtifactName () + ":" +
345
+ version +
346
+ (distribution .getClassifier ().isEmpty () ? "" : ":" + distribution .getClassifier ()) + "@" +
347
+ distribution .getFileExtension ());
348
+
345
349
}
350
+
351
+ sync .getInputs ().files (helperConfiguration );
352
+ // NOTE: Gradle doesn't allow a lambda here ( fails at runtime )
353
+ sync .doLast (new Action <Task >() {
354
+ @ Override
355
+ public void execute (Task task ) {
356
+ project .copy (spec ->
357
+ helperConfiguration .getResolvedConfiguration ().getResolvedArtifacts ().forEach (resolvedArtifact -> {
358
+ final FileTree files ;
359
+ File file = resolvedArtifact .getFile ();
360
+ if (file .getName ().endsWith (".zip" )) {
361
+ files = project .zipTree (file );
362
+ } else if (file .getName ().endsWith ("tar.gz" )) {
363
+ files = project .tarTree (file );
364
+ } else {
365
+ throw new IllegalArgumentException ("Can't extract " + file + " unknown file extension" );
366
+ }
367
+
368
+ spec .from (files , s -> s .into (resolvedArtifact .getModuleVersion ().getId ().getGroup ()));
369
+ spec .into (getExtractDir (project ));
370
+ }));
371
+ }
372
+ });
346
373
})));
347
374
}
348
375
0 commit comments